最佳实践:测试使用随机数生成器的代码

时间:2014-02-07 10:24:17

标签: c++ testing random

在代码中某处(深入,深入)说我使用随机数来做一些很酷的事情。测试通常应该是确定性的,而这部分代码的发布版本的行为明确地利用了随机数生成器的非确定性/随机性。

因此,为了获得确定性(功能)测试,我想设置一个固定的种子值:

size_t seed = 42;
std::mt19937 rng;
rng.seed(seed);

但是我也想确保当我使用随机输入和随机种子时没有发生任何奇怪的事情(例如异常):

std::mt19937 rng;
rng.seed(std::random_device()());

显然,有限数量的测试运行无法确定代码是否正确;但是,大量的测试运行至少可以给你一些信心。

我如何才能最好地处理这个问题?我想添加类似的东西:

size_t seed = std::random_device()();
#ifdef TESTING
    seed = 42;
#endif
rng.seed(seed);

但是,我不能拥有一个测试文件(使用gtest),它使用随机种子进行某些测试,并使用常量种子进行其他测试(可以吗?)。

¹在我的情况下:我从n中统一选择一个元素并随机独立地对输入进行分区。

编辑:我问的是功能测试,而不是单元测试。

2 个答案:

答案 0 :(得分:1)

首先,为随机数生成器创建一个接口,以便测试能够将其替换为预定义的接口。如果您在单元测试中使用随机数生成器,则它不再是单位。

然后想想你真正想要测试什么。我想,应该测试这个算法:

  • 它是否完全有效(您的预定义“随机”生成器可能在每次迭代时返回1,2,3,... - 可能以最大范围为模);
  • 如果随机生成器始终返回边界值(0和max-1或max,具体取决于您的需要),它是否返回有效结果;
  • 当随机生成器返回超出范围的值时,是否通知错误。

<小时/> 编辑:(回答问题编辑)

为什么在功能测试中对随机数生成器感到烦恼?功能测试检查应用程序在用户使用时是否正常工作。用户将无法访问随机数生成器的种子,因此请保持原样并允许其按照您的设计工作。如果算法的结果不依赖于随机数生成器生成的值,请检查它们是否在测试之间不会更改。如果他们依赖于随机数生成器,请检查如果他们在两次测试之间发生变化(如果他们不这样做,那意味着代码不会执行它的操作应该)。

答案 1 :(得分:1)

这取决于你想做什么样的测试。

在单元测试中,种子应设置为固定值。

在某种功能测试中,你真的想要使用随机数测试行为,并且无论需要多长时间,你可以设置随机种子(可能使用time()),并执行根据需要多次测试。

这意味着,您应该以类似的方式(使用gtest)创建两组测试,其中单元测试的执行速度要快得多。使用单元测试,您不会访问文件和减慢资源(如网络和数据库)。