为 Google 测试夹具指定构造函数参数
Specify constructor arguments for a Google test Fixture
使用 Google test 我想指定一个 Test fixture 用于不同的测试用例。
fixture 应分配和释放 class TheClass
及其数据管理 class TheClassData
的对象,其中数据管理 class 需要数据文件的名称。
对于不同的测试,文件名应该不同。
我定义了以下夹具:
class TheClassTest : public ::testing::Test {
protected:
TheClassTest(std::string filename) : datafile(filename) {}
virtual ~TheClassTest() {}
virtual void SetUp() {
data = new TheClassData(datafile);
tc = new TheClass(data);
}
virtual void TearDown() {
delete tc;
delete data;
}
std::string datafile;
TheClassData* data;
TheClass* tc;
};
现在,不同的测试应该使用不同文件名的fixture。
把这想象成建立一个测试环境。
问题:如何从测试中指定文件名,即如何调用夹具的非默认构造函数?
我发现了 ::testing::TestWithParam<T>
和 TEST_P
之类的东西,这没有帮助,因为我不想 运行 一个测试具有不同的值,但不同的测试具有一个灯具。
根据另一位用户的建议,您无法实现您想要的
通过使用非默认构造函数实例化夹具。然而,
还有其他方法。只需重载 SetUp
函数和
在测试中显式调用该版本:
class TheClassTest : public ::testing::Test {
protected:
TheClassTest() {}
virtual ~TheClassTest() {}
void SetUp(const std::string &filename) {
data = new TheClassData(filename);
tc = new TheClass(data);
}
virtual void TearDown() {
delete tc;
delete data;
}
TheClassData* data;
TheClass* tc;
};
现在在测试中只需使用此重载来设置文件名:
TEST_F(TheClassTest, MyTestCaseName)
{
SetUp("my_filename_for_this_test_case");
...
}
无参TearDown
会自动清理
测试完成。
使用当前 class 作为灯具的基础 class:
class TheClassTestBase : public ::testing::Test {
protected:
TheClassTestBase(std::string filename) : datafile(filename) {}
...
};
对于每个特定的文件名 - 使用派生夹具:
class TheClassTestForFooTxt : public TheClassTestBase {
protected:
TheClassTestForFooTxt() : TheClassTestBase ("foo.txt") {}
};
然而,这是每组参数都需要的额外步骤 - 因此您可以尝试使用模板或宏来轻松完成它。喜欢:
template <typename ClassTestTag>
struct ClassTestParams
{
static std::string filename;
};
template<typename ClassTestTag>
class TheClassTest : public TheClassTestBase {
protected:
TheClassTest() : TheClassTestBase (ClassTestParams<ClassTestTag>::filename) {}
};
然后 - 对于每组参数 - 这样做:
class FooTxtTag {};
template <> std::string ClassTestParams<FooTxtTag>::value = "foo.txt";
using TheClassTestForFooTxt = TheClassTest<FooTxtTag>;
TEST_F(TheClassTestForFooTxt, xxxx) {}
但是 - 在您的具体情况下 - 我也会尝试 GoogleTest:type-parameterized-tests。
对于这个具体案例,我觉得完全摆脱测试夹具要容易得多。 SetUp
函数可以替换为一个辅助函数,该函数使用所需的文件名实例化 class。这允许使用 TEST
而不是 TEST_P
或 TEST_F
。现在每个测试用例都是一个独立的测试,它使用辅助函数或直接在测试用例的主体中创建自己的测试 class 实例。
例如:
using namespace testing;
TEST(FooClassTest, testCase1)
{
FooClass fooInstance("File_name_for_testCase1.txt");
/* The test case body*/
delete fooInstance;
}
另一个解决这个问题的好方法是扩展你的装置,在扩展的 class 中提供一个新的默认构造函数,它使用你需要的参数调用旧的构造函数。例如:
struct MySpecializedTestFixture : public GenericTestFixture
{
MySpecializedTestFixture() : GenericTestFixture("a thing", "another thing") {}
};
TEST_F(MySpecializedTestFixture, FancyTest)
{
// Use the thing environment and make some assertions.
}
如果按照建议重载 SetUp
方法 ,并且要确保记住使用重载的 SetUp
,可以在 TearDown
方法。
class my_fixture : public ::testing::Test
{
protected:
bool SETUP_HIT_FLAG = false;
void SetUp(double parameter)
{
...
SETUP_HIT_FLAG = true;
}
void TearDown() override
{
assert(SETUP_HIT_FLAG && "You forgot to call SetUp with your parameter!");
}
};
使用 Google test 我想指定一个 Test fixture 用于不同的测试用例。
fixture 应分配和释放 class TheClass
及其数据管理 class TheClassData
的对象,其中数据管理 class 需要数据文件的名称。
对于不同的测试,文件名应该不同。
我定义了以下夹具:
class TheClassTest : public ::testing::Test {
protected:
TheClassTest(std::string filename) : datafile(filename) {}
virtual ~TheClassTest() {}
virtual void SetUp() {
data = new TheClassData(datafile);
tc = new TheClass(data);
}
virtual void TearDown() {
delete tc;
delete data;
}
std::string datafile;
TheClassData* data;
TheClass* tc;
};
现在,不同的测试应该使用不同文件名的fixture。 把这想象成建立一个测试环境。
问题:如何从测试中指定文件名,即如何调用夹具的非默认构造函数?
我发现了 ::testing::TestWithParam<T>
和 TEST_P
之类的东西,这没有帮助,因为我不想 运行 一个测试具有不同的值,但不同的测试具有一个灯具。
根据另一位用户的建议,您无法实现您想要的
通过使用非默认构造函数实例化夹具。然而,
还有其他方法。只需重载 SetUp
函数和
在测试中显式调用该版本:
class TheClassTest : public ::testing::Test {
protected:
TheClassTest() {}
virtual ~TheClassTest() {}
void SetUp(const std::string &filename) {
data = new TheClassData(filename);
tc = new TheClass(data);
}
virtual void TearDown() {
delete tc;
delete data;
}
TheClassData* data;
TheClass* tc;
};
现在在测试中只需使用此重载来设置文件名:
TEST_F(TheClassTest, MyTestCaseName)
{
SetUp("my_filename_for_this_test_case");
...
}
无参TearDown
会自动清理
测试完成。
使用当前 class 作为灯具的基础 class:
class TheClassTestBase : public ::testing::Test {
protected:
TheClassTestBase(std::string filename) : datafile(filename) {}
...
};
对于每个特定的文件名 - 使用派生夹具:
class TheClassTestForFooTxt : public TheClassTestBase {
protected:
TheClassTestForFooTxt() : TheClassTestBase ("foo.txt") {}
};
然而,这是每组参数都需要的额外步骤 - 因此您可以尝试使用模板或宏来轻松完成它。喜欢:
template <typename ClassTestTag>
struct ClassTestParams
{
static std::string filename;
};
template<typename ClassTestTag>
class TheClassTest : public TheClassTestBase {
protected:
TheClassTest() : TheClassTestBase (ClassTestParams<ClassTestTag>::filename) {}
};
然后 - 对于每组参数 - 这样做:
class FooTxtTag {};
template <> std::string ClassTestParams<FooTxtTag>::value = "foo.txt";
using TheClassTestForFooTxt = TheClassTest<FooTxtTag>;
TEST_F(TheClassTestForFooTxt, xxxx) {}
但是 - 在您的具体情况下 - 我也会尝试 GoogleTest:type-parameterized-tests。
对于这个具体案例,我觉得完全摆脱测试夹具要容易得多。 SetUp
函数可以替换为一个辅助函数,该函数使用所需的文件名实例化 class。这允许使用 TEST
而不是 TEST_P
或 TEST_F
。现在每个测试用例都是一个独立的测试,它使用辅助函数或直接在测试用例的主体中创建自己的测试 class 实例。
例如:
using namespace testing;
TEST(FooClassTest, testCase1)
{
FooClass fooInstance("File_name_for_testCase1.txt");
/* The test case body*/
delete fooInstance;
}
另一个解决这个问题的好方法是扩展你的装置,在扩展的 class 中提供一个新的默认构造函数,它使用你需要的参数调用旧的构造函数。例如:
struct MySpecializedTestFixture : public GenericTestFixture
{
MySpecializedTestFixture() : GenericTestFixture("a thing", "another thing") {}
};
TEST_F(MySpecializedTestFixture, FancyTest)
{
// Use the thing environment and make some assertions.
}
如果按照建议重载 SetUp
方法 SetUp
,可以在 TearDown
方法。
class my_fixture : public ::testing::Test
{
protected:
bool SETUP_HIT_FLAG = false;
void SetUp(double parameter)
{
...
SETUP_HIT_FLAG = true;
}
void TearDown() override
{
assert(SETUP_HIT_FLAG && "You forgot to call SetUp with your parameter!");
}
};