这种情况下有多少个测试用例?

时间:2017-03-08 21:55:32

标签: unit-testing

我有一个做很多事情的方法,因此创造了许多副作用。例如,假设对REST API的单个调用返回一个设置了许多字段的JSON对象。在这种情况下,如果我们要检查每个单独的字段,我们应该有一个单独的测试方法,它将包含许多assertEquals,或者每个字段验证应该有一个单独的测试方法,包含一个assertEquals。

类似地,一个方法可以有许多其他的副作用,例如,保存到数据库,发送电子邮件等。在这种情况下,我应该每侧有一个单元测试方法吗?

此外,如果每个SUT方法有多个测试输入,那么这会影响决定创建多少个测试方法吗?

此外,它可能与故事有关,故事说这个,这个子功能属于故事,那个案例不应该属于同一个测试方法吗?因为如果需求发生变化,那么每侧的所有测试方法都会发生变化。那可管理吗?

1 个答案:

答案 0 :(得分:0)

  

在这种情况下,如果我们要检查每个单独的字段,我们应该有一个单独的测试方法,它将包含许多assertEquals,或者每个字段验证应该包含一个assertEquals。 < / p>

担心测试用例中断言的数量就像担心函数中有多少行一样。它是复杂性的一阶近似,但它并不是你应该关注的。

您应该关注的是该测试的维护难度以及诊断的好坏程度。当测试失败时,你能找出原因吗?其中很大程度上取决于assertEquals对大数据结构的好处。

json = call_rest();
want = { ...whatever you expect... };
assertEquals( json.from_json(), want );

如果这只是告诉你他们不平等,那就没那么有用了。然后,您必须手动进入并查看jsonwant。如果它转出两个数据结构,那也不是很有用,你必须通过眼睛寻找差异。

但如果它提供了两种数据结构的有用差异,那么这很有用。例如,Perl的Test2将产生这样的诊断。

use Test2::Bundle::Extended;

is { foo => 23, bar => 42, baz => 99 },
   { foo => 22, bar => 42, zip => 99 };

done_testing;

# +-------+------------------+---------+------------------+
# | PATH  | GOT              | OP      | CHECK            |
# +-------+------------------+---------+------------------+
# | {foo} | 23               | eq      | 22               |
# | {zip} | <DOES NOT EXIST> |         | 99               |
# | {baz} | 99               | !exists | <DOES NOT EXIST> |
# +-------+------------------+---------+------------------+

然后出现了维护问题,这又归结为你的assertEquals有多好。单个assertEquals易于阅读和维护。

json = call_rest();
want = { ...whatever you expect... };
assertEquals( json.from_json(), want );

代码非常少,want非常清楚预期的内容。

虽然多个人非常罗嗦。

json = call_rest();
have = json.from_json();
assertEquals( have['thiskey'], 23 );
assertEquals( have['thatkey'], 42 );
assertEquals( have['foo'], 99 );
...and so on...

可能很难知道哪个断言失败,你必须通过行号或(如果你的测试套件支持它)手动命名每个断言,这是更多的工作和更多的维护,还有一件事是出错。

OTOH个人assertEquals允许更多灵活性。例如,如果您只想检查某些字段该怎么办?如果范围内有可接受的值会怎样?

# bar just has to contain a number
assert( have['bar'].is_number );

但是一些测试套件通过单个断言支持这一点。

want = {
    thiskey: 23,
    thatkey: 42,
    foo:     99,
    bar:     is_number
}

assertEquals( json.from_json, want );

is_number是一个特殊对象,它告诉断言它不是正常的质量检查,而只是检查该值是否为数字。如果您的测试套件支持这种风格,那么它通常优于写出一堆断言。声明性方法意味着编写,读取和维护的代码更少。

答案是:这取决于您的测试工具有多好!