![](/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.