4

今天下午我遇到了这种情况,所以我想问问你们是做什么的。

我们有一个用于用户密码重置的随机密码生成器,在修复它的问题时,我决定将例程移到我的(缓慢增长的)测试工具中。

我想测试生成的密码是否符合我们制定的规则,但当然函数的结果将是随机的(或者,好吧,是伪随机的)。

你们会在单元测试中做什么?生成一堆密码,检查它们都通过并认为足够好?

4

11 回答 11

8

单元测试每次运行时都应该做同样的事情,否则你可能会遇到单元测试只是偶尔失败的情况,这可能是调试的真正痛苦。

尝试每次都用相同的种子播种伪随机器(在测试中,即——不是在生产代码中)。这样,您的测试每次都会生成相同的输入集。

如果你不能控制种子并且没有办法阻止你正在测试的函数被随机化,那么我猜你被一个不可预测的单元测试困住了。:(

于 2008-09-17T21:56:08.400 回答
4

该函数是一个假设,即对于所有输入,输出都符合规范。单元测试是试图证伪该假设。所以是的,在这种情况下你能做的最好的事情就是产生大量的输出。如果它们都通过了您的规范,那么您可以合理地确定您的功能按规定工作。

考虑将随机数生成器放在这个函数之外并向它传递一个随机数,使函数具有确定性,而不是让它直接访问随机数生成器。这样,您可以在测试工具中生成大量随机输入,将它们全部传递给您的函数,然后测试输出。如果失败,请记录该值是什么,以便您拥有记录在案的测试用例。

于 2008-09-17T21:57:49.987 回答
2

除了测试一些以确保它们通过之外,我还会编写一个测试以确保违反规则的密码失败。

代码库中是否有任何东西检查生成的密码以确保它们足够随机?如果没有,我可能会考虑创建逻辑来检查生成的密码,对其进行测试,然后您可以声明随机密码生成器正在工作(因为“坏”密码不会出现)。

一旦掌握了该逻辑,您就可以编写一个集成类型测试,该测试将生成大量密码并将其传递给逻辑,此时您就会了解随机密码生成的“好”程度。

于 2008-09-17T21:58:42.323 回答
0

好吧,考虑到它们是随机的,没有真正的方法可以确定,但是测试 100 000 密码应该可以消除大多数疑问:)

于 2008-09-17T21:53:20.090 回答
0

您还可以查看突变测试(Java 的Jester ,Ruby 的Heckle

于 2008-09-17T21:56:20.567 回答
0

您可以使用常数值播种随机数生成器,以获得非随机结果并测试这些结果。

于 2008-09-17T21:57:10.160 回答
0

我假设用户输入的密码符合与随机生成的密码相同的限制。因此,您可能需要一组静态密码来检查已知条件,然后您将有一个循环来执行动态密码检查。循环的大小不是很重要,但它应该足够大,以便您从生成器中获得温暖的模糊感觉,但又不能太大,以至于您的测试需要永远运行。如果随着时间的推移出现任何问题,您可以将这些案例添加到静态列表中。

但从长远来看,弱密码不会破坏您的程序,密码安全性掌握在用户手中。因此,您的首要任务是确保动态生成和强度检查不会破坏系统。

于 2008-09-17T21:59:44.490 回答
0

在不知道您的规则是什么的情况下很难确定,但假设它们类似于“密码必须至少为 8 个字符,其中至少有一个大写字母、一个小写字母、一个数字和一个特殊字符”,那么它就是即使用蛮力检查足够数量的生成密码来证明算法是正确的也是不可能的(因为这将需要超过 8^70 = 1.63x10^63 的检查,具体取决于您指定使用的特殊字符的数量,这需要非常,很长时间才能完成)。

最终,您所能做的就是尽可能多地测试密码,如果有任何违反规则,那么您就知道算法是不正确的。最好的办法可能是让它在一夜之间运行,如果早上一切顺利,你可能会没事。

如果您想在生产中加倍确定,请实现一个外部函数,该函数在循环中调用密码生成函数并根据规则检查它。如果失败,则记录一个指示此错误的错误(因此您知道需要修复它)并生成另一个密码。继续,直到你得到一个符合规则的。

于 2008-09-17T22:03:21.157 回答
0

以我的拙见,您不希望有时通过有时失败的测试。有些人甚至可能认为这种测试不是单元测试。但主要的想法是当你看到绿条时确保该功能是正常的。

牢记这一原则,您可以尝试执行合理的次数,以使错误正确的机会几乎为零。然而,一个单一的测试失败将迫使你进行更广泛的测试,而不是调试失败。

于 2008-09-17T22:15:24.390 回答
0

使用固定的随机种子或使其可重现(即:从当天派生)

于 2008-10-01T14:26:52.507 回答
0

首先,为您的 PRNG 使用种子。您的输入不再是随机的并且消除了不可预测的输出问题——即现在您的单元测试是确定性的。

然而,这并不能解决测试实现的问题,但这里有一个示例,说明如何测试依赖于随机性的典型方法。

想象一下,我们已经实现了一个函数,它需要一组红色和蓝色弹珠并随机挑选一个,但是可以为概率分配一个权重,即 2 和 1 的权重意味着红色弹珠被选中的可能性是蓝色弹珠。

我们可以通过将一个选项的权重设置为零并验证在所有情况下(在实践中,对于大量测试输入)我们总是得到例如蓝色弹珠来测试这一点。颠倒权重应该会得到相反的结果(所有红色弹珠)。

这并不能保证我们的函数按预期运行(如果我们传入相同数量的红色和蓝色弹珠并具有相同的权重,我们是否总是在大量试验中得到 50/50 的分布?)但实际上它是往往就足够了。

于 2018-02-14T11:27:16.693 回答