如何在具有多个测试.cpps的头文件中使用INSTANTIATE_TEST_CASE_P?

时间:2019-03-12 19:29:59

标签: c++ googletest

假设我在头文件Fixtures.h中定义了一个GTest夹具:

 class baseFixture : public ::testing::Test{
   // some shared functionality among tests
 }

以及允许进行一些参数化的派生夹具:

class derivedFixture: public baseFixture, 
  public ::testing::WithParamInterface<std::tuple<bool, int>>{};

我想与INSTANTIATE_TEST_CASE_P一起使用,以便对分布在N个.cpp文件中的大量测试进行参数化。我想在标题中写:

INSTANTIATE_TEST_CASE_P(derivedTests, derivedFixture, 
  ::testing::Combine(::testing::Bool(), ::testing::Values(1));

为了运行{true,false}和{1}的叉积测试集。当我只编译一个cpp文件时,将其命名为N1.cpp,然后运行可执行文件,通过TEST_P(derivedFixture*测试,我得到了正确的行为-它们每次运行两次。但是,当我构建整个项目并执行测试时,每个测试将运行2 * N次。我在头文件中使用过包含防护措施来防止两次调用INSTANTIATE宏,并且很肯定我不会在其他任何地方调用它。

1 个答案:

答案 0 :(得分:0)

您正在做的本质上是这样的:

fixture.hpp(1)

#ifndef FIXTURE_HPP
#define FIXTURE_HPP

#include <gtest/gtest.h>

struct fixture: ::testing::TestWithParam<std::tuple<bool, int>>
{};

INSTANTIATE_TEST_CASE_P(instantiation_one, fixture,
  ::testing::Combine(::testing::Bool(), ::testing::Values(1)));

#endif

t1.cpp

#include "fixture.hpp"
#include <tuple>

TEST_P(fixture, test_a)
{
    auto const & param = GetParam();
    std::cout << "param 0 = " << std::get<0>(param) << std::endl;
    std::cout << "param 1 = " << std::get<1>(param) << std::endl;
    SUCCEED();
}

t2.cpp

#include "fixture.hpp"
#include <tuple>

TEST_P(fixture, test_b)
{
    auto const & param = GetParam();
    std::cout << "param 0 = " << std::get<0>(param) << std::endl;
    std::cout << "param 1 = " << std::get<1>(param) << std::endl;
    SUCCEED();
}

main.cpp(1)

#include <gtest/gtest.h>

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

编译,链接并运行:

$ ./gtester
[==========] Running 8 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 8 tests from instantiation_one/fixture
[ RUN      ] instantiation_one/fixture.test_a/0
param 0 = 0
param 1 = 1
[       OK ] instantiation_one/fixture.test_a/0 (0 ms)
[ RUN      ] instantiation_one/fixture.test_a/1
param 0 = 1
param 1 = 1
[       OK ] instantiation_one/fixture.test_a/1 (0 ms)
[ RUN      ] instantiation_one/fixture.test_a/0
param 0 = 0
param 1 = 1
[       OK ] instantiation_one/fixture.test_a/0 (0 ms)
[ RUN      ] instantiation_one/fixture.test_a/1
param 0 = 1
param 1 = 1
[       OK ] instantiation_one/fixture.test_a/1 (0 ms)
[ RUN      ] instantiation_one/fixture.test_b/0
param 0 = 0
param 1 = 1
[       OK ] instantiation_one/fixture.test_b/0 (0 ms)
[ RUN      ] instantiation_one/fixture.test_b/1
param 0 = 1
param 1 = 1
[       OK ] instantiation_one/fixture.test_b/1 (0 ms)
[ RUN      ] instantiation_one/fixture.test_b/0
param 0 = 0
param 1 = 1
[       OK ] instantiation_one/fixture.test_b/0 (0 ms)
[ RUN      ] instantiation_one/fixture.test_b/1
param 0 = 1
param 1 = 1
[       OK ] instantiation_one/fixture.test_b/1 (0 ms)
[----------] 8 tests from instantiation_one/fixture (0 ms total)

[----------] Global test environment tear-down
[==========] 8 tests from 1 test case ran. (1 ms total)
[  PASSED  ] 8 tests.

您预计会在预期的4个测试中看到8个测试,每个instantiation_one/fixture.test_a/N运行两次,对于{0,1}中的N

错误是这样的:我们这样做:

INSTANTIATE_TEST_CASE_P(instantiation_one, fixture,
  ::testing::Combine(::testing::Bool(), ::testing::Values(1)));
fixture.hpp中的

,它是#include版,因此在每个中重复 转换单元 tN.cpp,导致注册了2个参数化测试 将此代码在运行时N次注册,因此运行N次。

我们应该编译一个值参数化夹具的每个实例 对于给定的一组值仅一次 ,因此仅在一个源文件中进行操作,例如

fixture.hpp(2)

#ifndef FIXTURE_HPP
#define FIXTURE_HPP

#include <gtest/gtest.h>

struct fixture: ::testing::TestWithParam<std::tuple<bool, int>>
{};


#endif

main.cpp(2)

#include <gtest/gtest.h>
#include "fixture.hpp"

INSTANTIATE_TEST_CASE_P(instantiation_one, fixture,
  ::testing::Combine(::testing::Bool(), ::testing::Values(1)));

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

重新编译,重新链接并重新运行:

$ g++ -Wall -Wextra -c main.cpp t1.cpp t2.cpp
$ g++ -o gtester main.o t1.o t2.o -lgtest -pthread
$ ./gtester
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from instantiation_one/fixture
[ RUN      ] instantiation_one/fixture.test_a/0
param 0 = 0
param 1 = 1
[       OK ] instantiation_one/fixture.test_a/0 (0 ms)
[ RUN      ] instantiation_one/fixture.test_a/1
param 0 = 1
param 1 = 1
[       OK ] instantiation_one/fixture.test_a/1 (0 ms)
[ RUN      ] instantiation_one/fixture.test_b/0
param 0 = 0
param 1 = 1
[       OK ] instantiation_one/fixture.test_b/0 (1 ms)
[ RUN      ] instantiation_one/fixture.test_b/1
param 0 = 1
param 1 = 1
[       OK ] instantiation_one/fixture.test_b/1 (0 ms)
[----------] 4 tests from instantiation_one/fixture (1 ms total)

[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (1 ms total)
[  PASSED  ] 4 tests.