如何使用Google Test在main()函数中的特定位置调用特定的测试函数?
我使用TDD和Google Test进行涉及数值模拟的项目。数据的状态在 main
函数中的一个循环内改变,但是每次更改后都需要满足这些要求。如果测试用例满足所有要求,验收测试通过:
I am using TDD and Google Test for a project that involves numerical simulations. The state of the data gets changed within a loop in the main
function, but there are requirements that need to be fulfilled after each change. If all requirements are fulfilled for a test case, the acceptance test passed:
while(simulation)
modify simulation data
FIRST_TEST()
some other simulation operations
SECOND_TEST()
GTest引擎说明通常调用RUN_ALL_TESTS()。 高级指南显示了如何运行子测试,通过。但是,我想知道如何单独调用测试。
The GTest primer states that usually RUN_ALL_TESTS() is called. The Advanced Guide shows how to run sub-tests, by filtering out tests from RUN_ALL_TESTS. However, I would like to know how to invoke tests individually.
否则,我需要编写一个新的验收测试应用程序,每次我需要一个新的测试,如FIRST_和SECOND_
Otherwise I would need to write a new acceptance testing application each time I need a new test like FIRST_ and SECOND_ in the pseudocode snippet above.
更多背景:我使用OpenFOAM框架计算流体动力学,因此在 main之外创建全局夹具
不是一个选项。模拟应用程序需要运行目录和配置文件,并且main中的全局对象是相关的(需要彼此进行初始化)。此类应用程序的一个示例是 OpenFOAM-2.2.x 。
Some more background: I’m using the OpenFOAM framework for Computational Fluid Dynamics, so creating global fixtures outside of main
is not an option. The simulation application requires a directory and configuration files to run, and the global objects in main are correlated (require each other for initialization). One example of such an application is OpenFOAM-2.2.x.
我接受了接受的答案,关于如何在 Stack Overflow上的另一个问题中找到的测试中使用argc和argv作为全局变量的答案,我总结了到这个可编译的小模型,也许有人发现它有用:
I took the accepted answer as well as the answer on how to use argc and argv as global variables within the test found on another question on Stack Overflow and I summarized this into this compile-able small model, maybe someone finds it useful:
#include <gtest/gtest.h>
#include <iostream>
class Type
{
int value_ = 0;
int times_ = 1;
public:
Type(int x) : value_(x) {};
void operator()(){
if (times_ < 10) {
++times_;
value_ *= times_;
}
}
int value () const { return value_; }
};
class mySeparatedTests : public ::testing::Test
{
protected:
template<typename Type>
void TEST_ONE(Type const &t)
{
ASSERT_TRUE((t.value() % 2) == 0);
}
template<typename Type>
void TEST_TWO(Type const & t)
{
ASSERT_TRUE((t.value() - 5) > 0);
}
};
TEST_F(mySeparatedTests, testName)
{
extern char** globalArgv;
char** argv = globalArgv;
// Simulation parameters and objects requiring argc and argv for initialization.
int simulationEndTime;
*argv[1] >> simulationEndTime;
Type typeObject(*argv[2]);
TEST_ONE(typeObject);
// Simulation loop.
for (int i = 0; i < simulationEndTime; ++i)
{
typeObject();
TEST_TWO(typeObject);
}
}
int globalArgc;
char** globalArgv;
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
globalArgc = argc;
globalArgv = argv;
return RUN_ALL_TESTS();
return 0;
}
这种方法,如接受的答案所述, code> main 到TEST_F,并使用 mySeparatedTests
类函数来定义单个测试,然后可以在任何地方调用。编译时使用:
This approach, as described in the accepted answer, ports the simulation code from main
into TEST_F, and uses the mySeparatedTests
class functions to define individual tests, that can then be called anywhere. This is compiled with:
g++ -std=c++11 -l gtest main.cpp -o main
并且测试失败/通过取决于解析的参数对;
And tests fail/pass depending on parsed parameter pairs;
这会失败:
./main 1 1
这将成功:
./main 2 2
注意:的char / int转换发生;这只是为了显示如何拾取参数。
Note: I’m aware of char/int conversion happening; this is just to show how to pick up args.
我的猜测是,你有点误解googletest的作用。测试序列的控制由测试运行器控制。你可以做的是用和
循环定义一个单独的测试,区别在于你的 FIRST_TEST
等是函数一个夹具,有一些断言。例如:
My guess is that you have slightly misunderstood what googletest does. The control of the test sequence is controlled by the test runner. What you could do is define a single test with your while
loop with the difference that your FIRST_TEST
, etc are functions of a fixture, with some assertions. For example:
而不是:
int main(...) { ... while (...) PERFORM_TEST("A"); ... }
TEST(A,some_test) {}
googletest runner main and define:
you could take the standard googletest runner main and define:
// fixture
class MyTest : public ::testing::Test {
protected:
bool simulation() {
///...
}
void TEST_A() {
ASSERT_EQ(...);
//...
}
void TEST_B() {
ASSERT_EQ(...);
//...
}
///
};
// the test "runner"
TEST_F(MyTest, main_test) {
while (simulation()) {
// modify simulation data
TEST_A();
// some other simulation operations
TEST_B();
}
}