在处理模块List::Gen的某些更新时,我决定添加->pick(num)
方法,该方法将从其来源返回num
大小的随机元素列表。为了对此进行测试,我使用srand
为随机数生成器播种,并对表单进行了多次测试:
srand 1234;
is $src->pick(5)->str, '3 6 1 7 9';
这一切都在我当时使用的Windows机器上运行良好。但是,当我将项目移动到Mac工作站时,所有随机性测试都失败了,因为尽管有相同的随机种子,rand
产生了不同的结果。我收集的是来自rand()
的不同底层C实现。
所以问题是,测试这些功能的最佳跨平台方法是什么?我应该用自己的rand
函数重载吗?我应该为使用rand
的函数构建钩子,以启用产生可预测输出的“测试”模式吗?还有其他方法吗?
我更喜欢包含核心Perl技术的答案,因为我试图保持模块的依赖树很小。
Test::Random和Test::MockRandom似乎是CPAN的建议,有没有人有这些模块的经验?
答案 0 :(得分:2)
我没有用过任何一个。
看起来Test :: Random对你来说是更好的选择,因为你显然只是在测试中使用随机性,而不是在你发布的代码中。它应该更简单易用。
Test :: MockRandom模块强制rand()函数返回确定性序列。
答案 1 :(得分:0)
你可以运行几个选择,并确保他们不会返回相同的东西。毕竟,这就是这个功能的目的。
答案 2 :(得分:0)
我更喜欢简单地封装环境依赖关系并将其覆盖以用于测试目的,称为Test Stub的测试模式。 Test Stub还包括其他间接输入,如系统时间和文件句柄。这些都应该被解释为同一问题的不同形式,这就是为什么我认为这个问题的CPAN解决方案不是很好。
应用于随机数域,我们有类似的东西:
use strict;
use warnings;
package Foo;
sub new {
my ($class) = @_;
return bless {} => $class;
}
sub get_random_number {
return rand();
}
package main;
use Test::MockObject::Extends;
use Test::More tests => 1;
my $foo = Test::MockObject::Extends->new( Foo->new() );
$foo->set_series(get_random_number => 0.5, 0.001, 0.999);
is( $foo->get_random_number, 0.5 );
这使得被测系统保持不变,除了它应该具有的重构,但是提供控制点以将可预测的数据注入到测试中。 get_random_number
不会被测试所覆盖,因此以正确的检查方式编写它是至关重要的;对依赖系统资源的单次调用就是应该存在的所有内容。
如果您遇到特定问题,则需要将rand
的依赖关系从pick
中分解出来,然后在List::Gen
的可测试版本中覆盖提取的方法。 Test::MockObject::Extends
非常适合这种需要。
答案 3 :(得分:0)
也许随机部分对您的测试无关紧要?
通过测试可以检查以下内容:
这基本上就是你已经在做的事情,因为你试图将rand()排除在等式之外。也可以一路走下去,测试你的功能是否符合它所说的那样。