?TDD測試演示
?TDD算柳,是踢蛋蛋,啊不台谢,是測試驅(qū)動開發(fā)的簡稱
那什么是TDD寻狂,其實可以粗淺的理解為,先寫測試類朋沮。
詳細(xì)可以百度蛇券。
TDD的實現(xiàn)流程可以大概下圖表示:
?我們先看下下面這個需求。
模擬小白和小強打架樊拓,小白和小強有普通攻擊和大招纠亚,還有狀態(tài)。
在打架之后筋夏,小白和小強的狀態(tài)會改變(狀態(tài)簡化為只有血量)蒂胞。
小白的A為普通攻擊會扣5滴血,B為大招回自己10滴血条篷,扣對方10滴血啤誊。小白最大血量120岳瞭。
小強的A為普通攻擊會扣6滴血,B為大招傷自己5滴血蚊锹,扣對方30滴血。小強最大血量100稚瘾。
?我們先上手一個測試類牡昆。(代碼為java,你們可以補充其他語言的例子)
首先摊欠,要測試這小白和小強打架丢烘,肯定先要有個小白和小強,然后他們打架些椒。
這個打架的執(zhí)行用一個業(yè)務(wù)類來執(zhí)行播瞳,叫Fight。
所以我們先寫一個測試類叫FightTest免糕,為Fight這個業(yè)務(wù)類編寫測試赢乓,專門用來測試Fight
測試先行,我們就要先想Fight類中有什么石窑。這個業(yè)務(wù)類應(yīng)該有一個方法Fight.action牌芋。這個方法是打架的動作。
Fight.action這個方法傳入兩個Role(角色)和一個代表動作的字符 action
這個Fight.action可以用來執(zhí)行小白和小強打架的動作
然后要有兩個角色Role松逊,一個小白LittleWhite躺屁,一個小強LitterStrong。實現(xiàn)這兩個對象
所以我們直接寫出兩個對象new出來经宏,然后寫出Fight.action方法的測試用例
所以我們要寫一個Fight測試用例(諾犀暑,TDD就是先寫測試)我們要思考怎么測試Fight.action才是符合需求的。
讓測試結(jié)果符合需求烁兰。
由于我們需求是讓攻擊之后角色狀態(tài)改變耐亏,所以我們要測試每一種攻擊的可能造成的結(jié)果是否符合需求。
public class FightTest {
Fight f = null;
Role littleWhite = null;
Role littleStrong = null;
//@Before注解的意思是每次執(zhí)行@Test注解測試的時候都會執(zhí)行@Before注解的內(nèi)容
@Before
public void setUp() throws Exception {
f = new Fight();
littleWhite = new Role();
littleStrong = new Role();
}
//@Test注解用來執(zhí)行測試缚柏,該方法測試Fight.action
//記住苹熏,一個類寫一個測試類,每個方法寫一個測試方法(一些比較簡單的方法比如get币喧,set那些可以不用測)
@Test
public void testAction() {
State state = new State();
//初始化狀態(tài)測試,測試血量超過最大值的情況
state.setBlood(130);
littleWhite.setState(state);
littleStrong.setState(state);
state.setBlood(120);
Assert.assertEquals(state, littleWhite.getState());
state.setBlood(100);
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(100);
littleWhite.setState(state);
littleStrong.setState(state);
//littleWhite的所有攻擊測試包括邊際條件
//進(jìn)攻方轨域,防守方,攻擊方式A杀餐。
f.action(littleWhite, littleStrong, 'A');
state.setBlood(95);
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(120);
littleWhite.setState(state);
state.setBlood(100);
littleStrong.setState(state);
f.action(littleWhite, littleStrong, 'B');
state.setBlood(120);
Assert.assertEquals(state, littleWhite.getState());
state.setBlood(90);
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(0);
littleStrong.setState(state);
f.action(littleWhite, littleStrong, 'A');
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(1);
littleStrong.setState(state);
f.action(littleWhite, littleStrong, 'A');
state.setBlood(0);
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(0);
littleStrong.setState(state);
f.action(littleWhite, littleStrong, 'B');
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(1);
littleStrong.setState(state);
f.action(littleWhite, littleStrong, 'B');
state.setBlood(0);
Assert.assertEquals(state, littleStrong.getState());
state.setBlood(100);
littleWhite.setState(state);
//littleStrong的所有攻擊測試包括邊際條件
f.action(littleStrong, littleWhite, 'A');
state.setBlood(94);
Assert.assertEquals(state, littleWhite.getState());
state.setBlood(100);
littleWhite.setState(state);
f.action(littleStrong, littleWhite, 'B');
state.setBlood(70);
Assert.assertEquals(state, littleWhite.getState());
state.setBlood(0);
littleWhite.setState(state);
f.action(littleStrong, littleWhite, 'A');
state.setBlood(0);
Assert.assertEquals(state, littleWhite.getState());
state.setBlood(1);
littleWhite.setState(state);
f.action(littleStrong, littleWhite, 'A');
state.setBlood(0);
Assert.assertEquals(state, littleWhite.getState());
f.action(littleStrong, littleWhite, 'B');
state.setBlood(0);
Assert.assertEquals(state, littleWhite.getState());
state.setBlood(1);
littleWhite.setState(state);
f.action(littleStrong, littleWhite, 'B');
state.setBlood(0);
Assert.assertEquals(state, littleWhite.getState());
}
}
然后為了不報錯我們要創(chuàng)建Role類和Fight類還有State類干发,并且Fight類中創(chuàng)建action方法。
記住這個時候不要著急實現(xiàn)三個類的內(nèi)容史翘。
所以三個類里面只有這么多東西
public class Fight? {
public void action(Role attack, Role defense, char action) {
}
}
public class Role {
State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
}
public class State {
int blood;
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
}
public class Fight? {
public void action(Role first, Role second, char trick) {
}
}
然后這個時候我們知道了枉长,實現(xiàn)需求要構(gòu)建三個類冀续,剛剛寫了Fight類的測試,而Role類和State類的測試還沒寫
所以我們需要寫出Role類和State類的測試
然后我們分析需求必峰。Role類為角色類洪唐,這個類應(yīng)該有個方法模擬Role的動作。
這個方法可以接受Fight.action傳進(jìn)來攻擊方式和對手的狀態(tài)
然后返回對手更新后的狀態(tài)回Fight.action
然后根據(jù)這個需求寫測試類RoleTest
public class RoleTest {
Role r = null;
Trick defaultTrick = null;
Trick bigTrick = null;
@Before
public void setUp() throws Exception {
r = new Role();
defaultTrick = new Trick();
bigTrick = new Trick();
r.setDefaultTrick(defaultTrick);
r.setBigTrick(bigTrick);
}
@Test
public void testExecute() {
Trick defaultTrick = new Trick();
r.setDefaultTrick(defaultTrick);
State olestate = new State();
olestate.setBlood(100);
State newstate = new State();
newstate.setBlood(95);
Assert.assertEquals(newstate, r.execute (olestate,'A'));
//.........后面省略
}
}
另外還要Statk類的測試用例
public class StatkTest {
//................省略
}
我們在寫的時候發(fā)現(xiàn)吼蚁,我們Role需要兩個Trick(招數(shù))對象defaultTrick(普通攻擊),和bigTrick(大招)
來描述凭需。所以我們添加上兩個Trick屬性,以及新建一個Trick類肝匆。
Role類變成這樣粒蜈。但我們還是不要急著實現(xiàn)
public class Role {
State state;
Trick defaultTrick;
Trick bigTrick;
public Trick getDefaultTrick() {
return defaultTrick;
}
public void setDefaultTrick(Trick defaultTrick) {
this.defaultTrick = defaultTrick;
}
public Trick getBigTrick() {
return bigTrick;
}
public void setBigTrick(Trick bigTrick) {
this.bigTrick = bigTrick;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public State execute(State defense, char trick) {
return null;
}
}
依然的,我們先創(chuàng)建個Trick的測試用例
public class TrickTest {
//................省略
}
這個時候我們終于可以開始實現(xiàn)Trick旗国。然后寫完一個方法枯怖,運行一個測試方法。
測試通過之后進(jìn)行代碼重構(gòu)能曾。代碼重構(gòu)無需修改測試度硝。