数据驱动测试是不是很糟糕?

bbt*_*trb 11 c++ testing data-driven googletest

我已经开始使用googletest来实现测试,并在有关参数化测试的文档中偶然发现了这个引用

  • 您希望通过各种输入(也称为数据驱动的测试)测试您的代码.此功能很容易被滥用,所以请在锻炼时锻炼你的良好感觉!

我认为在执行以下操作时我确实"滥用"了系统,并希望听取您对此事的意见和建议.

假设我们有以下代码:

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);
Run Code Online (Sandbox Code Playgroud)

好的,所以使用这个代码,测试f()(通过比较f_alt())与随机生成的数据的不同输入数组大小来测试分支的正确性当然是有意义的.最重要的是,我有几个structsSumMethod,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);
// ...
Run Code Online (Sandbox Code Playgroud)

当然,我的问题是:这是否有意义,为什么这会很糟糕?

实际上,我在使用floats 运行测试时发现了一个"bug" ,f()并且由于舍入而f_alt()给出了不同的值SumMethod,我可以通过预先输入数组等来改进.从这个经验我认为这实际上是一些好的做法.

hai*_*img 11

我认为主要问题是使用"随机生成的数据"进行测试.从您的问题中不清楚每次运行测试工具时是否重新生成此数据.如果是,则您的测试结果不可重复.如果某些测试失败,那么每次运行它都会失败,而不是一次在蓝色的月亮,一些奇怪的随机测试数据组合.

因此,在我看来,您应该预先生成测试数据并将其作为测试套件的一部分.您还需要确保数据集足够大且多样化,足以提供足够的代码覆盖率.

此外,正如Ben Voigt在下面评论的那样,使用随机数据进行测试是不够的.您需要在算法中识别极端情况并单独测试它们,并为这些情况专门定制数据.但是,在我看来,如果您不确定是否知道所有角落情况,那么使用随机数据进行额外测试也是有益的.您可以使用随机数据偶然击中它们.

  • 随机数据测试有一个简单的解决方案:确保所有随机性都由相同的可播种生成器生成,并存储该生成器的种子.随机测试可以是一个很好的工具,但就像任何其他工具一样,您必须知道如何使用它以及有哪些优点和缺点. (3认同)
  • 随机生成的数据有两个原因 - 首先,因为正如您所提到的,测试不可重现.其次,因为角落情况可能不被随机生成的数据所覆盖.保存随机向量对第二个缺点没有任何作用. (2认同)

duf*_*ymo 6

问题是你不能像浮点数那样断言浮点数的正确性.

检查某个epsilon中的正确性,这是计算值和期望值之间的微小差异.这是你能做的最好的事情.对于所有浮点数都是如此.

我认为在执行以下操作时我确实"滥用"了系统

你在阅读那篇文章之前认为这是不好的吗?你能说清楚它有什么不好吗?

您必须在某个时候测试此功能.您需要数据才能执行此操作.虐待在哪里?