不要试图一次测试太多的东西。对于一个测试,集合中每个数据对象的每个属性都太多了。相反,我建议:
- 如果集合是固定长度的,则编写一个单元测试以验证长度。如果它是可变长度,则编写多个测试以测试可表征其行为的长度(例如0、1、3、10)。无论哪种方式,都不要在这些测试中验证属性。
- 编写单元测试以验证每个属性。如果集合是固定长度且较短的集合,则针对每个测试针对每个元素的一个属性进行断言。如果它是固定长度但很长,则选择一个代表性但较小的元素样本,以针对每个属性进行断言。如果它是可变长度的,则生成一个相对较短但有代表性的集合(即可能是三个元素),并针对每个元素的一个属性进行断言。
这样做可以使测试足够小,以至于省去了循环的痛苦。C#/单元示例,给定测试方法ICollection<Foo> generateFoos(uint numberOfFoos)
:
[Test]
void generate_zero_foos_returns_empty_list() { ... }
void generate_one_foo_returns_list_of_one_foo() { ... }
void generate_three_foos_returns_list_of_three_foos() { ... }
void generated_foos_have_sequential_ID()
{
var foos = generateFoos(3).GetEnumerable();
foos.MoveNext();
Assert.AreEqual("ID1", foos.Current.id);
foos.MoveNext();
Assert.AreEqual("ID2", foos.Current.id);
foos.MoveNext();
Assert.AreEqual("ID3", foos.Current.id);
}
void generated_foos_have_bar()
{
var foos = generateFoos(3).GetEnumerable();
foos.MoveNext();
Assert.AreEqual("baz", foos.Current.bar);
foos.MoveNext();
Assert.AreEqual("baz", foos.Current.bar);
foos.MoveNext();
Assert.AreEqual("baz", foos.Current.bar);
}
如果您习惯于“平面单元测试”范式(无嵌套结构/逻辑),那么这些测试似乎很干净。因此,通过将原始问题识别为试图一次测试太多的属性而不是缺少循环,可以避免测试中的逻辑。