是否确定测试复杂的行为时有一个单元测试多个断言? [英] Is it OK to have multiple assertions in a unit test when testing complex behavior?

查看:180
本文介绍了是否确定测试复杂的行为时有一个单元测试多个断言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的具体方案。

我有一个类 QueryQueue 封装了 QueryTask 类的ArcGIS API,用于Flex的范围内。这使我能够很容易地排队执行多个查询任务。呼叫 QueryQueue.execute()遍历我的队列中的所有任务,并调用它们的执​​行方法。

I have a class QueryQueue that wraps the QueryTask class within the ArcGIS API for Flex. This enables me to easily queue up multiple query tasks for execution. Calling QueryQueue.execute() iterate through all the tasks in my queue and call their execute method.

当所有的结果已经收到并处理 QueryQueue 将分派完成事件。接口上我的课是很简单的。

When all the results have been received and processed QueryQueue will dispatch the completed event. The interface to my class is very simple.

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 来考虑的方法必须进行成功的几件事情。

For the QueryQueue.execute method to be considered successful several things must occur.

  1. task.execute 必须调用每个查询任务一次且仅一次
  2. INPROGRESS = TRUE ,而仍未有结果
  3. INPROGRESS = FALSE 时,结果都被处理
  4. 完成时,结果都被处理时调度
  5. 取消从不叫
  6. 进行中的队列正确处理和包装物的查询结果的处理
  1. task.execute must be called on each query task once and only once
  2. inProgress = true while the results are pending
  3. inProgress = false when the results have been processed
  4. completed is dispatched when the results have been processed
  5. canceled is never called
  6. The processing done within the queue correctly processes and packages the query results

我所挣扎的是打破这些测试成可读的,逻辑和维护测试。

What I am struggling with is breaking these tests into readable, logical, and maintainable tests.

从逻辑上讲,我测试一个的状态的,那就是成功的执行状态。这表明一个单元测试,将断言#1至#6以上都是真实的。

Logically I am testing one state, that is the successful execution state. This would suggest one unit test that would assert #1 through #6 above are true.

[Test] public mustReturnQueryQueueEventArgsWithResultsAndNoErrorsWhenAllQueriesAreSuccessful:void

不过,测试的名称不是信息,因为它并没有描述所有的事情,必须是真实的,才能被认为是一个合格的测试。

However, the name of the test is not informative as it does not describe all the things that must be true in order to be considered a passing test.

阅读在线(包括<一个href="http://stackoverflow.com/questions/735737/multiple-assertions-when-unit-testing-constructor">here和<一href="http://programmers.stackexchange.com/questions/7823/is-it-ok-to-have-multiple-asserts-in-a-single-unit-test">programmers.stackexchange.com)有一个庞大的阵营声称,单元测试应该只有一个断言(作为指导)。当一个测试失败,你确切地知道失败的结果(即INPROGRESS未设置为true,完成多次显示等),你风,可能会有更多的(但在理论上更加简单和清晰)测试,像这样:

Reading up online (including here and at programmers.stackexchange.com) there is a sizable camp that asserts that unit tests should only have one assertion (as a guideline). As a result when a test fails you know exactly what failed (i.e. inProgress not set to true, completed displayed multiple times, etc.) You wind up with potentially a lot more (but in theory simpler and clearer) tests like so:

[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

这可以有很多的反复code在测试风,但可能有相应的设置拆卸<最小化/ code>的方法。

This could wind up with a lot of repeated code in the tests, but that could be minimized with appropriate setup and teardown methods.

虽然这个问题是类似的其他问题,我寻找的这种特定情况下的答案,因为我认为这是一个复杂的单元测试场景展示多个国家和需要验证行为的一个很好的重新presentation。许多其他问题都有,可惜的是,没有任何例子或者例子并没有表现出复杂的状态和行为。

While this question is similar to other questions I am looking for an answer for this specific scenario as I think it is a good representation of a complex unit testing scenario exhibiting multiple states and behaviors that need to be verified. Many of the other questions have, unfortunately, no examples or the examples do not demonstrate complex state and behavior.

推荐答案

让我们关注您首先确定了测试。所有除了最后一个( mustReturnQueryQueueEventArgs ... )是好的,我可以immediatelly知道什么被测试的有(这是非常好的现象,说明他们是描述性的,最可能简单)。

Let's focus on the tests you have identified first. All except the last one (mustReturnQueryQueueEventArgs...) are good ones and I could immediatelly tell what's being tested there (and that's very good sign, indicating they're descriptive and most likely simple).

唯一的问题是你的最后一次测试。需要注意的是广泛使用的话的的测试名称通常敲响钟声的问题。这不是很清楚什么应该做的。返回正确的结果是第一位的脑海,但人们可能会认为这是模糊的术语?这是正确的,它是模糊的。然而,你常常会发现,这确实是pretty的共同要求,由法/经营合同中的细节描述。

The only problem is your last test. Note that extensive use of words "and", "with", "or" in test name usually rings problems bell. It's not very clear what it's supposed to do. Return correct results comes to mind first, but one might argue it's vague term? This holds true, it is vague. However you'll often find out that this is indeed pretty common requirement, described in details by method/operation contract.

在您的特定情况下,我想简化了最后一次测试,以验证正确的结果是否返回,这将是所有的。你测试状态,事件和东西导致的结果已经建立,所以没有必要一遍。

In your particular case, I'd simplify last test to verify whether correct results are returned and that would be all. You tested states, events and stuff that lead to results building already, so there is no need to that again.

现在,在你的链接提供的意见是相当不错的人居然和一般的,我建议坚持他们(单断言一个测试)。现在的问题是,什么样的单断言的真正代表? 1号线的code在测试结束?让我们看看这个简单的例子吧:

Now, advices in links you provided are quite good ones actually, and generally, I suggest sticking to them (single assertion for one test). The question is, what single assertion really stands for? 1 line of code at the end of test? Let's consider this simple example then:

// a method which updates two fields of our custom entity, MyEntity
public void Update(MyEntity entity)
{
    entity.Name = "some name";
    entity.Value = "some value";
}

此方法合同来执行这些操作2。通过成功的,我们理解实体正确更新。如果它们中的某些原因之一出现故障,方法作为一个单元被认为是失败的。你可以看到这是怎么回事;你要么有两个断言或写自定义比较纯粹是出于测试目的。

This method contract is to perform those 2 operations. By success, we understand entity to be correctly updated. If one of them for some reasons fails, method as a unit is considered to fail. You can see where this is going; you'll either have two assertions or write custom comparer purely for testing purposes.

不要被欺骗的单断言的;它不是关于code或数行的断言(测试然而,在大多数你会写这确实会图1:1),但关于断言的单个单元(在上面的例子中,的更新的被认为是一个单位)。和单位可能会在现实中多东西,不作任何意义没有海誓山盟。

Don't be tricked by single assertion; it's not about lines of code or number of asserts (however, in majority of tests you'll write this will indeed map 1:1), but about asserting single unit (in the example above, update is considered to be an unit). And unit might be in reality multiple things that don't make any sense at all without eachother.

而这正是问题一个你链接引号(罗伊Osherove):

And this is exactly what one of questions you linked quotes (by Roy Osherove):

我的指引通常是您测试每个测试一个逻辑概念。你可以有多个声称对同一个对象。他们通常将是相同的概念被测试

My guideline is usually that you test one logical CONCEPT per test. you can have multiple asserts on the same object. they will usually be the same concept being tested.

这是关于概念/责任;数量不限的断言。

It's all about concept/responsibility; not the number of asserts.

这篇关于是否确定测试复杂的行为时有一个单元测试多个断言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆