我已经开始使用googletest来实施测试,并在有关的文档中偶然发现了这个引用 价值参数化测试
- 您希望通过各种输入测试代码(a.k.a.数据驱动 测试)。此功能很容易滥用,所以请锻炼你的好处 这样做的感觉!
我认为在做以下事情时我确实“滥用”了系统,并希望听取您对此事的意见和建议。
假设我们有以下代码:
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);
// ...
当然,我的问题是:这有什么意义,为什么这会很糟糕?
事实上,我在运行测试时发现了一个“bug” float
在哪里 f()
和 f_alt()
会给出不同的价值 SumMethod
由于四舍五入,我可以通过预先输入数组等来改进。从这个经验我认为这实际上是一些好的做法。