c++ - 如何在具有多个测试 .cpps 的头文件中使用 INSTANTIATE_TEST_CASE_P?
问题描述
假设我在头文件 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 宏被调用两次,并且很肯定我不会在其他任何地方调用它。
解决方案
你正在做的基本上是这样的:
夹具.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();
}
主.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.
在 {0,1} 中,您会看到 8 个测试,而您期望 4 个,每个测试instantiation_one/fixture.test_a/N
运行两次。N
错误是这样的:我们这样做:
INSTANTIATE_TEST_CASE_P(instantiation_one, fixture,
::testing::Combine(::testing::Bool(), ::testing::Values(1)));
in fixture.hpp
,这是#include
-ed ,因此在每个翻译单元 tN.cpp
中重复,导致此代码注册的 2 个参数化测试N
在运行时注册时间,因此运行 N 次。
我们应该为给定的一组值只编译一次值参数化夹具的每个实例化,因此只在一个源文件中进行编译,例如
夹具.hpp (2)
#ifndef FIXTURE_HPP
#define FIXTURE_HPP
#include <gtest/gtest.h>
struct fixture: ::testing::TestWithParam<std::tuple<bool, int>>
{};
#endif
主.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.
推荐阅读
- scala - 如何在 Kafka 2.0 版本中实现 SimpleConsumer?
- assembly - 如何在屏幕上打印 DX:AX 的十六进制结果?
- c# - Json 属性改变类型
- c# - 属性路由无法正常工作,指定的 URL 返回 HTTP 404 Not Found?
- c# - 当我选中复选框并单击详细信息按钮后,我需要在弹出窗口中显示选定行的详细信息
- node.js - 如何在 cognito 中解决“客户端试图写入未经授权的属性”问题?
- javascript - 来自Angular 7组件的Meterial Design javascript方法
- c# - Botframework V4:在 Messenger 中重置 Bot
- .htaccess - 如何隐藏来自用户代理之一的重定向
- php - 可以在 Symfony 3.4 中禁用特定的弃用警告吗?