![](/img/trans.png)
[英]Adobe AIR mobile applications unit testing integration tests test automations
[英]Is it OK to have multiple assertions in a unit test when testing complex behavior?
這是我的具體情況。
我有一個QueryQueue
類, QueryQueue
將QueryTask
類包裝在ArcGIS API for Flex中。 這使我可以輕松地將多個查詢任務排隊等待執行。 調用QueryQueue.execute()
遍歷隊列中的所有任務,並調用它們的execute方法。
接收並處理所有結果后, QueryQueue
將調度完成的事件。 我班的接口很簡單。
public interface IQueryQueue
{
function get inProgress():Boolean;
function get count():int;
function get completed():ISignal;
function get canceled():ISignal;
function add(query:Query, url:String, token:Object = null):void;
function cancel():void;
function execute():void;
}
為了使QueryQueue.execute
方法成功,必須發生一些事情。
task.execute
inProgress = true
inProgress = false
completed
結果后調度completed
canceled
從未被調用 我正在努力將這些測試分解為可讀,邏輯和可維護的測試。
從邏輯上講,我正在測試一種狀態 ,即成功執行狀態。 這表明一個單元測試可以斷定上面的#1至#6是正確的。
[Test] public mustReturnQueryQueueEventArgsWithResultsAndNoErrorsWhenAllQueriesAreSuccessful:void
但是,測試的名稱並不能說明所有問題,因為它沒有描述要通過測試就必須真實的所有事物。
在線閱讀(包括在此處以及在developers.stackexchange.com上 ),有一個相當大的陣營,它斷言單元測試應該只有一個斷言(作為准則)。 結果,當測試失敗時,您會確切地知道失敗的原因(即,inProgress未被設置為true,完成顯示多次,等等。)您可能會得到更多(但從理論上講更簡單更清晰)的測試,如下所示:
[Test] public mustInvokeExecuteForEachQueryTaskWhenQueueIsNotEmpty():void
[Test] public mustBeInProgressWhenResultsArePending():void
[Test] public mustNotInProgressWhenResultsAreProcessedAndSent:void
[Test] public mustDispatchTheCompletedEventWhenAllResultsProcessed():void
[Test] public mustNeverDispatchTheCanceledEventWhenNotCanceled():void
[Test] public mustReturnQueryQueueEventArgsWithResultsAndNoErrorsWhenAllQueriesAreSuccessful:void
// ... and so on
在測試中可能會產生大量重復的代碼,但是可以通過適當的setup
和teardown
方法將其最小化。
盡管此問題與其他問題類似,但我正在尋找針對此特定方案的答案,因為我認為它很好地表示了一個復雜的單元測試方案,該方案具有多個狀態和行為,需要進行驗證。 不幸的是,許多其他問題都沒有示例,或者這些示例沒有展示復雜的狀態和行為。
我認為可能會有很多,這里有幾件事:
最終,您的目標應該是通過專注於SOLID原則來追求理想的狀態(每個單元測試一個斷言),但是最終您確實需要完成工作,否則編寫軟件沒有任何實際意義(至少我認為: ))。
讓我們專注於您首先確定的測試。 除了最后一個( mustReturnQueryQueueEventArgs...
)之外,其他所有都是好東西,我可以立即告訴那里正在測試什么(這是一個很好的信號,表明它們具有描述性,並且很可能很簡單)。
唯一的問題是您的最后一次測試。 請注意,測試名稱中單詞“ and” , “ with” , “ or”的廣泛使用通常會引起問題。 目前尚不清楚應該做什么。 返回正確的結果首先想到的是,但有人可能會說這是一個模糊的術語? 這是正確的,這是模糊的。 但是,您經常會發現這確實是相當普遍的要求,並按方法/操作合同進行了詳細說明。
在您的特定情況下,我將簡化上一次測試,以驗證是否返回了正確的結果,僅此而已。 您已經測試了導致結果建立的狀態,事件和事物,因此無需再次進行測試。
現在,您提供的鏈接中的建議實際上是非常好的建議, 通常 ,我建議您堅持使用它們(對一個測試使用單個斷言)。 問題是, 單個斷言真正代表什么? 測試結束時有1行代碼? 然后讓我們考慮這個簡單的示例:
// a method which updates two fields of our custom entity, MyEntity
public void Update(MyEntity entity)
{
entity.Name = "some name";
entity.Value = "some value";
}
該方法合同將執行這兩個操作。 通過成功,我們了解要正確更新的實體。 如果其中一個由於某種原因失敗,則將方法作為一個單元視為失敗。 您可以看到前進的方向; 您將擁有兩個斷言,或者僅出於測試目的編寫自定義比較器。
不要被單一的主張所欺騙; 這與代碼行數或斷言數量無關(但是,在大多數測試中,您編寫的確會映射為1:1),而是斷言單個單元 (在上面的示例中, update被視為一個單元)。 實際上,單位可能是多種事物,彼此之間毫無任何意義。
這正是您鏈接引號的問題之一(Roy Osherove):
我的指導原則通常是每次測試都測試一個邏輯概念。 您可以在同一對象上具有多個斷言。 它們通常是要測試的相同概念。
都是關於概念/責任; 不是斷言的數量。
我不熟悉flex,但是我想我在單元測試方面有很好的經驗,因此您必須知道單元測試是一種哲學,因此對於第一個答案,可以進行多重聲明,但是如果您測試相同的行為,單元測試中的重點始終是非常易於維護和簡單的代碼,否則單元測試將需要單元測試來進行測試! 因此,我的建議是,如果您是單元測試的新手,請不要使用多個斷言,但是如果您在單元測試方面有豐富的經驗,那么您會知道何時需要使用它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.