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)
我在单元测试方面没有太多经验,但作为一名数学家,我认为你能做的并不多。
如果您知道公式的一些不变量,您可以测试它们,但我认为这仅在极少数情况下有意义。
举个例子,如果你想测试,如果你已经正确实现了自然指数函数,你可以利用它的导数应该与函数本身具有相同值的知识。然后,您可以计算一百万个点的导数的数值近似值,并查看它们是否接近实际函数值。