我们如何对使用随机性的函数进行单元测试?

问题描述 投票:0回答:1

我对使用随机性的单元测试函数的最佳实践技术(如果有的话)感兴趣。要清楚,我不关心测试随机数发生器的分布。

作为玩具示例,让我们考虑一下这个功能:

// Returns a random element from @array. @array may not be empty.
int GetRandomElement(int[] array);

this question的回答表明我们可能注入一个随机性的模拟源,这是有道理的。但我不确定如何使用模拟。例如,假设我们有这个接口:

// A mock-friendly source of randomness.
interface RandomnessSource {
  // Returns a random int between @min (inclusive) and @max (exclusive).
  int RandomInt(int min, int max);
}

...并将GetRandomElement()的签名更改为:

// Returns a random element from @array, chosen with @randomness_source.
// @array may not be empty.
int GetRandomElement(int[] array, RandomnessSource randomness_source);

好吧,现在测试看起来像:

MockRandomnessSource mock = new MockRandomnessSource();
mock.ExpectCall(RandomnessSource::RandomInt(0, 5)).Return(2);
AssertEquals(GetRandomElement({0, 10, 20, 30, 40}, mock), 20);

...可以正常工作,但只有实现如下:

// A fairly intuitive implementation.
int GetRandomElement(int[] array, RandomnessSource randomness_source) {
  // Pick a random number between [0..n), where @n is the @array's legnth.
  return array.Get(randomness_source.RandomInt(0, array.Length()));
}

...但是函数规范中没有任何内容阻止这样的实现:

// Less intuitive, but still a conforming implementation.
int GetRandomElement(int[] array, RandomnessSource randomness_source) {
  // Pick a random number between [1..n+1), only to subtract 1 from it.
  return array.Get(randomness_source.RandomInt(1, array.Length() + 1) - 1);
}

跳出来的一个想法是我们可能会进一步约束函数的契约,如下所示:

// Returns a random element from @array, chosen with @randomness_source by
// by calling @RandomnessSource::RandomInt to pick a random index between
// 0 and the length of @array.
int GetRandomElement(int[] array, RandomnessSource randomness_source);

...但我不能完全认为这对功能合同施加了太大的限制。

我还怀疑可能有更好的方法来定义接口RandomnessSource以使其调用者更适合单元测试,但我不太清楚是什么/如何。

......这让我想到了一个问题:使用随机性的单元测试函数的最佳实践技术(如果有的话)是什么?

unit-testing random
1个回答
0
投票

通常你不想单元测试“随机性”。单元测试主要用于确定预期输入是否会为您提供预期输出。非常明确和结构化。您希望每次运行测试时,您的单元测试都是可预测的,并且行为方式相同。

如果你真的想测试它,问题就变成你想要测试它的具体程度如何?如果在两次测试之间结果不同会发生什么?如何定义成功的测试与失败的测试?

这些问题在正常单元测试中更为明显,其中结果非常清晰且事先已明确定义。

© www.soinside.com 2019 - 2024. All rights reserved.