Is there a way to detect command line arguments not running tests? - c++

Using the googletest framework I want to write my own main function. Basically some custom initialization step needs to happen before RUN_ALL_TESTS is called. I'd like to skip this step, if the command line parameters for googletest indicate, no tests should be run (e.g. if --gtest_list_tests is passed).
Is it possible to retrieve this kind of information from the test framework without the need to parse the parameters myself?
What I'd like to accomplish:
#include <gtest/gtest.h>
bool RunAllTestsDoesNotRunTests()
{
// should return false, if and only if RUN_ALL_TESTS() runs any test cases
// implementation?
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
if (!RunAllTestsDoesNotRunTests())
{
DoExpensiveInitialization();
}
return RUN_ALL_TESTS();
}
Is this even possible? I've tried to identify members of ::testing::UnitTest, that would allow me to retrieve this kind of information, without any success so far though.
Am I going at this the wrong way? Preferrably I'd like to avoid lazily doing the initialization via fixture or similar logic requiring me to adjust every test case.

There are various flags that might prevent google test from running any tests. I can think of at least the following:
--gtest_list_tests is passed.
--gtest_repeat=0 is passed.
--help or other forms of it like -h or any unrecognized flag with gtest prefix is passed See here.
You can test these cases by:
The first can be checked using ::testing::GTEST_FLAG(list_tests). See here.
The second can be tested using ::testing::GTEST_FLAG(repeat).
The third can be checked by reading the global variable g_help_flag. While practical, this is not ideal because it's in the internal namespace and might change in future releases.
Another alternative is to parse the command line arguments yourself.
So assuming you want to be practical, one way to get to what you want is this:
// Defining g_help_flag as an extern variable
namespace testing {
namespace internal {
extern bool g_help_flag;
}
}
bool RunAllTestsDoesNotRunTests()
{
// should return false, if and only if RUN_ALL_TESTS() runs any test cases
// implementation?
return ( ::testing::GTEST_FLAG(list_tests) ||
::testing::GTEST_FLAG(repeat) == 0 ||
::testing::internal::g_help_flag);
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
if (!RunAllTestsDoesNotRunTests())
{
// DoExpensiveInitialization();
std::cout << "Expensive initialization!" << std::endl;
} else {
std::cout << "No Expensive initialization!" << std::endl;
}
return RUN_ALL_TESTS();
}
Live example: https://godbolt.org/z/P36fde11T

command line arguments are detected using the GTEST_FLAG macro. An example of what you're trying to do might look like:
#include <gtest/gtest.h>
TEST(equality, always_passes) {
EXPECT_TRUE(true);
}
bool RunAllTestsDoesNotRunTests()
{
return ::testing::GTEST_FLAG(list_tests);
}
void DoExpensiveInitialization() {
std::cout << "Boop Boop, Beep Beep" << std::endl;
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
if (!RunAllTestsDoesNotRunTests())
{
DoExpensiveInitialization();
}
return RUN_ALL_TESTS();
}
When compiled and linked appropriately, it can be run as:
$ ./a.out
Boop Boop, Beep Beep
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from equality
[ RUN ] equality.always_passes
[ OK ] equality.always_passes (0 ms)
[----------] 1 test from equality (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
$ ./a.out --gtest_list_tests
equality.
always_passes
i.e. you don't see the Boop Boop, Beep Beep as the function was not called.
Now if you have something that you want to have run once, if you're running tests, then adding it to the testing::Environment would also do the trick:
#include <gtest/gtest.h>
class MyEnvironment: public ::testing::Environment
{
public:
virtual ~MyEnvironment() = default;
// Override this to define how to set up the environment.
virtual void SetUp() { std::cout << "Env Beep Beep" << std::endl; }
// Override this to define how to tear down the environment.
virtual void TearDown() {}
};
TEST(equality, always_passes) {
EXPECT_TRUE(true);
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
auto* env = new MyEnvironment();
::testing::AddGlobalTestEnvironment(env);
return RUN_ALL_TESTS();
}
When executed, it will also cope with filters (the previous example would not be able to cope in that case):
$ ./a.out --gtest_filter=equality\*
Note: Google Test filter = equality*
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
Env Beep Beep
[----------] 1 test from equality
[ RUN ] equality.always_passes
[ OK ] equality.always_passes (0 ms)
[----------] 1 test from equality (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
$ ./a.out --gtest_filter=equality\* --gtest_list_tests
equality.
always_passes
Again, not that the Env Beep Beep does not appear if you don't run any tests (you can check with a filter like --gtest_filter=equality, and you won't see the Env output in that case.

Related

How to test boost logger output in unit testing?

My application uses BOOST_LOG_TRIVIAL to log messages. I thought it's good to check in test (gtest) that correct messages are written there in given scenarios.
Is there a way to somehow access what was written there after code was called? Or does it first have to be mocked in some way?
I have googled a lot for this and haven't found any instructions, so either I am asking wrong questions or no one thinks it should be done.
In your googletest suite, you can use the boost::log facilities in
each test case to redirect the BOOST_LOG_TRIVIAL messages to a file.
After writing the BOOST_LOG_TRIVIAL message(s) you want you can then
flush the file, open it, and check that it has the contents you expect.
For example:
gtester.cpp
#include <gtest/gtest.h>
#include <boost/shared_ptr.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/trivial.hpp>
#include <string>
#include <fstream>
using sink_t = boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>;
struct boost_log_tester : ::testing::Test {
void SetUp() {
file_sink = boost::log::add_file_log("boost.log");
}
void TearDown() {
boost::log::core::get()->remove_sink(file_sink);
file_sink.reset();
}
protected:
boost::shared_ptr<sink_t> file_sink;
};
TEST_F(boost_log_tester,info_msg)
{
std::string msg = "An informational severity message";
BOOST_LOG_TRIVIAL(info) << msg;
file_sink->flush();
std::ifstream captured_cout("boost.log");
ASSERT_TRUE(captured_cout.good()) << "Failure executing test: Could not open `boost.log` for reading";
std::string cout_str;
std::getline(captured_cout,cout_str);
EXPECT_NE(cout_str.find(msg),std::string::npos);
}
TEST_F(boost_log_tester,error_msg)
{
std::string msg = "An error severity message";
BOOST_LOG_TRIVIAL(error) << msg;
file_sink->flush();
std::ifstream captured_cerr("boost.log");
ASSERT_TRUE(captured_cerr.good()) << "Failure executing test: Could not open `boost.log` for reading";
std::string cerr_str;
std::getline(captured_cerr,cerr_str);
EXPECT_NE(cerr_str.find(msg),std::string::npos);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Compile and link:
$ g++ -Wall -Wextra -DBOOST_LOG_DYN_LINK -c gtester.cpp
$ g++ -o gtester gtester.o -lboost_log -lboost_thread -lboost_system -lgtest -pthread
And it runs like:
$ ./gtester
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from boost_log_tester
[ RUN ] boost_log_tester.info_msg
[ OK ] boost_log_tester.info_msg (0 ms)
[ RUN ] boost_log_tester.error_msg
[ OK ] boost_log_tester.error_msg (2 ms)
[----------] 2 tests from boost_log_tester (2 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (2 ms total)
[ PASSED ] 2 tests.
Following Mike's answer, in which I think necessity of file creation is a downside, I did a bit of research and found this way of using a stringstream instead:
class boost_logger_test : public testing::Test
{
typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend> sink_t;
boost::shared_ptr<sink_t> streamSink;
std::stringstream ss;
public:
virtual void SetUp()
{
streamSink = boost::log::add_console_log(ss);
}
virtual void TearDown()
{
boost::log::core::get()->remove_sink(streamSink);
streamSink.reset();
}
std::vector<std::string> getLogMessages()
{
std::vector<std::string> messages;
std::string msg;
while (std::getline(ss, msg, '\n'))
{
messages.push_back(msg);
}
return messages;
}
}
Then you could easily use messages in tests, like:
ASSERT_THAT(getLogMessages(), ElementsAre("Just some log message"));

When there is a failure in ASSERT_ macro of gtest, the TearDown function will be called or not?

Will the TearDown function be called when the ASSERT_EQ fails in google test? Or it just cancel that test case and move to the next one without TearDown? This is because in my TearDown function, I need to do something to properly shutdown the test function, so I'm afraid that this ASSERT will make my test not independent.
It's not hard to satisfy yourself that TearDown is always run, regardless
of whether an ASSERT_... macro fails:
testcase.cpp
#include <gtest/gtest.h>
#include <iostream>
struct foo : ::testing::Test
{
void SetUp()
{
std::cout << ">>>" << __PRETTY_FUNCTION__ << " was run " << std::endl;
}
void TearDown()
{
std::cout << ">>>" << __PRETTY_FUNCTION__ << " was run " << std::endl;
}
};
TEST_F(foo,bar)
{
ASSERT_EQ(1,0);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Compile and link:
g++ -o testcase testcase.cpp -lgtest -pthread
Run:
$ ./testcase
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from foo
[ RUN ] foo.bar
>>>virtual void foo::SetUp() was run
testcase.cpp:19: Failure
Expected equality of these values:
1
0
>>>virtual void foo::TearDown() was run
[ FAILED ] foo.bar (0 ms)
[----------] 1 test from foo (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] foo.bar
1 FAILED TEST

Test Cases states Failed but value returned is true

I have written up a simple sample code to understand GMOCK used for unit testing:
#include <iostream>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::AtLeast;
class A {
public:
void ShowPub1()
{
std::cout << "A::PUBLIC::SHOW..1" << std::endl;
}
int ShowPub2(int x)
{
std::cout << "A::PUBLIC::SHOW..2" << std::endl;
return true;
}
};
class MockA : public A{
public:
MOCK_METHOD0(ShowPub1, void());
MOCK_METHOD1(ShowPub2, int(int x));
};
Below is my test code - I just wish to call ShowPub2 method of class A. I was expecting the statement A::PUBLIC::SHOW..2 to get printed at console - but it just did not happen and the test case also failed though the method is hardcoded to return true:
TEST(FirstA, TestCall) {
MockA a;
EXPECT_CALL(a, ShowPub2(2))
.Times(AtLeast(1));
a.ShowPub2(2);
EXPECT_TRUE(a.ShowPub2(2));
}
GMOCK test code execution output - I am not sure why the output A::PUBLIC::SHOW..2 did not rendered in console and test case failed:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from FirstA
[ RUN ] FirstA.TestCall
c:\users\user1\documents\c and c++\gmock\gmock1\gmock1\gmock1.cpp(78): error:
Value of: a.ShowPub2(2)
Actual: false
Expected: true
[ FAILED ] FirstA.TestCall (0 ms)
[----------] 1 test from FirstA (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] FirstA.TestCall
1 FAILED TEST
Press any key to continue . . .
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
return 0;
}
Some clarification is needed here..
Creating a Mock class means that the Mock methods are generate with its own implementations. These line of code
MOCK_METHOD0(ShowPub1, void());
MOCK_METHOD1(ShowPub2, int(int x));
doesn't mean it will call parent implementation of ShowPub1 / ShowOub2. This only means that you'll get a function (Mock) with same signature as that of the class you're mocking.
The test fails because of this line
EXPECT_TRUE(a.ShowPub2(2));
Since the original implementation is not called, this function fails.
The test function should be written as
TEST(FirstA, TestCall) {
MockA a;
EXPECT_CALL(a, ShowPub2(2)) .Times(AtLeast(1));
a.ShowPub2(2);
}
Here you're testing the behavior that the function is called at least once and the test will be successful with that.
If you want to test the functionality of a function, write separate tests. Mocking will not solve the problem in this case.

Is it possible to mock a called function return value using gtest or gmock?

I am new to gtest and gmock please let me understand how to mock the called function. Which will also help me in code coverage.
#include <stdio.h>
#include "gtest/gtest.h"
int ret()
{
return 5;
}
class A
{
public:
A();
int a;
int func();
};
A::A()
{
printf("This is constructor\n");
}
int A::func()
{
int iRet = ret(); /* When func() is called by gtest I would like to control the return value of ret() */
int iRet1 = ret();
/* Based on these two values some operations to be done */
printf("This is func. %d, %d\n", iRet, iRet1);
return iRet;
}
TEST (abc, xyz) {
A a;
EXPECT_EQ(5, a.func()); /* Here how to get different values of iRet and iRet1 for ret() function? */
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
In case if it is not possible through gtest and/or gmock, please suggest me any other tool for the same.
Also I tried with the following thing which is not working as expected:
int ret()
{
printf("Returning 5\n");
return 5;
}
int ret1()
{
int iRet = 10;
printf("Inside ret1\n");
iRet = ret();
if (iRet == 5)
{
printf("Original ret is called\n");
}
else if (iRet == 100)
{
printf("This is mocked function call\n");
}
else
{
printf("Opps! This should not happen\n");
}
return iRet;
}
class FooMock {
public:
MOCK_METHOD0(ret, int());
MOCK_METHOD0(ret1, int());
};
TEST (abc, xyz) {
FooMock mock;
EXPECT_CALL(mock, ret()).Times(1).WillOnce(Return(100));
mock.ret1();
}
int main(int argc, char **argv)
{
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
While running giving me the following error:
$ ./a.out
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from abc
[ RUN ] abc.xyz
gtest.cpp:86: Failure
Actual function call count doesn't match EXPECT_CALL(mock, ret())...
Expected: to be called once
Actual: never called - unsatisfied and active
gtest.cpp:87: Failure
Actual function call count doesn't match EXPECT_CALL(mock, ret())...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] abc.xyz (0 ms)
[----------] 1 test from abc (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] abc.xyz
1 FAILED TEST
Please let me know if anything I am doing wrong...
So, the idea of unit-testing is that you run some of your code and that you compare the results to what you expect to be the result. Your code makes it more complicated than it has to be. E.g.
#include <stdio.h>
#include "gtest/gtest.h"
int incBy5(const int a) {
return a+5;
}
TEST (abc, xyz) {
int x=17;
EXPECT_EQ(x+5, incBy5(x));
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
See the documentation of unit testing concepts in general and google-test in particular. The mocking aspect of it all comes into place with more complex things to test where you may not have everything readily available (e.g. network resources, databases, ...) and you create mock-ups that can replace these resources.
In your second snippet, you define two mock methods, ret and ret1. Later, you set up an expectation on ret but invoke ret1. At the end of the test, the expectation on ret remains unfulfilled, causing gmock to complain.

googletest SetUp Method not called

I'm using Google Test to unit test my C++ project. The getting started guide says:
If necessary, write a default constructor or SetUp() function to prepare the objects for each test. A common mistake is to spell SetUp() as Setup() with a small u - don't let that happen to you.
SetUp() is spelled correctly, but I still can't get SetUp to work. Any ideas?
#include "gtest/gtest.h"
class SampleTest : public ::testing::Test {
protected:
virtual void SetUp() { std::cout << "SetUp called." << std::endl; }
};
TEST(SampleTest, OneEqualsOne) {
int one = 1;
ASSERT_EQ(1, one);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
g++ -g -Wno-deprecated -I gtest/include SampleTest.cpp gtest/libgtest.a -o SampleTest
Output:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from SampleTest
[ RUN ] SampleTest.OneEqualsOne
[ OK ] SampleTest.OneEqualsOne (1 ms)
[----------] 1 test from SampleTest (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[ PASSED ] 1 test.
Change TEST to TEST_F, as SetUp methods and such are called with TEST_F, but not with TEST alone.
Change your TEST macro to TEST_F. (It's listing in the documentation right underneath the quote you provided.)