2010-07-22 62 views
2

我想为生成不同字符串的类编写单元测试。我最初的反应是以下几点:单元测试生成不同字符串的类

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 /许多哲学)?

还有其他意见或建议吗?

回答

1

我会继续使用你的方法;这可能是最可靠的选择。

顺便说一句,你不需要if声明:

Assert.IsTrue(generatedStrings.Add(str), "Generated {0} twice", str); 
0

如果我想测试上随机输入依赖代码,我会尝试存根出随机生成(比如,ITestableRandomGenerator)以便它可以被嘲笑进行测试。然后您可以注入不同的“随机”序列,以适当地触发您的代码的不同执行路径,并保证必要的代码覆盖率。

您已经显示的特定测试基本上是一个黑盒测试,因为您只是生成输出并验证它至少可以工作N个周期。由于代码没有任何输入,这是一个合理的测试,但如果您知道不同的条件可能会影响您的算法,那么您可以更好地测试这些特定输入。这可能意味着以某种方式运行具有不同“种子”值的算法,选择种子以便以不同的方式执行代码。

0

如果您将算法传递到UniqueStringCreator的构造函数中,您可以在单元测试中使用存根对象来生成伪随机(可预测)数据。另请参阅战略模式。

0

如果在类内部有某种检查,则可以始终将生成字符串的部分与检查清晰度的部分分开。

然后你嘲笑检查器,并测试两种情况下的行为;检查者认为字符串已经创建的那个,以及它没有创建的字符串。

无论底层实现逻辑如何,您可能会发现类似的方式来分割责任。

否则,我同意SLaks - 坚持你所拥有的。进行测试的主要原因是让代码易于更改,所以只要人们可以阅读并思考,“哦,那就是它正在做什么!”你可能很好。