1 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超5個(gè)贊
我會(huì)給你另一種觀點(diǎn)。我見過很多人走錯(cuò)了路,當(dāng)你這樣做時(shí),其他一切都變得很難做/測(cè)試,這正是你現(xiàn)在正在做的。
從這里開始,你想達(dá)到什么目的?
我想測(cè)試并確保某個(gè)方法被調(diào)用......
這是一件好事嗎?什么是不應(yīng)該有的單元測(cè)試?那就是對(duì)代碼的深入了解。
為什么?因?yàn)槊看文銓?duì)代碼做一點(diǎn)小改動(dòng),你都會(huì)因?yàn)檫@種深厚的知識(shí)而不得不改變測(cè)試。如果您有 1000 次測(cè)試,那么您將走上一條艱難的道路。
好的,現(xiàn)在我們知道問題是什么了,那么我們?nèi)绾谓鉀Q呢?好吧,首先讓我們確保我們可以在不深入了解代碼的情況下進(jìn)行測(cè)試。
我們?cè)撛趺醋??好吧,想象一下你的代碼添加了一個(gè)額外的步驟,一個(gè)設(shè)置狀態(tài)的標(biāo)志。您可能有一個(gè)存儲(chǔ)結(jié)果狀態(tài)的標(biāo)志......
你有 3 個(gè)方法要調(diào)用,所以你需要 3 個(gè)不同的狀態(tài),所以創(chuàng)建一個(gè)變量來反映它,無論是字符串、枚舉還是其他任何讓你開心的東西。
例如,假設(shè)我們創(chuàng)建了一個(gè)包含 3 個(gè)可能值的字符串:cycleDown、cycleUp 和 select。
您的代碼開始看起來像:
public string handleInput(InputKey key)
{
String state = determineState(key);
SomeType someResult = executeActionForState(state);
}
public String determineState(string key)
{
String state = "";
switch (key) {
case S:
case DOWN:
state = "cycleDown";
break;
case W:
case UP:
state = "cycleUp";
break;
case SPACE:
case ENTER:
state = "select";
break;
default:
break;
}
return state;
}
public void executeActionForState(string state)
{
if ( state == "cycleup" ) {
}
etc etc
}
現(xiàn)在,我可能不一定像這樣編寫您的示例代碼,這有點(diǎn)勉強(qiáng),這取決于您對(duì)代碼執(zhí)行的其他操作,但這是為了展示如何將功能與 UI 方面分開。
我可以很容易地測(cè)試狀態(tài)方法,我可以更改它的代碼,而不必更改測(cè)試,因?yàn)闇y(cè)試會(huì)查看輸入和輸出,而不是事情是如何實(shí)現(xiàn)的。
單元測(cè)試是關(guān)于功能的,它是關(guān)于擁有一旦創(chuàng)建就不需要更改的簡(jiǎn)單測(cè)試。驗(yàn)證某個(gè)方法是否已被調(diào)用不會(huì)給您帶來任何有價(jià)值的東西,因?yàn)槟恢涝摲椒ㄉ院髸?huì)做什么。
您可以通過其他方式測(cè)試 UI 內(nèi)容,單元測(cè)試僅與正確的功能有關(guān)。如果你不明確這種分離,那么你將難以維護(hù)你的測(cè)試,它會(huì)變得越來越難,直到你放棄。
您將測(cè)試您是否獲得了正確的狀態(tài),然后測(cè)試 cycleUp 方法是否根據(jù)您的要求做了正確的事情,這就是您知道每個(gè)部分獨(dú)立工作的方式。稍后您開始查看集成測(cè)試、自動(dòng)化 UI 測(cè)試,但這些是不同的東西。對(duì)它的目的進(jìn)行單元測(cè)試,保持簡(jiǎn)單,不與其他代碼綁定,然后一切都會(huì)變得簡(jiǎn)單。你不需要模擬太多,你不需要太擔(dān)心復(fù)雜的設(shè)置,你也不需要每次代碼中的某些內(nèi)容發(fā)生變化時(shí)都改變你的測(cè)試。
現(xiàn)在,為了解決問題的最后一部分,私有方法,您通過觀察它們的輸出來測(cè)試它們。您的類中必須有一些公共的東西,在調(diào)用私有方法時(shí)會(huì)發(fā)生變化。所以測(cè)試一下。
添加回答
舉報(bào)