SlideShare ist ein Scribd-Unternehmen logo
1 von 71
Downloaden Sie, um offline zu lesen
嵌入式測試驅動開發
Hugo
2/13/2014
熟悉的開發方式
先寫程式,再寫測試

bug

Test-After Development (TAD)
問題是...
沒出錯不知道哪裡有 bug
bug 小時候放著不管
長大很恐怖
有什麼方法...
能盡早把 bug 出來?
先寫測試

bug,再寫程式

Test-Driven Development (TDD)
Test
Driven
Development
測試驅動開發
TDD 循環
加 紅燈:增 一個運行失敗,
甚至無法 譯的測試
加 綠燈:快 修改, 做能讓
測試 過的工作
加 黃燈:重構,移除重複改進
代碼可讀性

Test Driven Development: By Example
測試 是 TDD 的關鍵
建立

運行

驗證

拆卸

Setup

Exercise

Verify

Teardown

單元測試四階段
自動化單元測試框架
測試案例 #1

測試案例#2

...

report

測試結果 #1

測試框架
產品代碼 ( 測代碼)

proj/

測試結果 #2
...

fun.c

objs/
projTest/

src/

func.o

src/

funTest.c

objs/

func.o
funcTest.o

目標環境

測試環境
TDD 的好處
加
加
加
加
加
加

產生 bug 更少
除錯時間更短
不會說謊的文件
改善設計
監督進度
心平靜
嵌入式測試驅動開發
有什麼特別的地方嗎?
依賴硬體,浪費時間
Code

單元測試

運行系統

開發環境

目標環境

雙目標開發 - 解開硬體的依賴
嵌入式 TDD 循環
階段一

階段二

階段三

階段四

階段五

開發環境
TDD

交叉 譯
相容測試

評估版
單元測試

目標硬體
單元測試

目標硬體
驗收測試

很頻繁

不頻繁

Test-Driven Development for Embedded C
嵌入式驅動開發工具
加 Unity
– C 語言自動化測試框架
– 用 Ruby Script 安裝測試

加 CppUTest
– C/C++自動化測試框架
– 用 Ruby Script 測試轉
換 Unity 測試

Unity http://throwtheswitch.org/, CppUTest http://cpputest.github.io/
範例 - 開發 LED 驅動程式
玩意

10行程式就搞定了
麼簡單還需要測試嗎?
MyLedDriver.c
#define LED_REGISTER 0x80001234
void LedDriver_Set (uint16_t value)
{
*((uint16_t *)LED_REGISTER) = value;
}
uint16_t LedDriver_Get (void)
{
return *((uint16_t *)LED_REGISTER);
}
LedUser.c

void TurnOnLed8 (void)
{
LedDriver_Set (1 << 8);
}
沒有測試把關
再怎麼簡單都可能出錯
TDD 會怎麼做?
測試列表
先寫出測試失敗的測試
LedDriverTest.c
TEST (LedDriver, LedsOffAfterCreate)
{
uint16_t virtualLeds = 0xffff;
LedDriver_Create (&virtualLeds);
TEST_ASSERT_EQUAL (0, virtualLeds);
}

LedDriver.c
void LedDriver_Create (uint16_t* address)
{
}
Dependence Injection (依賴注入)
用最簡單的方式讓測試 過
LedDriver.c
void LedDriver_Create (uint16_t* address)
{
*address = 0;
}

$ make
compiling LedDriver.c
Linking LedDirver_tests
Running LedDriver_tests
.
OK (1 tests, 1 ran, 1 checks, 0 ignored)
再增

一個測試

LedDriverTest.c
TEST (LedDriver, TurnOnLedOne)
{
uint16_t virtualLeds;
LedDriver_Create (&virtualLeds);
LedDriver_TurnOn (1);
TEST_ASSERT_EQUAL (1, virtualLeds);
}

LedDriver.c
void LedDriver_TurnOn (int ledNumber)
{
}
寫 hardcode 讓測試 過
LedDriver.c
static uint16_t* ledsAddress;
void LedDriver_Create (uint16_t* address)
{
ledsAddress = address;
*ledsAddress = 0;
}
void LedDriver_TurnOn (int ledNumber)
{
*ledDriver = 1;
}

Data Encapsulation (資料封裝)
等等! 不科學啊...
hardcode 的實作有問題
增 非當下測試所需的代碼
會降低捕捉各種 bug 的動力
先仿冒再建
保持小而 注的測試
TDD 像是過河的墊腳石
喔...

就是 TDD 嗎?
真正的系統長的像

樣
依賴像一串肉粽
控制輸入 & 監測輸出

直接輸入

直接輸出

間接輸出

間接輸入
斷開魂結

斷開鎖鍊
測試 替身
何時使用測試替身?
加
加
加
加
加
加

獨立於硬體
注入 以產生的輸入
慢的合作者
依賴不穩定的事情
代未被實現的服務
對於 以配置的事物的依賴
測試替身的替換

術

加 譯時期,透過 Preprocessor 替換
加 連結時期,透過 Object File 替換
加 執行時期,透過 Function Pointer 替換
Test Stub

xUnit Test Patterns: Refactoring Test Code
FakeTimeService.c
static int theMinute;
void FakeTimeService_SetMinute (int minute)
{
theMinute = minute;
}
void TimeService_GetTime (Time* time)
{
time->minuteOfDay = theMinute;
}
FakeTimeServiceTest.c
TEST (FakeTimeService, Set)
{
Time time;

FakeTimeService_SetMinute (42);
TimeService_GetTime (&time);
LONGS_EQUAL (42, time.minuteOfDay);
}
Test Spy
FakeTimeService.c
static int theMinute;
int FakeTimeService_GetMinute (void)
{
return theMinute;
}
void TimeService_SetDay (Time* time)
{
theMinute = time->minuteOfDay;
}
FakeTimeServiceTest.c
TEST (FakeTimeService, Get)
{
Time time;

time->minuteOfDay = 42;
TimeService_SetTime (&time);
LONGS_EQUAL (42, FakeTimeService_GetMinute());
}
Mock Object
Flash Program 序列圖 -

的情形
FlashTest.c
TEST (Flash, WriteSucceeds)
{
int result = 0;
MockIO_Expect_Write (0, 0x40);
MockIO_Expect_Write (0x1000, 0xBEEF);
MockIO_Expect_ReadThenReturn (0, 1<<7);
MockIo_Expect_ReadThenReturn (0, 1<<7);
MockIO_Expect_ReadThenReturn (0x1000, 0xBEEF);
Result = Flash_Write (0x1000, 0xBEEF);
LONG_EQUAL (0, result);
MockIO_Verify_Complete();

}

CMock http://throwtheswitch.org/, CppUMock http://cpputest.github.io/
怎樣才算好設計?
可測性 可讀性 可維護性
借用物件導向的設計原則
用 C 語言實現資料封裝
WallClock.h
void WallClock_SetTime (Time time);
Time WallClock_GetTime (void);

Watch.h
typedef struct WatchStruct Watch;
void SetTime (Watch* watch, Time time);
Time GetTime (Watch* watch);
用 C 語言實現類別繼
Watch.h
typedef struct WatchStruct {
void (*SetTime) (Watch*, Time);
Time (*GetTime) (Watch*);
} Watch;

interface
Watch

DigitalWatch.c

typedef struct DigitalWatchStruct {
Watch* base;
Time time;
} DigitalWatch;
Watch* DigitalWatch_Create (void) {
DigitalWatch* self = malloc(sizeof(DigitalWatch));
self->base->SetTime = mySetTime;
self->base->GetTime = myGetTime;
return (Watch*)self;
}

Digital
Watch
用 C 語言實現類別多型
User.c
void doSetTime (Watch* watch, Time time) {
watch->SetTime (watch, time);
}

User

interface
Watch

DigitalWatch.c
static void mySetTime (Watch* watch, Time time)
{
DigitalWatch* self = (DigitalWatch*)watch;
self->time = time;
}
MechanicWatch.c
static void mySetTime (Watch* watch, Time time)
{
MechanicWatch* self = (MechanicWatch*)watch;
self->time = time;
}

Digital
Watch

Mechanic
Watch
SOLID 設計原則
User

interface
Watch

Digital
Watch

Mechanic
Watch

Pocket
Watch

SRP 單一職責
OCP 開放封閉
LSP 替換原則
ISP 介面分
DIP 依賴 轉

Agile Software Development, Principle, Patterns, and Practices
隨著代碼不斷增
系統架構變得越來越混亂
代碼的壞味道
加
加
加
加
加
加
加
加
加
加
加

重複代碼
壞名字
義大利麵式代碼
長函式
眼花撩亂的布林運算
重複的 switch/case
邪惡的嵌套
依戀情結
參數太多
注釋 注釋掉的代碼
條件 譯
CodeSmells.c
void foobar (Time* time, Work* work)
{
if (work->item != NULL) {
Day day = time->dayOfWeek;
int min = time->minuteOfDay;
if ((day >= MONDAY && day <= FRIDAY) &&
((min >= 9*60 && min <= 12*60) ||
(min >= 13*60 && min <= 18*60)) {
if (work->type == CODING)
doCode (work->item);
else
doDebug (work->item);
// doSomethingImportant ();
}
}
}
重構是
在不改變當前外部行為的條件下,
對現有代碼進行修改的過程

Refactoring: Improving the Design of Existing Code
RefactoredCode.c
static bool isWorkTime (Time* time)
{
...
}
static void workHard (Work* work)
{
...
}
void workInOffice (Time* time, Work* work)
{
if (!isWorkTime(time))
return;
workHard (work);

}
唉呦 不錯 重構

個屌
但實際動手
你肯定會講一句話...
砍掉重練比較快
在真實世界裡
必須要跟遺留代碼戰鬥
遺留代碼 = 沒有測試的代碼
修改遺留代碼
•
•
•
•
•

發現改動點
到測試點
斷開依賴
寫測試
改動和重構

Working Efficiently with Legacy Code
測試點
加 接縫 (函式呼 )
加 域變數/感知變量
加 除錯輸出
加 嵌入監控
把遺留代碼放到測試框架中
TestLegacyCode.c
void addNewLegacyCTest()
{
makeItCompile();
makeItLink();
while (runCrashes()) {
findRuntimeDependency();
fixRuntimeDependency();
}
addMoreLegacyCTests();
}
TDD 聽來不錯,但是...
不知怎麼開始?
先來場 Coding Dojo 吧
參考資料
Test-Driven Development for Embedded C
Test Driven Development: By Example
xUnit Test Patterns: Refactoring Test Code
Refactoring: Improving the Design of Existing Code
Working Efficiently with Legacy Code
Agile Software Development, Principle, Patterns, and Practices
Design Patterns for Embedded Systems in C: An Embedded
Software Engineering Toolkit

Weitere ähnliche Inhalte

Was ist angesagt?

大家來學GObject
大家來學GObject大家來學GObject
大家來學GObject
Shu-Yu Fu
 

Was ist angesagt? (20)

Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11
 
TMUX Rocks!
TMUX Rocks!TMUX Rocks!
TMUX Rocks!
 
[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로
 
Advance Malware CnC by Avkash k and dhawal shah
Advance Malware CnC by Avkash k and dhawal shahAdvance Malware CnC by Avkash k and dhawal shah
Advance Malware CnC by Avkash k and dhawal shah
 
Advanced C - Part 1
Advanced C - Part 1 Advanced C - Part 1
Advanced C - Part 1
 
Unit testing with JUnit
Unit testing with JUnitUnit testing with JUnit
Unit testing with JUnit
 
大家來學GObject
大家來學GObject大家來學GObject
大家來學GObject
 
DockerとKubernetesをかけめぐる
DockerとKubernetesをかけめぐるDockerとKubernetesをかけめぐる
DockerとKubernetesをかけめぐる
 
Vim Rocks!
Vim Rocks!Vim Rocks!
Vim Rocks!
 
Acceptance Test Driven Development and Robot Framework
Acceptance Test Driven Development and Robot FrameworkAcceptance Test Driven Development and Robot Framework
Acceptance Test Driven Development and Robot Framework
 
Clean Code
Clean CodeClean Code
Clean Code
 
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
 
GNU ld的linker script簡介
GNU ld的linker script簡介GNU ld的linker script簡介
GNU ld的linker script簡介
 
VerilatorとSystemC
VerilatorとSystemCVerilatorとSystemC
VerilatorとSystemC
 
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM SystemsXPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
 
OPTEE on QEMU - Build Tutorial
OPTEE on QEMU - Build TutorialOPTEE on QEMU - Build Tutorial
OPTEE on QEMU - Build Tutorial
 
nodeMCU IOT教學03 - NodeMCU導論
nodeMCU IOT教學03 - NodeMCU導論nodeMCU IOT教學03 - NodeMCU導論
nodeMCU IOT教學03 - NodeMCU導論
 
[嵌入式系統] 嵌入式系統進階
[嵌入式系統] 嵌入式系統進階[嵌入式系統] 嵌入式系統進階
[嵌入式系統] 嵌入式系統進階
 
Character drivers
Character driversCharacter drivers
Character drivers
 
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
 

Andere mochten auch

2014/02: 嵌入式測試驅動開發
2014/02: 嵌入式測試驅動開發2014/02: 嵌入式測試驅動開發
2014/02: 嵌入式測試驅動開發
AgileCommunity
 
初探行为驱动开发(Bdd)
初探行为驱动开发(Bdd)初探行为驱动开发(Bdd)
初探行为驱动开发(Bdd)
YuLei Liao
 
Test driven development in C
Test driven development in CTest driven development in C
Test driven development in C
Amritayan Nayak
 

Andere mochten auch (6)

關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......
 
2014/02: 嵌入式測試驅動開發
2014/02: 嵌入式測試驅動開發2014/02: 嵌入式測試驅動開發
2014/02: 嵌入式測試驅動開發
 
Coding dojo初體驗
Coding dojo初體驗Coding dojo初體驗
Coding dojo初體驗
 
初探行为驱动开发(Bdd)
初探行为驱动开发(Bdd)初探行为驱动开发(Bdd)
初探行为驱动开发(Bdd)
 
認試軟體測試的世界 & TDD/BDD 入門
認試軟體測試的世界 & TDD/BDD 入門認試軟體測試的世界 & TDD/BDD 入門
認試軟體測試的世界 & TDD/BDD 入門
 
Test driven development in C
Test driven development in CTest driven development in C
Test driven development in C
 

Ähnlich wie 嵌入式測試驅動開發

Foundation of software development 1
Foundation of software development 1Foundation of software development 1
Foundation of software development 1
netdbncku
 
Clojure cnclojure-meetup
Clojure cnclojure-meetupClojure cnclojure-meetup
Clojure cnclojure-meetup
sunng87
 
GTest交流与经验总结
GTest交流与经验总结GTest交流与经验总结
GTest交流与经验总结
coderzh
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojects
George Ang
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source Projects
George Ang
 
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Gelis Wu
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题
yiditushe
 

Ähnlich wie 嵌入式測試驅動開發 (20)

Android 智慧型手機程式設計
Android 智慧型手機程式設計Android 智慧型手機程式設計
Android 智慧型手機程式設計
 
如何在實務上使用TDD來開發 twmvc#12
如何在實務上使用TDD來開發 twmvc#12如何在實務上使用TDD來開發 twmvc#12
如何在實務上使用TDD來開發 twmvc#12
 
twMVC#12 | 如何在實務上使用 TDD 來開發
twMVC#12 | 如何在實務上使用 TDD 來開發twMVC#12 | 如何在實務上使用 TDD 來開發
twMVC#12 | 如何在實務上使用 TDD 來開發
 
Foundation of software development 1
Foundation of software development 1Foundation of software development 1
Foundation of software development 1
 
第1章概述
第1章概述第1章概述
第1章概述
 
Clojure cnclojure-meetup
Clojure cnclojure-meetupClojure cnclojure-meetup
Clojure cnclojure-meetup
 
GTest交流与经验总结
GTest交流与经验总结GTest交流与经验总结
GTest交流与经验总结
 
Programming in Objective-C
Programming in Objective-CProgramming in Objective-C
Programming in Objective-C
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojects
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source Projects
 
用 Drone 打造 輕量級容器持續交付平台
用 Drone 打造輕量級容器持續交付平台用 Drone 打造輕量級容器持續交付平台
用 Drone 打造 輕量級容器持續交付平台
 
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
 
在B2B硬體產業運用 Agile 與 DevOps 的實務與心法
在B2B硬體產業運用 Agile 與 DevOps 的實務與心法在B2B硬體產業運用 Agile 與 DevOps 的實務與心法
在B2B硬體產業運用 Agile 與 DevOps 的實務與心法
 
漫談 Source Control Management
漫談 Source Control Management漫談 Source Control Management
漫談 Source Control Management
 
一個微信專案從0到000的效能調教
一個微信專案從0到000的效能調教一個微信專案從0到000的效能調教
一個微信專案從0到000的效能調教
 
面向模式的软件体系架构
面向模式的软件体系架构面向模式的软件体系架构
面向模式的软件体系架构
 
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
 
使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题
 
[DevOpsDays] 硬體產業的DevOps導入與實踐 - 以工控產業為例
[DevOpsDays] 硬體產業的DevOps導入與實踐 - 以工控產業為例[DevOpsDays] 硬體產業的DevOps導入與實踐 - 以工控產業為例
[DevOpsDays] 硬體產業的DevOps導入與實踐 - 以工控產業為例
 

Mehr von hugo lu

Testing in swift
Testing in swiftTesting in swift
Testing in swift
hugo lu
 
The linux networking architecture
The linux networking architectureThe linux networking architecture
The linux networking architecture
hugo lu
 

Mehr von hugo lu (12)

WSO2 IoTS Device Manufacturer Guide
WSO2 IoTS Device Manufacturer GuideWSO2 IoTS Device Manufacturer Guide
WSO2 IoTS Device Manufacturer Guide
 
Dev ops 簡介
Dev ops 簡介Dev ops 簡介
Dev ops 簡介
 
Sql injection 幼幼班
Sql injection 幼幼班Sql injection 幼幼班
Sql injection 幼幼班
 
Sql or no sql, that is the question
Sql or no sql, that is the questionSql or no sql, that is the question
Sql or no sql, that is the question
 
Continuous integration
Continuous integrationContinuous integration
Continuous integration
 
Swift 2.0 的新玩意
Swift 2.0 的新玩意Swift 2.0 的新玩意
Swift 2.0 的新玩意
 
精實執行工作坊
精實執行工作坊精實執行工作坊
精實執行工作坊
 
Testing in swift
Testing in swiftTesting in swift
Testing in swift
 
畫出商業模式
畫出商業模式畫出商業模式
畫出商業模式
 
The linux networking architecture
The linux networking architectureThe linux networking architecture
The linux networking architecture
 
精實軟體度量
精實軟體度量精實軟體度量
精實軟體度量
 
看板實驗室
看板實驗室看板實驗室
看板實驗室
 

Kürzlich hochgeladen

10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
PUAXINYEEMoe
 
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
michaelell902
 
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
PUAXINYEEMoe
 

Kürzlich hochgeladen (9)

taibif_資料標準概念介紹_20240509_20240509_20340509.pdf
taibif_資料標準概念介紹_20240509_20240509_20340509.pdftaibif_資料標準概念介紹_20240509_20240509_20340509.pdf
taibif_資料標準概念介紹_20240509_20240509_20340509.pdf
 
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdftaibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
 
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
 
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
 
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
 
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
 
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade SixMath Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
 
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
 
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
 

嵌入式測試驅動開發