TDD驅動測試開發
測試重要性
越早進行測試,未來負擔越小!測試是永遠避不了的,透過單元測試可完成持續性遞迴測試,保證業務邏輯正確,測試推到後面去辛苦遽增,測試範圍大增 ex: 單元測試:可以很明確簡單完成測試(僅測關鍵業務邏輯) 整合測試:基本上很困難透過測試(需依賴外部來源)
測試永遠少不了,測試越早執行負擔越小,工程師常常想反正我寫完還是要測試,那時候在手動測試即可,
前言
TDD屬於單元測試測試類型(僅測試該程式功能),當測試service時, 不須考慮model(資料/外部),僅測試service,常常使用假的替代(策略模型),不依賴外部資源,表示在任何環境下都可以執行!

在一般專案中常常發現,幾乎沒發現有撰寫程式碼一般原因如下:
寫不出來(沒人教過)
有人教過,但是寫錯方式
前輩說寫測是很花時間沒有效益。
寫測試花費時間太多,可成會多花一倍時間?
AAA概念
Arrange: 先設定我們在這次測試中,所預期的結果(個案)
Act: 就是我們想要測試的 function 或 method
Assert: 確認在 Action 發生後,確認在執行了想要測試 function 或 method 後,的確符合我們在 Arrange 階段設定的目標
A [] B >C
步驟
撰寫測試目的與優點
從測試出發,才比較容易寫出可以測試之程式
容易真正關鍵核心業務
不依賴外部系統、來源或資料庫。
才能滿足CI/CD需求(每次打包之程式都有經過驗證確認)
使用TDD撰寫測試程式
重測試開始寫,因對應物件尚未建立所以無法編譯
完成程式可編譯即可
撰寫通過個案程式
重構原有程式
每次修改都重新執行確認保持綠燈(程式有驗證)
graph LR;
red(新增測試個案-編譯不過)-->test(測試剛剛新個案-紅燈);
test --> green(撰寫可以通過之程式-綠燈)
green --> refac(重構)
refac --> red
經典案例 Tennis Kata
一個完整的網球比賽分成:
網球每局的記分方法:「零」(love)、「十五」(fifteen)、「三十」(thirty)和「四十」(forty)。記分時,發球手的得分在前。因此「30比0」的意思是,發球手贏得2分,而接球手還未得分。
0
0
love:love
0
15
love:fifteen
0
40
love:forty







簡單重構

更貼近進階案例
規則
建立使用者帳號: 1.帳號不存在 2.帳號長度6碼 3.密碼包含英文更數字
sequenceDiagram
participant A as UserCreated (Bord)
participant B as UserGateWay(外部資源、資料庫、IO資料流)
A->>B: 1. exsit
B->>A: 2. 存在/不存在
A->>B: 3.save
個案
1.建立帳號成功案例(CreateUser)
帳號:A1234567
密碼:7654321A
<font color="#660000">
不存在</font><br />

package tdd;
public class UserCreated {
public CreateUserReponse createUser(CreateUserRequest createUserReques) {
// TODO Auto-generated method stub
return null;
}
}


public class UserCreated {
private UserGateWay userGateWay;
public UserService(UserGateWay userGateWay) {
super();
this.userGateWay = userGateWay;
}
public CreateUserReponse createUser(CreateUserRequest createUserReques) {
String account = createUserReques.getAccount();
String passowd = createUserReques.getPassowd();
boolean exsit = this.userGateWay.exsit(account);
CreateUserReponse createUserReponse = new CreateUserReponse();
if (!exsit) {
boolean isMore6 = account.length() > 6;
boolean isPasswordOk = this.checkPasswor(passowd);
if (isMore6 && isPasswordOk) {
User user = new User(account, passowd);
createUserReponse.setUser(user);
userGateWay.save(user);
}
}
return createUserReponse;
}
private boolean checkPasswor(String passowd) {
boolean isDigit = false;
boolean isLetter = false;
for (int i = 0; i < passowd.length(); i++) {
if (Character.isDigit(passowd.charAt(i))) {
isDigit = true;
}
if (Character.isLetter(passowd.charAt(i))) {
isLetter = true;
}
}
return isDigit && isLetter;
}
}
public class UserCreated {
private static final String A1234567 = "A1234567";
/**
* 建立帳號成功案例 - 帳號:A1234567 - 密碼:7654321A - 不存在
*/
@Test
public void create_sucesfully() {
UserGateWay userGateWay = Mockito.mock(UserGateWay.class);
Mockito.when(userGateWay.exsit(A1234567)).thenReturn(false);
UserService userService = new UserService(userGateWay);
CreateUserRequest createUserReques = new CreateUserRequest(A1234567, "7654321A");
CreateUserReponse reponse = userService.createUser(CreateUserReques);
assertTrue(reponse.getUser() != null);
}
}
2.建立帳號失敗案例
帳號:A1234567
密碼:7654321A
<font color="#660000">
存在</font><br />
/**
* 建立帳號失敗案例 - 帳號:A1234567 - 密碼:7654321A - 不存在
*/
@Test(expected = TddBusinessException.class)
public void create_fail_exist_account() {
UserGateWay userGateWay = Mockito.mock(UserGateWay.class);
Mockito.when(userGateWay.exsit(A1234567)).thenReturn(true);
UserService userService = new UserService(userGateWay);
CreateUserRequest createUserReques = new CreateUserRequest(A1234567, "7654321A");
userService.createUser(CreateUserReques);
}
3.建立帳號失敗案例
帳號:A
密碼:7654321A
<font color="#660000">
不在再</font><br />
/**
* 3.建立帳號失敗案例 - 帳號:A - 密碼:7654321A - 不在再</font><br />
*/
@Test(expected = TddBusinessException.class)
public void create_fail_account_less_6() {
UserGateWay userGateWay = Mockito.mock(UserGateWay.class);
Mockito.when(userGateWay.exsit("A")).thenReturn(false);
UserService userService = new UserService(userGateWay);
CreateUserRequest CreateUserReques = new CreateUserRequest("A", "7654321A");
userService.createUser(CreateUserReques);
}

MAVEN專案deploay
mvn clean pacakge
Last updated
Was this helpful?