我正在尝试为生成不同字符串的类编写单元测试。我最初的反应如下:
public void GeneratedStringsShouldBeDistinct()
{
UniqueStringCreator stringCreator = new UniqueStringCreator();
HashSet<string> generatedStrings = new HashSet<string>();
string str;
for (int i = 0; i < 10000; i++)
{
str = stringCreator.GetNext();
if (!generatedStrings.Add(str))
{
Assert.Fail("Generated {0} twice", str);
}
}
}
我喜欢这种方法,因为我知道底层算法并没有使用任何随机性,所以我不会遇到可能会失败一次然后接下来会成功的情况 - 但是未来可能会被某人交换掉。 OTOH,任何随机算法的测试会导致这种类型的测试不一致,那么为什么不这样做呢?
我应该只获得2个元素并检查清晰度(使用0/1 /多元哲学)?
还有其他意见或建议吗?
答案 0 :(得分:1)
我会继续使用你的方法;它可能是最可靠的选择。
顺便说一句,您不需要if
声明:
Assert.IsTrue(generatedStrings.Add(str), "Generated {0} twice", str);
答案 1 :(得分:0)
如果我想测试依赖于随机输入的代码,我会尝试删除随机生成(例如,ITestableRandomGenerator),以便可以模拟它进行测试。然后,您可以注入不同的“随机”序列,这些序列可以适当地触发被测代码的不同执行路径,并保证必要的代码覆盖率。
您展示的特定测试基本上是一个黑盒测试,因为您只是生成输出并验证它至少可以运行N个周期。由于代码没有任何输入,这是一个合理的测试,但如果您知道不同的条件可能会影响您的算法,以便您可以测试这些特定的输入可能会更好。这可能意味着以某种方式运行具有不同“种子”值的算法,选择种子以便它以不同的方式运用代码。
答案 2 :(得分:0)
如果您将算法传递给UniqueStringCreator的构造函数,则可以在单元测试中使用存根对象来生成伪随机(可预测)数据。另见战略模式。
答案 3 :(得分:0)
如果在类中有某种检查,你总是可以将检查清晰度的部分与生成字符串的部分分开。
然后你嘲笑检查器,并测试两个上下文中的行为;检查器认为已经创建了一个字符串的那个,以及没有创建字符串的那个。
无论底层实现逻辑如何,您都可以找到类似的方法来分担职责。
否则,我同意SLaks - 坚持你所拥有的。进行测试的主要原因是代码保持易于更改,因此只要人们可以阅读并思考,“哦,那它在做什么!”你可能很好。