SlideShare a Scribd company logo
1 of 71
嵌入式測試驅動開發
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
Setup

運行
運行

Exercise
Exercise

驗證
驗證

Verify
Verify

單元測試四階段

拆卸
拆卸

Teardown
Teardown
自動化單元測試框架
測試案例 #1 測試案例 #2 ...
測試案例 #1 測試案例 #2

report

測試結果 #1
測試結果 #1

測試框架
測試框架

測試結果 #2
測試結果 #2

產品代碼 ((受測代碼 ))
產品代碼 受測代碼

...

proj/

fun.c

objs/
projTest/

src/

func.o

src/

funTest.c

objs/

func.o
funcTest.o

目標環境

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

產生 bug 更少
除錯時間更短
不會說謊的文件
改善設計
監督進度
內心平靜
嵌入式測試驅動開發
有什麼特別的地方嗎 ?
依賴硬體,浪費時間
Code
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
MyLedDriver.c
#define LED_REGISTER 0x80001234
#define LED_REGISTER 0x80001234
void LedDriver_Set (uint16_t value)
void LedDriver_Set (uint16_t value)
{
{
*((uint16_t *)LED_REGISTER) = value;
*((uint16_t *)LED_REGISTER) = value;
}
}
uint16_t LedDriver_Get (void)
uint16_t LedDriver_Get (void)
{
{
return *((uint16_t *)LED_REGISTER);
return *((uint16_t *)LED_REGISTER);
}
}
LedUser.c
LedUser.c
void TurnOnLed8 (void)
void TurnOnLed8 (void)
{
{
LedDriver_Set (1 << 8);
LedDriver_Set (1 << 8);
}
}
沒有測試把關
再怎麼簡單都可能出錯
TDD 會怎麼做 ?
測試列表
先寫出測試失敗的測試
LedDriverTest.c
LedDriverTest.c
TEST (LedDriver, LedsOffAfterCreate)
TEST (LedDriver, LedsOffAfterCreate)
{
{
uint16_t virtualLeds = 0xffff;
uint16_t virtualLeds = 0xffff;
LedDriver_Create (&virtualLeds);
LedDriver_Create (&virtualLeds);
TEST_ASSERT_EQUAL (0, virtualLeds);
TEST_ASSERT_EQUAL (0, virtualLeds);
}
}
LedDriver.c
LedDriver.c
void LedDriver_Create (uint16_t* address)
void LedDriver_Create (uint16_t* address)
{
{
}
}
Dependence Injection ( 依賴注入 )
用最簡單的方式讓測試通過
LedDriver.c
LedDriver.c
void LedDriver_Create (uint16_t* address)
void LedDriver_Create (uint16_t* address)
{
{
*address = 0;
*address = 0;
}
}

$ make
compiling LedDriver.c
Linking LedDirver_tests
Running LedDriver_tests
.
OK (1 tests, 1 ran, 1 checks, 0 ignored)
再增加一個測試
LedDriverTest.c
LedDriverTest.c
TEST (LedDriver, TurnOnLedOne)
TEST (LedDriver, TurnOnLedOne)
{
{
uint16_t virtualLeds;
uint16_t virtualLeds;
LedDriver_Create (&virtualLeds);
LedDriver_Create (&virtualLeds);
LedDriver_TurnOn (1);
LedDriver_TurnOn (1);
TEST_ASSERT_EQUAL (1, virtualLeds);
TEST_ASSERT_EQUAL (1, virtualLeds);
}
}
LedDriver.c
LedDriver.c
void LedDriver_TurnOn (int ledNumber)
void LedDriver_TurnOn (int ledNumber)
{
{
}
}
寫 hardcode 讓測試通過
LedDriver.c
LedDriver.c
static uint16_t* ledsAddress;
static uint16_t* ledsAddress;
void LedDriver_Create (uint16_t* address)
void LedDriver_Create (uint16_t* address)
{
{
ledsAddress = address;
ledsAddress = address;
*ledsAddress = 0;
*ledsAddress = 0;
}
}
void LedDriver_TurnOn (int ledNumber)
void LedDriver_TurnOn (int ledNumber)
{
{
*ledDriver = 1;
*ledDriver = 1;
}
}
Data Encapsulation ( 資料封裝 )
等等 ! 這不科學啊 ...
hardcode 的實作有問題
增加非當下測試所需的代碼
會降低捕捉各種 bug 的動力
先仿冒再建造
保持小而專注的測試
TDD 像是過河的墊腳石
喔 ... 這就是 TDD 嗎 ?
真正的系統長的像這樣
依賴像一串肉粽
控制輸入 & 監測輸出

直接輸入

直接輸出

間接輸入

間接輸出
斷開魂結、斷開鎖鍊
測試 替身
何時使用測試替身 ?
•
•
•
•
•
•

獨立於硬體
注入難以產生的輸入
加速緩慢的合作者
依賴不穩定的事情
取代未被實現的服務
對於難以配置的事物的依賴
測試替身的替換技術
• 編譯時期,透過 Preprocessor 替換
• 連結時期,透過 Object File 替換
• 執行時期,透過 Function Pointer 替換
Test Stub

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

}
}

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

}
}

time->minuteOfDay = 42;
time->minuteOfDay = 42;
TimeService_SetTime (&time);
TimeService_SetTime (&time);
LONGS_EQUAL (42, FakeTimeService_GetMinute());
LONGS_EQUAL (42, FakeTimeService_GetMinute());
Mock Object
Flash Program 序列圖 - 成功的情形
FlashTest.c
FlashTest.c
TEST (Flash, WriteSucceeds)
TEST (Flash, WriteSucceeds)
{
{
int result = 0;
int result = 0;
MockIO_Expect_Write (0, 0x40);
MockIO_Expect_Write (0, 0x40);
MockIO_Expect_Write (0x1000, 0xBEEF);
MockIO_Expect_Write (0x1000, 0xBEEF);
MockIO_Expect_ReadThenReturn (0, 1<<7);
MockIO_Expect_ReadThenReturn (0, 1<<7);
MockIo_Expect_ReadThenReturn (0, 1<<7);
MockIo_Expect_ReadThenReturn (0, 1<<7);
MockIO_Expect_ReadThenReturn (0x1000, 0xBEEF);
MockIO_Expect_ReadThenReturn (0x1000, 0xBEEF);
Result = Flash_Write (0x1000, 0xBEEF);
Result = Flash_Write (0x1000, 0xBEEF);

}
}

LONG_EQUAL (0, result);
LONG_EQUAL (0, result);
MockIO_Verify_Complete();
MockIO_Verify_Complete();

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

WallClock_SetTime
WallClock_SetTime
WallClock_GetTime
WallClock_GetTime

(Time time);
(Time time);
(void);
(void);

Watch.h
Watch.h
typedef struct WatchStruct Watch;
typedef struct WatchStruct Watch;
void SetTime (Watch* watch, Time time);
void SetTime (Watch* watch, Time time);
Time GetTime (Watch* watch);
Time GetTime (Watch* watch);
用 C 語言實現類別繼承
Watch.h
Watch.h
typedef struct WatchStruct {
typedef struct WatchStruct {
void (*SetTime) (Watch*, Time);
void (*SetTime) (Watch*, Time);
Time (*GetTime) (Watch*);
Time (*GetTime) (Watch*);
} Watch;
} Watch;
DigitalWatch.c
DigitalWatch.c
typedef struct DigitalWatchStruct {
typedef struct DigitalWatchStruct {
Watch* base;
Watch* base;
Time time;
Time time;
} DigitalWatch;
} DigitalWatch;
Watch* DigitalWatch_Create (void) {
Watch* DigitalWatch_Create (void) {
DigitalWatch* self = malloc(sizeof(DigitalWatch));
DigitalWatch* self = malloc(sizeof(DigitalWatch));
self->base->SetTime = mySetTime;
self->base->SetTime = mySetTime;
self->base->GetTime = myGetTime;
self->base->GetTime = myGetTime;
return (Watch*)self;
return (Watch*)self;
}
}

《 interface 》
《 interface 》
Watch
Watch

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

User
User

《 interface 》
《 interface 》
Watch
Watch

Digital
Digital
Watch
Watch

Mechanic
Mechanic
Watch
Watch
SOLID 設計原則
User
User

《 interface 》
《 interface 》
Watch
Watch

Digital
Digital
Watch
Watch

Mechanic
Mechanic
Watch
Watch

Pocket
Pocket
Watch
Watch

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

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

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

《 Refactoring: Improving the Design of Existing Code 》
RefactoredCode.c
RefactoredCode.c
static bool
static bool
{
{
...
...
}
}
static void
static void
{
{
...
...
}
}

isWorkTime (Time* time)
isWorkTime (Time* time)

workHard (Work* work)
workHard (Work* work)

void workInOffice (Time* time, Work* work)
void workInOffice (Time* time, Work* work)
{
{
if (!isWorkTime(time))
if (!isWorkTime(time))
return;
return;
}
}

workHard (work);
workHard (work);
唉呦 不錯 重構這個屌
但實際動手
你肯定會講一句話 ...
砍掉重練比較快
在真實世界裡
我們必須要跟遺留代碼戰鬥
遺留代碼 = 沒有測試的代碼
修改遺留代碼
•
•
•
•
•

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

《 Working Efficiently with Legacy Code 》
測試點
• 接縫 ( 函式呼叫 )
• 全域變數 / 感知變
量
• 除錯輸出
• 嵌入監控
把遺留代碼放到測試框架中
TestLegacyCode.c
TestLegacyCode.c
void addNewLegacyCTest()
void addNewLegacyCTest()
{
{
makeItCompile();
makeItCompile();
makeItLink();
makeItLink();
while (runCrashes()) {
while (runCrashes()) {
findRuntimeDependency();
findRuntimeDependency();
fixRuntimeDependency();
fixRuntimeDependency();
}
}
addMoreLegacyCTests();
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 》

More Related Content

What's hot

The Joy of SciPy
The Joy of SciPyThe Joy of SciPy
The Joy of SciPykammeyer
 
BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully
BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully
BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully BlueHat Security Conference
 
Coran (Riwayet kaloun)
Coran (Riwayet kaloun)Coran (Riwayet kaloun)
Coran (Riwayet kaloun)salah fenni
 
Лекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовЛекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовMikhail Kurnosov
 
تصميم مواقع الويب
تصميم مواقع الويبتصميم مواقع الويب
تصميم مواقع الويبmostfaremo
 
Regex Presentation
Regex PresentationRegex Presentation
Regex Presentationarnolambert
 
Python Libraries and Modules
Python Libraries and ModulesPython Libraries and Modules
Python Libraries and ModulesRaginiJain21
 
أساسيات الكمبيوتر وتقنية المعلومات
أساسيات الكمبيوتر وتقنية المعلوماتأساسيات الكمبيوتر وتقنية المعلومات
أساسيات الكمبيوتر وتقنية المعلوماتHashim Hussein
 
Crash dump analysis - experience sharing
Crash dump analysis - experience sharingCrash dump analysis - experience sharing
Crash dump analysis - experience sharingJames Hsieh
 
Rack documentation template
Rack documentation templateRack documentation template
Rack documentation templateKamran Arshad
 
مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1
مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1
مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1Mahmoud Alfarra
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScriptMegha V
 

What's hot (20)

The Joy of SciPy
The Joy of SciPyThe Joy of SciPy
The Joy of SciPy
 
BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully
BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully
BlueHat v17 || Out of the Truman Show: VM Escape in VMware Gracefully
 
Coran (Riwayet kaloun)
Coran (Riwayet kaloun)Coran (Riwayet kaloun)
Coran (Riwayet kaloun)
 
Dart ( 1 )
Dart ( 1 )Dart ( 1 )
Dart ( 1 )
 
Лекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовЛекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмов
 
Protocol Buffer.ppt
Protocol Buffer.pptProtocol Buffer.ppt
Protocol Buffer.ppt
 
تصميم مواقع الويب
تصميم مواقع الويبتصميم مواقع الويب
تصميم مواقع الويب
 
Regex Presentation
Regex PresentationRegex Presentation
Regex Presentation
 
Android local sockets in native code
Android local sockets in native code Android local sockets in native code
Android local sockets in native code
 
Firewall(linux)
Firewall(linux)Firewall(linux)
Firewall(linux)
 
Dart workshop
Dart workshopDart workshop
Dart workshop
 
Python Libraries and Modules
Python Libraries and ModulesPython Libraries and Modules
Python Libraries and Modules
 
Effective Modern C++
Effective Modern C++Effective Modern C++
Effective Modern C++
 
أساسيات الكمبيوتر وتقنية المعلومات
أساسيات الكمبيوتر وتقنية المعلوماتأساسيات الكمبيوتر وتقنية المعلومات
أساسيات الكمبيوتر وتقنية المعلومات
 
Crash dump analysis - experience sharing
Crash dump analysis - experience sharingCrash dump analysis - experience sharing
Crash dump analysis - experience sharing
 
Python programming : Threads
Python programming : ThreadsPython programming : Threads
Python programming : Threads
 
Rack documentation template
Rack documentation templateRack documentation template
Rack documentation template
 
المحاضرة الرابعة الفيروسات
المحاضرة الرابعة الفيروساتالمحاضرة الرابعة الفيروسات
المحاضرة الرابعة الفيروسات
 
مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1
مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1
مساق الخوارزميات والبرمجة بلغة جافا (1) مفاهيم الخوارزميات ج1
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 

Similar to 2014/02: 嵌入式測試驅動開發

嵌入式測試驅動開發
嵌入式測試驅動開發嵌入式測試驅動開發
嵌入式測試驅動開發hugo lu
 
使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)Max Lai
 
Foundation of software development 1
Foundation of software development 1Foundation of software development 1
Foundation of software development 1netdbncku
 
The way to continuous delivery
The way to continuous deliveryThe way to continuous delivery
The way to continuous deliveryQiao Liang
 
敏捷测试中的工具实现
敏捷测试中的工具实现敏捷测试中的工具实现
敏捷测试中的工具实现drewz lin
 
Legacy code 讀書會 1st (Ch1 - Ch5)
Legacy code 讀書會 1st (Ch1 - Ch5)Legacy code 讀書會 1st (Ch1 - Ch5)
Legacy code 讀書會 1st (Ch1 - Ch5)Fong Liou
 
Java script测试之js unit ut
Java script测试之js unit utJava script测试之js unit ut
Java script测试之js unit utfangdeng
 
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)Rick Hwang
 
LABVIEW的自动化测试之路
LABVIEW的自动化测试之路LABVIEW的自动化测试之路
LABVIEW的自动化测试之路Dean Lee
 
如何在實務上使用TDD來開發 twmvc#12
如何在實務上使用TDD來開發 twmvc#12如何在實務上使用TDD來開發 twmvc#12
如何在實務上使用TDD來開發 twmvc#12twMVC
 
持續交付高品質程式碼 公開版
持續交付高品質程式碼 公開版持續交付高品質程式碼 公開版
持續交付高品質程式碼 公開版Kirk Chen
 
Continuous integration
Continuous integrationContinuous integration
Continuous integrationnetdbncku
 
极速 Angular 开发:效能调校技巧 (ngChina 2019)
极速 Angular 开发:效能调校技巧 (ngChina 2019)极速 Angular 开发:效能调校技巧 (ngChina 2019)
极速 Angular 开发:效能调校技巧 (ngChina 2019)Will Huang
 
twMVC#12 | 如何在實務上使用 TDD 來開發
twMVC#12 | 如何在實務上使用 TDD 來開發twMVC#12 | 如何在實務上使用 TDD 來開發
twMVC#12 | 如何在實務上使用 TDD 來開發twMVC
 
Junit使用指南及作业规范
Junit使用指南及作业规范Junit使用指南及作业规范
Junit使用指南及作业规范dong jiang
 
PHPUnit slide formal
PHPUnit slide formalPHPUnit slide formal
PHPUnit slide formaljameslabs
 
Testing in python 2.7.3
Testing in python 2.7.3Testing in python 2.7.3
Testing in python 2.7.3Wen Liao
 
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013Hazem Saleh
 

Similar to 2014/02: 嵌入式測試驅動開發 (20)

嵌入式測試驅動開發
嵌入式測試驅動開發嵌入式測試驅動開發
嵌入式測試驅動開發
 
使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)使用 Pytest 進行單元測試 (PyCon TW 2021)
使用 Pytest 進行單元測試 (PyCon TW 2021)
 
Foundation of software development 1
Foundation of software development 1Foundation of software development 1
Foundation of software development 1
 
The way to continuous delivery
The way to continuous deliveryThe way to continuous delivery
The way to continuous delivery
 
敏捷测试中的工具实现
敏捷测试中的工具实现敏捷测试中的工具实现
敏捷测试中的工具实现
 
Legacy code 讀書會 1st (Ch1 - Ch5)
Legacy code 讀書會 1st (Ch1 - Ch5)Legacy code 讀書會 1st (Ch1 - Ch5)
Legacy code 讀書會 1st (Ch1 - Ch5)
 
單元測試
單元測試單元測試
單元測試
 
Java script测试之js unit ut
Java script测试之js unit utJava script测试之js unit ut
Java script测试之js unit ut
 
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
從理想、到現實的距離,開啟品味軟體測試之路 - 台灣軟體工程協會 (20220813)
 
LABVIEW的自动化测试之路
LABVIEW的自动化测试之路LABVIEW的自动化测试之路
LABVIEW的自动化测试之路
 
如何在實務上使用TDD來開發 twmvc#12
如何在實務上使用TDD來開發 twmvc#12如何在實務上使用TDD來開發 twmvc#12
如何在實務上使用TDD來開發 twmvc#12
 
PHP 单元测试
PHP 单元测试PHP 单元测试
PHP 单元测试
 
持續交付高品質程式碼 公開版
持續交付高品質程式碼 公開版持續交付高品質程式碼 公開版
持續交付高品質程式碼 公開版
 
Continuous integration
Continuous integrationContinuous integration
Continuous integration
 
极速 Angular 开发:效能调校技巧 (ngChina 2019)
极速 Angular 开发:效能调校技巧 (ngChina 2019)极速 Angular 开发:效能调校技巧 (ngChina 2019)
极速 Angular 开发:效能调校技巧 (ngChina 2019)
 
twMVC#12 | 如何在實務上使用 TDD 來開發
twMVC#12 | 如何在實務上使用 TDD 來開發twMVC#12 | 如何在實務上使用 TDD 來開發
twMVC#12 | 如何在實務上使用 TDD 來開發
 
Junit使用指南及作业规范
Junit使用指南及作业规范Junit使用指南及作业规范
Junit使用指南及作业规范
 
PHPUnit slide formal
PHPUnit slide formalPHPUnit slide formal
PHPUnit slide formal
 
Testing in python 2.7.3
Testing in python 2.7.3Testing in python 2.7.3
Testing in python 2.7.3
 
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
Efficient JavaScript Unit Testing (Chinese Version), JavaOne China 2013
 

More from AgileCommunity

從Agile到Lean Startup:趨勢的軟體開發之旅
從Agile到Lean Startup:趨勢的軟體開發之旅從Agile到Lean Startup:趨勢的軟體開發之旅
從Agile到Lean Startup:趨勢的軟體開發之旅AgileCommunity
 
A journey about how’s high performance teams forming and develop Mobile appli...
A journey about how’s high performance teams forming and develop Mobile appli...A journey about how’s high performance teams forming and develop Mobile appli...
A journey about how’s high performance teams forming and develop Mobile appli...AgileCommunity
 
Agile tour 2014 - Coding Dojo with C# and TDD
Agile tour 2014 - Coding Dojo with C# and TDDAgile tour 2014 - Coding Dojo with C# and TDD
Agile tour 2014 - Coding Dojo with C# and TDDAgileCommunity
 
Project GATE 的敏捷實踐之路
Project GATE 的敏捷實踐之路Project GATE 的敏捷實踐之路
Project GATE 的敏捷實踐之路AgileCommunity
 
Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅
Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅
Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅AgileCommunity
 
More with Less - Agile Meetup 2014/9/18
More with Less - Agile Meetup 2014/9/18More with Less - Agile Meetup 2014/9/18
More with Less - Agile Meetup 2014/9/18AgileCommunity
 
2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美
2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美
2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美AgileCommunity
 

More from AgileCommunity (11)

從Agile到Lean Startup:趨勢的軟體開發之旅
從Agile到Lean Startup:趨勢的軟體開發之旅從Agile到Lean Startup:趨勢的軟體開發之旅
從Agile到Lean Startup:趨勢的軟體開發之旅
 
A journey about how’s high performance teams forming and develop Mobile appli...
A journey about how’s high performance teams forming and develop Mobile appli...A journey about how’s high performance teams forming and develop Mobile appli...
A journey about how’s high performance teams forming and develop Mobile appli...
 
練出精實ux
練出精實ux練出精實ux
練出精實ux
 
Agile tour dojo c++
Agile tour dojo c++Agile tour dojo c++
Agile tour dojo c++
 
Agile tour 2014 - Coding Dojo with C# and TDD
Agile tour 2014 - Coding Dojo with C# and TDDAgile tour 2014 - Coding Dojo with C# and TDD
Agile tour 2014 - Coding Dojo with C# and TDD
 
Project GATE 的敏捷實踐之路
Project GATE 的敏捷實踐之路Project GATE 的敏捷實踐之路
Project GATE 的敏捷實踐之路
 
Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅
Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅
Agile Tour Taipei 2014 - 趨勢科技的 agile 之旅
 
2014/10/3 Ux in china
2014/10/3 Ux in china2014/10/3 Ux in china
2014/10/3 Ux in china
 
More with Less - Agile Meetup 2014/9/18
More with Less - Agile Meetup 2014/9/18More with Less - Agile Meetup 2014/9/18
More with Less - Agile Meetup 2014/9/18
 
Coding dojo初體驗
Coding dojo初體驗Coding dojo初體驗
Coding dojo初體驗
 
2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美
2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美
2013/10: Q con shanghai2013-davidko-如何利用 kanban让 scrum 更完美
 

2014/02: 嵌入式測試驅動開發

Editor's Notes

  1. Bug 是什麼? bug 是應注意,而未注意的錯誤。
  2. 許願式則是測試 -&gt; 寫碼 -&gt; 重構,就前兩步驟順序互換。如果你先許願,然後去實現它。你會發現結果只會實現你許過的願望,不會發生實現你沒許過的願望。以軟體開發術語來說,就是花最少力氣完成目標程式的開發,剛剛好符合單元測試的&quot;規範&quot;。絕對不會過度設計(over design),而且寫出來的目標程式碼 100% 可以被測試,測試涵蓋率百分百。
  3. 增量式軟體開發技術、先有測試再寫程式 測試要小、能自動
  4. 測試是對需求的理解 測試是功能許下的承諾 測試驗證新功能可運作 測試保證舊功能沒被破壞
  5. 易於運行的測試: 獨立、可重複、自我檢驗、全自動 測試四階段 建立: 創建測試的前置條件 運行: 對系統進行操作 驗證: 檢查預期的輸出 拆卸: 把被測系統恢復到測試前的初始狀態
  6. 產生較少的 bug 除錯時間變短 產生可執行的規格 永遠有最新的文件 改善設計 監督進度
  7. 硬體遲遲沒準備好,壓縮軟體開發時程 硬體昂貴、資源稀少,開發人員空等待 硬體也會有 bug,除錯更加困難 建構目標系統時間漫長 上傳(燒錄)韌體時間漫長 Cross-compiler 昂貴,授權數量有限
  8. TDD 對嵌入式開發的幫助: 硬體可用前或硬體很貴很稀少,通過獨立於硬體的方式校驗產品代碼 開發環境除錯,減少編譯、上傳的次數與時間 減少在目標硬體的除錯時間 隔離軟硬體交互影響 軟硬體解耦合有助於改善設計
  9. TDD 微循環 - 運行頻繁,幾分鐘一次。代碼與測試都在這開發。可做靜態分析。 編譯器相容性測試 - 移植性問題 (header file、library、語言工具)。採用新語言特性、函式庫才驗證。 評估版上運行單元測試 - 驗證編譯後的代碼在本地開發系統和目標處理器上行為一致。CI 的一部分,每天運行。 目標硬體運行單元測試 - 挑戰目標硬體有限資源 (記憶體)。可能需要批次測試不同測試套件。 目標硬體運行驗收測試 - 手動驗證不能完全自動化的測試
  10. Unity 用 C 實現的自動化測試框架 用 Ruby Script 解決測試安裝問題 CppUTest 用 C/C++ 實現的自動化測試框架 不需理解 C++ 附帶 Ruby Script 可將 CppUTest 測試轉換成 Unity 測試
  11. 使用者點亮第八顆燈,卻清除了其他燈號的設定
  12. 測試列表由需求衍生而來 測試列表定義你對需要完成功能的最好理解
  13. * 依賴注入
  14. 先測試介面,在測試內部實現
  15. 但是 測試是對的 Bob Martin TDD三條原則 除非是讓一個失敗的單元測試通過,否則不要寫產品代碼 不要寫比足以失敗更多的單元測試,建構失敗也可以 不要寫比足以讓單元測試通過更多的產品代碼
  16. 剛接觸TDD的人會感到困惑 增加不是現在測試所需要的代碼,會降低寫讓代碼不產生bug所需的所有測試 有測試之前增加代碼會增加複雜度
  17. 增量式前進 先仿冒在建造 - 一旦去仿冒比正確實做更麻煩時,就造出真正的東西 保持小而專注的測試 綠燈之後要重構
  18. Test automation is about verifying the behavior of the SUT. The actual behavior of the SUT can be verified in two ways. Verify the states of various objects affected by the SUT Verify the interactions between SUT and its DOCs 檢驗狀態 In State Verification, we assert that the SUT and any objects it returns are in the expected state after we have exercised the SUT. We “pay no attention to the man behind the curtain.” 檢驗行為 In Behavior Verification, we focus our assertions on the indirect outputs (outgoing interfaces) of the SUT. This typically involves replacing the DOC with something that facilitates observing and verifying the outgoing calls. 1. We can verify the states of various objects affected by the SUT by extracting each state using an observation point and using assertions to compare it to the expected state. 2. We can verify the behavior of the SUT directly by using observation points inserted between the SUT and its depended-on component (DOC) to monitor its interactions (in the form of the method calls it makes) and comparing those method calls with what we expected.
  19. 注入難以產生的輸入 &gt;&gt; 觸發不太可能執行到的路徑 加速緩慢的合作者 &gt;&gt; 資料庫、網路、慢速儲存裝置 依賴不穩定的事情 &gt;&gt; 時鐘 對開發事物的依賴 &gt;&gt; 有機會探索CUT對於現在未實現的服務的需求 對於難以配置的事物的依賴 &gt;&gt; 資料庫
  20. Using a Test Stub as a control point for indirect inputs. One way to use a control point to inject indirect inputs into the SUT is to install a Test Stub in place of the DOC. Before exercising the SUT, we tell the Test Stub what it should return to the SUT when it is called. This strategy allows us to force the SUT through all its code paths.
  21. Using a Test Spy as an observation point for indirect outputs of the SUT. One way to implement Behavior Verification is to install a Test Spy in place of the target of the indirect outputs. After exercising the SUT, the test asks the Test Spy for information about how it was used and compares that information to the expected behavior using assertions.
  22. Using a Mock Object as an observation point for indirect outputs of the SUT. Another way to implement Behavior Verification is to install a Mock Object in place of the target of the indirect outputs. As the SUT makes calls to the DOC, the Mock Object uses assertions to compare the actual calls and arguments with the expected calls and arguments.
  23. 可測性 (Testable)是什麼? 什麼樣的代碼才有可測性 模組的概念 - 系統中一個完備的部份,有明確定義的介面 抽象資料類型(ADT)中,模組的數據被當成私有成員對待 (封裝)
  24. 不要把選擇邏輯分佈在系統各處,而是只在一處做選擇,並且將系統配置成支持這種情形 (工廠模式)
  25. 壞名字、眼花撩亂的布林運算、邪惡的嵌套、依戀情結
  26. 解決軟體開發的技術債
  27. 壞名字、眼花撩亂的布林運算、邪惡的嵌套、依戀情結
  28. 沒有測試的代碼是壞代碼。無論寫得多好,多美,多麼物件導向或封裝良好。有了測試,才能快速和可驗證地改變代碼。沒有測試,實際上無法知道代碼倒底變好還是變壞。
  29. 測試點 - 發現改動點後,考慮如何測試它。在哪一點上面能更自然地感知代碼發生了什麼,代碼又是從哪裡得到輸入的。 斷開依賴 - 把遺留代碼放入測試框架中,或是得到某些測試點的訪問,必須斷開依賴。 寫測試 - 有了測試點,就能寫一些測試來識別及保護遺留代碼的行為。
  30. 接縫 - 函式呼叫在代碼不同部分形成了接縫。接縫就是你可以改變程序的行為,卻不用修改那個位置。 可以使用測試替身來”監視”傳給合作者數據的地方,讓測試可以確保被測試代碼給合作者傳去正確的指令。
  31. 讓它能編譯 - 為測試函式提供數據結構和參數 (隨意使用空指標和簡單數值) ,增加 #include 讓測試文件可以編譯 讓它能連結 - 處理未解決的外部符號 (unresolved external symbol) ,連結部份產品代碼或使用測試替身 運行會崩潰 - 因為之前傳入未初始化或不恰當初始化的數據 找到運行時依賴 - 使用 debugger 找到崩潰點 (非法訪問記憶體) 修正運行時依賴 - 初始化數據、函式指標