如何测试多参数公式

Mik*_*Mik 8 testing unit-testing googletest

我正在重构一些实现公式的代码,我想先测试,以提高我的测试技能,并保留代码.

这段特殊代码是一个公式,它接受3个参数并返回一个值.我甚至有一些数据表,其中包含不同输入的预期结果,因此从理论上讲,我可以进行多种类型的测试,只需更改输入参数并根据相应的预期值检查结果.

但我认为应该有更好的方法来实现它,并查看我发现的值参数化测试的文档.

因此,我现在知道如何自动为不同的输入创建测试.
但是,如何将相应的预期结果与我计算出的结果进行比较呢?

我唯一能想到的是静态查找表和文本夹具中的静态成员,它是查找表的索引,并在每次运行时递增.像这样的东西:

#include "gtest/gtest.h"

double MyFormula(double A, double B, double C)
{
    return A*B - C*C;   // Example. The real one is much more complex
}

class MyTest:public ::testing::TestWithParam<std::tr1::tuple<double, double, double>>
{
protected:

    MyTest(){ Index++; }
    virtual void SetUp()
    {
        m_C = std::tr1::get<0>(GetParam());
        m_A = std::tr1::get<1>(GetParam());
        m_B = std::tr1::get<2>(GetParam());
    }

    double m_A;
    double m_B;
    double m_C;

    static double ExpectedRes[];
    static int Index;

};

int MyTest::Index = -1;

double MyTest::ExpectedRes[] =
{
//               C = 1
//      B:   1     2     3     4     5     6     7     8     9    10
/*A =  1*/  0.0,  1.0,  2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,  9.0, 
/*A =  2*/  1.0,  3.0,  5.0,  7.0,  9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 
/*A =  3*/  2.0,  5.0,  8.0, 11.0, 14.0, 17.0, 20.0, 23.0, 26.0, 29.0, 

//               C = 2
//      B:     1     2     3     4     5     6     7     8     9    10
/*A =  1*/   -3.0, -2.0, -1.0,  0.0,  1.0,  2.0,  3.0,  4.0,  5.0,  6.0, 
/*A =  2*/   -2.0,  0.0,  2.0,  4.0,  6.0,  8.0, 10.0, 12.0, 14.0, 16.0, 
/*A =  3*/   -1.0,  2.0,  5.0,  8.0, 11.0, 14.0, 17.0, 20.0, 23.0, 26.0, 
};

TEST_P(MyTest, TestFormula)
{
    double res = MyFormula(m_A, m_B, m_C);
    ASSERT_EQ(ExpectedRes[Index], res);
}

INSTANTIATE_TEST_CASE_P(TestWithParameters,  
                        MyTest,  
                        testing::Combine( testing::Range(1.0, 3.0), // C
                                          testing::Range(1.0, 4.0), // A 
                                          testing::Range(1.0, 11.0) // B
                                          ));  
Run Code Online (Sandbox Code Playgroud)

这是一个好方法还是有更好的方法来获得每次运行的正确预期结果?

Rob*_*edy 10

包括预期结果和输入.而不是输入值的三倍,使您的测试参数为4元组.

class MyTest: public ::testing::TestWithParam<
  std::tr1::tuple<double, double, double, double>>
{ };

TEST_P(MyTest, TestFormula)
{
  double const C = std::tr1::get<0>(GetParam());
  double const A = std::tr1::get<1>(GetParam());
  double const B = std::tr1::get<2>(GetParam());
  double const result = std::tr1::get<3>(GetParam());

  ASSERT_EQ(result, MyFormula(A, B, C));
}
Run Code Online (Sandbox Code Playgroud)

缺点是您将无法简化测试参数testing::Combine.相反,您可以使用它testing::Values来定义您想要测试的每个不同的4元组.您可能会达到参数计数限制Values,因此您可以拆分实例化,例如将所有C = 1个案例放在一个案例中,将所有C = 2个案例放在另一个案例中.

INSTANTIATE_TEST_CASE_P(
  TestWithParametersC1, MyTest, testing::Values(
    //           C     A     B
    make_tuple( 1.0,  1.0,  1.0,  0.0),
    make_tuple( 1.0,  1.0,  2.0,  1.0),
    make_tuple( 1.0,  1.0,  3.0,  2.0),
    // ...
  ));  

INSTANTIATE_TEST_CASE_P(
  TestWithParametersC2, MyTest, testing::Values(
    //           C     A     B
    make_tuple( 2.0,  1.0,  1.0, -3.0),
    make_tuple( 2.0,  1.0,  2.0, -2.0),
    make_tuple( 2.0,  1.0,  3.0, -1.0),
    // ...
  ));
Run Code Online (Sandbox Code Playgroud)

或者,您可以将所有值放在与实例化分开的数组中,然后使用testing::ValuesIn:

std::tr1::tuple<double, double, double, double> const FormulaTable[] = {
  //           C     A     B
  make_tuple( 1.0,  1.0,  1.0,  0.0),
  make_tuple( 1.0,  1.0,  2.0,  1.0),
  make_tuple( 1.0,  1.0,  3.0,  2.0),
  // ...
  make_tuple( 2.0,  1.0,  1.0, -3.0),
  make_tuple( 2.0,  1.0,  2.0, -2.0),
  make_tuple( 2.0,  1.0,  3.0, -1.0),
  // ...
};

INSTANTIATE_TEST_CASE_P(
  TestWithParameters, MyTest, ::testing::ValuesIn(FormulaTable));
Run Code Online (Sandbox Code Playgroud)


Dan*_*anT 0

我在单元测试方面没有太多经验,但作为一名数学家,我认为你能做的并不多。

如果您知道公式的一些不变量,您可以测试它们,但我认为这仅在极少数情况下有意义。

举个例子,如果你想测试,如果你已经正确实现了自然指数函数,你可以利用它的导数应该与函数本身具有相同值的知识。然后,您可以计算一百万个点的导数的数值近似值,并查看它们是否接近实际函数值。