c++ 为Google测试夹具指定构造函数参数

tag5nh1u  于 2022-11-19  发布在  Go
关注(0)|答案(6)|浏览(425)

通过Google测试,我想指定一个测试fixture用于不同的测试用例。fixture应该分配和释放类TheClass和它的数据管理类TheClassData的对象,其中数据管理类需要一个数据文件的名称。
对于不同的测试,文件名应有所不同。
我定义了以下夹具:

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。

**问题:**如何从测试中指定文件名,即如何调用fixture的非默认构造函数?

我发现了像::testing::TestWithParam<T>TEST_P这样的东西,这没有帮助,因为我不想用不同的值运行一个测试,而是用一个fixture运行不同的测试。

kx5bkwkv

kx5bkwkv1#

正如另一位用户所建议的,使用非默认构造函数示例化fixture并不能达到你想要的效果。然而,还有其他方法。只需重载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将在测试完成时自动清除。

dfuffjeb

dfuffjeb2#

使用当前类作为设备的基类:

class TheClassTestBase : public ::testing::Test {
 protected:
  TheClassTestBase(std::string filename) : datafile(filename) {}
  ...
 };

对于每个特定的文件名-使用派生的fixture:

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:类型参数化测试。

h7appiyu

h7appiyu3#

另一个处理这个问题的好方法是扩展你的fixture,并在扩展的类中提供一个新的默认构造函数,它使用你需要的参数调用旧的构造函数。例如:

struct MySpecializedTestFixture : public GenericTestFixture
{
  MySpecializedTestFixture() : GenericTestFixture("a thing", "another thing") {}
};

TEST_F(MySpecializedTestFixture, FancyTest)
{
  // Use the thing environment and make some assertions.
}
xzlaal3s

xzlaal3s4#

如果您依照建议的here多载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!");
    }
};
wfauudbj

wfauudbj5#

使用模板的另一种方式:

template<int N>
class Fixture : public ::testing::Test { ... }

using FixtureForTest = Fixture<1000>;
TEST_F(FixtureForTest, test) { ... }
mrwjdhj3

mrwjdhj36#

对于这一具体情况,我觉得完全摆脱测试fixture要容易得多。SetUp函数可以替换为一个helper函数,该函数用所需的文件名示例化类。这允许使用TEST而不是TEST_PTEST_F。现在,每个测试用例都是一个独立的测试,它使用helper函数或直接在测试用例的主体中创建自己的测试类示例。
例如:

using namespace testing;
TEST(FooClassTest, testCase1)
{
    FooClass fooInstance("File_name_for_testCase1.txt");
    /* The test case body*/
    delete fooInstance;
}

相关问题