我开始使用googletest实现测试,并在有关value-parameterized tests的文档中偶然发现了这句话
我认为在执行以下操作时确实确实在“滥用”该系统,并希望听到您对此事的意见。
假设我们有以下代码:
template<typename T>
struct SumMethod {
T op(T x, T y) { return x + y; }
};
// optimized function to handle different input array sizes
// in the most efficient way
template<typename T, class Method>
T f(T input[], int size) {
Method m;
T result = (T) 0;
if(size <= 128) {
// use m.op() to compute result etc.
return result;
}
if(size <= 256) {
// use m.op() to compute result etc.
return result;
}
// ...
}
// naive and correct, but slow alternative implementation of f()
template<typename T, class Method>
T f_alt(T input[], int size);
好的,因此使用此代码,使用随机生成的数据的不同输入数组大小来测试
f()
(与f_alt()
进行比较)当然很有意义,以测试分支的正确性。最重要的是,我有几个structs
,例如SumMethod
,MultiplyMethod
等,因此我也针对不同类型运行了大量测试:typedef MultiplyMethod<int> MultInt;
typedef SumMethod<int> SumInt;
typedef MultiplyMethod<float> MultFlt;
// ...
ASSERT(f<int, MultInt>(int_in, 128), f_alt<int, MultInt>(int_in, 128));
ASSERT(f<int, MultInt>(int_in, 256), f_alt<int, MultInt>(int_in, 256));
// ...
ASSERT(f<int, SumInt>(int_in, 128), f_alt<int, SumInt>(int_in, 128));
ASSERT(f<int, SumInt>(int_in, 256), f_alt<int, SumInt>(int_in, 256));
// ...
const float ep = 1e-6;
ASSERT_NEAR(f<float, MultFlt>(flt_in, 128), f_alt<float, MultFlt>(flt_in, 128), ep);
ASSERT_NEAR(f<float, MultFlt>(flt_in, 256), f_alt<float, MultFlt>(flt_in, 256), ep);
// ...
现在,我的问题当然是:这有意义吗,为什么这会不好?
实际上,我在使用
float
运行测试时发现了一个“错误”,其中由于四舍五入,f()
和f_alt()
会因SumMethod
而给出不同的值,我可以通过对输入数组等进行预排序来改善。好的做法。 最佳答案
我认为主要问题是使用“随机生成的数据”进行测试。从您的问题尚不清楚,每次运行测试工具时是否会重新生成此数据。如果是这样,那么您的测试结果将无法重现。如果某些测试失败,则每次运行时它都会失败,而不是在某些奇怪的随机测试数据组合下一次失败。
因此,我认为您应该预先生成测试数据,并将其保留为测试套件的一部分。您还需要确保数据集足够大且足够多样化以提供足够的代码覆盖率。
而且,正如本·沃格特(Ben Voigt)在下面评论的那样,仅使用随机数据进行测试是不够的。您需要在算法中识别极端情况并单独测试它们,并为这些情况量身定制数据。但是,我认为,当/如果不确定自己是否了解所有极端情况,使用随机数据进行其他测试也将是有益的。您可能会使用随机数据偶然击中它们。