Unit testing with google test - c++

I want to learn using google test framework with everyday projects, so I looked up a few tutorials, but I have no idea how to get started.
I'm using Qtcreator in Ubuntu 14.04, I downloaded gtest.zip from the google site and unzipped it, but here is where it all stoped.
This is the code i want to "gtest":
//main.cpp
#include <iostream>
#include <cstdlib>
#include "fib.h"
using namespace std;
int main(int argc, char *argv[])
{
int n = atof(argv[1]);
fib fibnumber;
cout << "\nDesired number is: " << fibnumber.fibRec(n) << endl;
}
//fib.h
#ifndef FIB_H
#define FIB_H
class fib
{
public:
int fibRec(int n);
};
#endif // FIB_H
//fib.cpp
#include "fib.h"
int fib::fibRec(int n)
{
if(n <= 0) return 0;
if(n == 1) return 1;
else return(fibRec(n-1)+fibRec(n-2));
}
So where do i even begin, I want to make unit test and compile it without any plugins, but i don't know how to make use of the file I unzipped and then use it to write a unit test.

The google Testing framework works by building it as part of your source code. That means there is no library that you have to link to, instead you build the library when you compile your code (there is a good reason for this).
Have a look at the official documentation:
https://github.com/google/googletest/blob/master/googletest/docs/primer.md
Steps
Try to build a test testcase for your program. I can't tell you how to do it with Qtcreator but that should be easy enough to find. Create a test that will definitely fail, like the one below.
TEST(MyFirstTest, ThisTestShallFail) {
EXPECT_EQ(1, 2);
}
Run this very simple test to check that it fails. If you want, change it to make it pass.
Start creating your unit tests. Check for a few easy number. Check boundary conditions etc.

In addition to #Unapiedra's suggestions, I would suggest to write a separate test file and a separate source/implementation file to test the code with google test framework and link the project using a build system or better a build generator system.
My example below demonstrates this using a cmake build generator. (My assumption here is that the user is familiar with cmake)
Note: although in practice it is recommended to write code incrementally using the Test Driven Development philosophy, I don't do it since the purpose here is to show how a simple unit test can be written and compiled using google test framework.
charOperations.hpp
#ifndef CHAR_OPERATIONS_H
#define CHAR_OPERATIONS_H
#incude <string>
class CharOperations{
private :
// ...
public:
//converts lower case characters to upper case
// and returns a std::string object from this
std::string convertToUpper(const char letter){
char upCase = std::toupper(static_cast<unsigned char>(letter));
return std::string(1, upCase);
}
//converts upper case characters to lower case
// and returns a std::string object from this
std::string convertToLower(const char letter){
char loCase = std::tolower(static_cast<unsigned char>(letter));
return std::string(1, loCase);
}
// more functions ...
};
#endif //class definition ends
test_example.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "CharOperations.hpp"
//declare a test fixture so that the object
// CharOperation need not be declared in each test
//Each test fixture has to be publicly derived from
// testing::Test
class CharOperationsTest : public testing::Test{
//class object public so that it is accessible
//within the tests that are written
public:
CharOperations charOps;
};
// now write the tests using macro TEST_F
// which is used for testing with test fixtures
//1st parameter to TEST_F is the name of the fixture
//second parameter to TEST_F is the name of the test
//each test has to have a unique name.
//test #1
TEST_F(CharOperationsTest, ConvertsCharToUpperCaseString){
ASSERT_THAT(charOps.convertToUpper('a') testing::Eq("A");
}
//test #2
TEST_F(CharOperationsTest, ConvertsCharToLowerCaseString){
ASSERT_THAT(charOps.convertToLower('A') testing::Eq("a");
}
//more tests ...
//run all tests
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.2.3)
project(TDD CXX)
enable_testing()
set(CMAKE_CXX_STANDARD 11)
find_package(PkgConfig REQUIRED)
pkg_check_modules(gtest REQUIRED gtest>=1.8.1)
pkg_check_modules(gmock REQUIRED gmock>=1.8.1)
include_directories(${gtest_INCLUDE_DIRS})
include_directories(${gmock_INCLUDE_DIRS})
add_executable(test.out ##target executable name
test_example.cpp
)
target_link_libraries(test.out ${gtest_LIBRARIES})
A general suggestion for writing tests: It can be observed in the file test_example.cpp, the Macros/Functions Test. Eq and InitGoogleTests reside under the namespace testing. Hence it might be prudent to declare a using namespace testing declaration at the beginning of the file after all #includes. Lastly needles to say to compile in a separate build directory

Related

How to use a global variable for "configurations" in multiple tests in Googletest framework

I am using Google test framework for C++. Each file includes a config.hpp which defined a global configuration variable. I would like to define my config in a variable, not a compile-time const or constexpr. How can I define the dependencies to have the same variable in different files that are linked together? Do I have to use a singleton? Can I avoid that? Is there a better recommended way to use multiple test files xUnit style?
My config file: config.hpp:
#pragma once
struct {
const float tolerance = 0.001;
// ...
} CONFIG_VAR;
Each test *.cpp source file is like:
#include "gtest/gtest.h"
#include "core/config.hpp"
TEST(a, b) { ... }
My main file:
#include "gtest/gtest.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
I compile and link using:
em++ -I $GTEST_ROOT/googletest/include main_all_tests.cpp test_*.cpp
PS. My problem is multiple definition of the variable CONFIG_VAR.
My solution is based on a related question.
Everything you need is right here at the Google Test's official repository on GitHub.
Anyway, to sharing something in the same file test you do it like that:
class YourTestCase : public ::testing::Test
{
protected:
virtual void SetUp()
{
globalObject = new YourObject();
}
virtual void TearDown() {
delete globalObject;
globalObject = nullptr;
}
Object * globalObject = nullptr;
};
so, in your test cases:
TEST_F(YourTestCase, TestOne) {
ASSERT_EQ("your value here", globalObject->getValue());
}
TEST_F(YourTestCase, TestTwo) {
ASSERT_EQ("your value here", globalObject->getValue());
}
TEST_F(YourTestCase, TestThree) {
ASSERT_EQ("your value here", globalObject->getValue());
}
Note.: Pay attention to the function's name. It is TEST_F not TEST.
On the other hand, if what you want to do it is at the test program level ― sharing something among files, you will need to set up an environment object. Something like this:
Environment * AddGlobalTestEnvironment(Environment * env);
I have never worked with that before, so I can not tell you so much about it, but there is more information at that link I shared above. Usually, global variables make the code harder to read and may cause problems. You'd be better off avoiding them.

Catch.hpp unit testing: How to dynamically create test cases?

I am using CATCH v1.1 build 14 to do unit testing of my C++ code.
As part of the testing, I would like to check the outputs of several modules in my code. There is not a set number of modules; more modules may be added at any time. However, the code to test each module is identical. Therefore, I think it would be ideal to put the testing code in a for loop. In fact, using catch.hpp, I have verified that I can dynamically create Sections within a Test Case, where each Section corresponds to a module. I can do this by enclosing the SECTION macro in a for loop, for example:
#include "catch.hpp"
#include <vector>
#include <string>
#include "myHeader.h"
TEST_CASE("Module testing", "[module]") {
myNamespace::myManagerClass manager;
std::vector<std::string> modList;
size_t n;
modList = manager.getModules();
for (n = 0; n < modList.size(); n++) {
SECTION(modList[n].c_str()) {
REQUIRE(/*insert testing code here*/);
}
}
}
(This is not a complete working example, but you get the idea.)
Here is my dilemma. I would like to test the modules independently, such that if one module fails, it will continue testing the other modules instead of aborting the test. However, the way CATCH works, it will abort the entire Test Case if a single REQUIRE fails. For this reason, I would like to create a separate Test Case for each module, not just a separate Section. I tried putting my for loop outside the TEST_CASE macro, but this code fails to compile (as I expected):
#include "catch.hpp"
#include <vector>
#include <string>
#include "myHeader.h"
myNamespace::myManagerClass manager;
std::vector<std::string> modList;
size_t n;
modList = manager.getModules();
for (n = 0; n < modList.size(); n++) {
TEST_CASE("Module testing", "[module]") {
SECTION(modList[n].c_str()) {
REQUIRE(/*insert testing code here*/);
}
}
}
It might be possible to do this by writing my own main(), but I can't see how to do it exactly. (Would I put my TEST_CASE code directly into the main()? What if I want to keep my TEST_CASE code in a different file? Also, would it affect my other, more standard Test Cases?)
I can also use CHECK macros instead of REQUIRE macros to avoid aborting the Test Case when a module fails, but then I get the opposite problem: It tries to continue the test on a module that should have failed out early on. If I could just put each module in its own Test Case, that should give me the ideal behavior.
Is there a simple way to dynamically create Test Cases in CATCH? If so, can you give me an example of how to do it? I read through the CATCH documentation and searched online, but I couldn't find any indication of how to do this.
There is a way to achieve what you're looking for, but I'd observe that you're going about this the wrong way:-
Unit tests are to meant to test each unit, i.e. you write a component and a test to verify the correct behaviour of that component. If you later decide to change one component in some way, you update the corresponding test.
If you aggregate all of your tests for all of your components into the same file, it becomes much harder to isolate the unit that behaves differently.
If you want to factor out the testing of a component because it's essentially the same across all your components, you could do one of the following:
1. Extract the common tests to a separate header file
You can #define the type name of the component you wish to test and then include a header file with all the tests in it:
// CommonTests.t.h
#include "catch.hpp"
TEST_CASE("Object Can be instantiated", "[ctor]")
{
REQUIRE_NOTHROW(COMPONENT component);
}
// SimpleComponent.t.cpp
#define COMPONENT SimpleComponent
#include "CommonTests.t.h"
This is straightforward to do, but has a downside - when you run the test runner, you'll have duplicate tests (by name) so you can only run all tests, or by tag.
You can solve this by stringizing the component name and pre/appending it to the test case name.
** 2. Call common tests by parameterising the component **
Put your common tests into a separate file and call the common test methods directly:
// CommonTests.t.h
void RunCommonTests(ComponentInterface& itf);
// CommonTests.t.cpp
void RunCommonTests(ComponentInterface& itf)
{
REQUIRE(itf.answerToLifeUniverseAndEverything() == 42);
}
// SimpleComponent.t.cpp
#include "SimpleComponent.h"
#include "CommonTest.t.h"
#include "catch.hpp"
TEST_CASE("SimpleComponent is default-constructible", "[ctor]")
{
REQUIRE_NOTHROW(SimpleComponent sc);
}
TEST_CASE("SimpleComponent behaves like common components", "[common]")
{
SimpleComponent sc;
RunCommonTests(sc);
}
It sounds like Catch might be migrating toward property-based testing, which I'm hoping will allow a way to dynamically create test cases. In the meantime, here's what I ended up doing.
I created a .cpp file with a single TEST_CASE for a single module, and a global variable for the module name. (Yes, I know global variables are evil, which is why I am being careful and using it as the last resort):
module_unit_test.cpp:
#include "catch.hpp"
#include <string>
#include "myHeader.h"
extern const std::string g_ModuleName; // global variable: module name
TEST_CASE("Module testing", "[module]") {
myNamespace::myManagerClass manager;
myNamespace::myModuleClass *pModule;
SECTION(g_ModuleName.c_str()) {
pModule = manager.createModule(g_ModuleName.c_str());
REQUIRE(pModule != 0);
/*insert more testing code here*/
}
}
Then, I create an executable that will run this test on a single module specified on the command line. (I tried looping through the Catch::Session().run() below, but Catch does not allow it to run more than once.) The object file from the code below module_test.cpp and from the unit test code above module_unit_test.cpp are linked when creating the executable.
module_test.cpp:
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <string>
#include <cstdio>
std::string g_ModuleName; // global variable: module name
int main(int argc, char* argv[]) {
// Make sure the user specified a module name.
if (argc < 2) {
std::cout << argv[0] << " <module name> <Catch options>" << std::endl;
return 1;
}
size_t n;
char* catch_argv[argc-1];
int result;
// Modify the input arguments for the Catch Session.
// (Remove the module name, which is only used by this program.)
catch_argv[0] = argv[0];
for (n = 2; n < argc; n++) {
catch_argv[n-1] = argv[n];
}
// Set the value of the global variable.
g_ModuleName = argv[1];
// Run the test with the modified command line arguments.
result = Catch::Session().run(argc-1, catch_argv);
return result;
}
Then, I do the looping in a separate executable (not linked to the object files from the code above):
module_test_all.cpp:
#include <cstdlib>
#include <vector>
#include <string>
#include "myHeader.h"
int main(int argc, char* argv[]) {
std::string commandStr;
int result, status = 0;
myNamespace::myManagerClass manager;
std::vector<std::string> modList;
size_t m, n;
// Scan for modules.
modList = manager.getModules();
// Loop through the module list.
for (n = 0; n < modList.size(); n++) {
// Build the command line.
commandStr = "module_test " + modList[n];
for (m = 1; m < argc; m++) {
commandStr += " ";
commandStr += argv[m];
}
// Do a system call to the first executable.
result = system(commandStr.c_str());
// If a test fails, I keep track of the status but continue
// looping so all the modules get tested.
status = status ? status : result;
}
return status;
}
Yes, it is ugly, but I have confirmed that it works.

How to use cppunit just like junit --- two mains

I know that the unit test for Java is very simple. We just need use JUnit and run test classes as JUnit test.
Now I'm working with C++ and I find a test library: cppunit.
It seems that I need to run my test with a specific function main.
However, a cpp project can have ONLY ONE main.
What should I do? I have to switch mains when I do my test and when I run my project?
What should I do? I have to switch mains when I do my test and when I run my project?
You should separate the code to test into a library project, that can be linked from your target application and the unit test runner.
Then have two more projects providing a main() function:
one for the target app, that just forwards main() implementation to a call of a MyTargetApp class member function, e.g. MyTargetApp::run()
one for the unit testing, that calls a TestRunner, and contains all of the test suite and fixture classes (including these for the MyTargetApp).
The target application project can be configured without linking against the cppunit library and your test suite/fixture implementations (which will certainly reduce the final artifacts footprint).
However, a cpp project can have ONLY ONE main.
Another option is to use just one project with a narrow main() function that can be compiled using a conditional preprocessor statement (as from their example on the TestRunner class):
#ifdef TESTING
int runUnitTests(int argc, char* argv[]);
#endif
int main(int argc, char* argv[]) {
#ifdef TESTING
// run the unit tests
// -----------------------------------------------------------------
return runUnitTests(argc,argv);
#else
// run the application
// -----------------------------------------------------------------
MyTargetApp app;
return app.run(argc,argv);
#endif
#ifdef TESTING
int runUnitTests(int argc, char* argv[]) {
std::string testPath = (argc > 1) ? std::string(argv[1]) : "";
// Create the event manager and test controller
CppUnit::TestResult controller;
// Add a listener that colllects test result
CppUnit::TestResultCollector result;
controller.addListener( &result );
// Add a listener that print dots as test run.
CppUnit::TextTestProgressListener progress;
controller.addListener( &progress );
// Add the top suite to the test runner
CppUnit::TestRunner runner;
runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() );
try {
std::cout << "Running " << testPath;
runner.run( controller, testPath );
std::cerr << std::endl;
// Print test in a compiler compatible format.
CppUnit::CompilerOutputter outputter( &result, std::cerr );
outputter.write();
}
catch ( std::invalid_argument &e ) {
// Test path not resolved
std::cerr << std::endl
<< "ERROR: " << e.what()
<< std::endl;
return 0;
}
return result.wasSuccessful() ? 0 : 1;
}
#endif
Then have 2 different project configurations, one that defines TESTING and one without.
One disadvantage of this solution is though, you'll get all the unit test suites and fixtures left in your program, because cppunit macros will register and instantiate them automatically, regardless if the will be called from the execution path.

Is there a #define _KEYWORD_ for CXXTEST compiler to exclude blocks of code?

I need to temporarily put a main() function in my object to test alternate functionality (beyond a simple unit test), but I keep having to comment out my main() function to run my unit tests.
Is there a #define _KEYWORD_ for CxxTest to allow this to happen automatically?
You simply need to encapsulate the offending code with a compiler directive based on the definition of the CXXTEST_RUNNING keyword.
For example:
class myClass {
public:
myClass () {}
};
#ifndef CXXTEST_RUNNING
int main (int argc, char *argv[]) {
// Temporary runner. Typically deleted upon completion
// of alternate functionality added later in the project.
}
#endif
In this case, when using the CxxTest framework the main() function will be ignored in favor of the main() created by the testing framework. Otherwise, the main() function you have provided will be used.

Boost Test register exception translator

Does anybody know how to register my custom exception translator when using auto test cases in Boost.Test? I've found some examples (very few actually), but they do not show how to use this feature with auto test cases which are the biggest advantage of boost.test in my opinion. My example test suite:
#define BOOST_TEST_MODULE StateMachineTest
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE (FirstTest);
BOOST_AUTO_TEST_CASE (testBasic)
{
BOOST_CHECK (true);
}
BOOST_AUTO_TEST_SUITE_END ();
Thanks in advance.
(Note: I'm still using Boost 1.34.1)
Regardless of the AUTO_TEST_CASE feature, to register custom exception handlers you need to implement the init_unit_test_suite main function. (You do not need to register any of your auto tests there.)
All my unit tests projects use a ut_main.cpp file that contains (roughly) the following:
(This is in addition to all the other cpp files containing the actual auto tests.)
void translate_mfc_exception(CException* pMfcEx) {
...
BOOST_ERROR(msg);
}
// ...
using namespace ::boost::unit_test;
test_suite* init_unit_test_suite(int argc, char* argv[])
{
// Initialize global Handlers:
unit_test_monitor.
register_exception_translator<CException*>( &translate_mfc_exception );
// Return dummy suite to make framework happy:
test_suite* test = BOOST_TEST_SUITE( "Empty Test Suite" );
return test;
}
This should be all you need in addition to your auto test cases.
Alternatively you can register translator in global fixture