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.
Related
I am a little bit new to cpp. And all the concepts of 'includes' tho are important are pretty new and vague forme. I have a few questions which are related to my main question . The main question is:. I have a program which is a file containing 'main' and other 5 classes let's call it 'PROG'. I put them all in one file using no h files at all. The program is running and all is good. The point is, I now have 'test file ' which should test my program. Test file is separated to h file and cpp file. Is there any way to run everything without changing my program 'PROG'?? I don't want to create h files to my 'PROG' . The problem is, the test file uses a few of the claseess written the program 'PROG'. I thought about writing 'includes' cpp in the test file and putting 'pragma once'. I don't know why it doesn't work. Doesn't pragma once work for ' cpp includes'??
Or basically can anyone answer the general question. Which is in short:. You have a file containing main and classes (which all in cpp file with no h file) . And you want to run it with another file (cpp+ h) but both files use each othrr. Which makes a circular use. Is there a way to run it ?
You might be able to write tests, however they will be run at an unspecified time either before or after your program runs, so won't be able to access std::cout etc. If your program uses any static objects, you won't be able to do this.
It will be much easier to move your main into a main.cpp that #includes definitions of your classes, and compile a separate test_main.cpp that instead runs your tests.
As a sketch of the former
class TestFailure{};
class RunAtStartup
{
template<typename Func>
RunAtStartup(Func f) { f(); }
}
extern double function_to_test(int arg);
static RunAtStartup run_function_to_test([]{
// arrange
int param = 0;
// act
double res = function_to_test(param);
// assert
if(res != 1.0) throw TestFailure();
});
Does this help?
PROG:
class C {
void f();
}
#ifndef TEST
void C::f() {
// implementation
}
#endif // TEST
TEST:
#define TEST
#include "main.cpp"
// Your test code here can have instances to class C
C c;
c.f();
But take cpp/h approach as anyone recommends, which is everywhere.
I'd highly recommend using headers, but if you really don't want to modify your original file, you can #include "main.cpp" from your test file and redefine the main symbol during the inclusion. This allows you to create your own main method for the test program.
In test.cpp:
#define main real_main
#include "mymain.cpp"
#undef main
int main(int argc, const char** argv) {
std::cout << "wah" << std::endl;
int fakeargc = 1;
const char* fakeargv[fakeargc] = { "hoo" };
real_main(fakeargc, fakeargv);
}
In main.cpp:
#include <iostream>
int main(int argc, const char** argv) {
std::cout << "hello world " << argv[0] << std::endl;
return 0;
}
This is NOT a duplicate of Superiority of unnamed namespace over static?
Please read the question carefully before marking it as duplicate. I am not asking why use an unnamed namespace versus static!
I am asking, why are google tests placed inside an unnamed namespace? Is this some convention that google tests follow, and if so, why? The tests work fine whether they are in an unnamed namespace or not, so obviously it is not required.**
I cloned google test from github and built it for my mac. It works fine, but I noticed in the sample test code they give they place the tests in an unnamed namespace. Does anyone know why?
For example, see following file:
googletest/googletest/samples/sample1_unittest.cc
(https://github.com/google/googletest/blob/master/googletest/samples/sample1_unittest.cc#L41)
Part of the file looks like this:
// Step 1. Include necessary header files such that the stuff your
// test logic needs is declared.
//
// Don't forget gtest.h, which declares the testing framework.
#include <limits.h>
#include "sample1.h"
#include "gtest/gtest.h"
namespace {
// Step 2. Use the TEST macro to define your tests.
...
TEST(FactorialTest, Negative) {
// This test is named "Negative", and belongs to the "FactorialTest"
// test case.
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
}
...
} // namespace
Does anyone know why all the tests are in an unnamed namespace?
I tried removing the unnamed namespace and the sample still worked fine, so clearly it is not necessary for this particular sample.
I think the comment by Mike Kinghan answers the question, especially the part
You don't need to ask a programmer why haven't put stuff into the global namespace. You need to ask why they have.
However, I think its a good idea, pedagogically, to give an example of the kind of horrors that can happen if one doesn't follow good coding practices and as a consequence, violate ODR by mistake.
First, to relate the program below with the question, one needs to know that some of the Google Test macros create new classes. Now, consider the following program
myClass1.h
#ifndef MYCLASS1_H
#define MYCLASS1_H
int f();
#endif /* MYCLASS1_H */
myClass2.h
#ifndef MYCLASS2_H
#define MYCLASS2_H
int g();
#endif /* MYCLASS2_H */
myClass1.cpp
#include "myClass1.h"
class MyClass {
public:
void twice() { val *= 2; }
char val;
};
int f() {
MyClass x;
x.val = 2;
x.twice();
return x.val;
}
myClass2.cpp
#include "myClass2.h"
class MyClass {
public:
void twice() { val *= 2; }
double val;
};
int g() {
MyClass x;
x.val = 3;
x.twice();
return x.val;
}
main.cpp
#include <iostream>
#include "myClass1.h"
#include "myClass2.h"
int main() {
std::cerr << f() << std::endl << g() << std::endl;
return 0;
}
Notice how the class MyClass has two different definitions. With g++ 5.4.0-6ubuntu1~16.04.10, compiling and running the program with
g++ -O3 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
prints 4 and 6, the expected behavior. However, compiling and running with no optimizations, i.e. with
g++ -O0 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined
prints 4 and 3!
Now, put this bug in a non-trivial program and you might easily loose an afternoon of debugging, especially if the bug laid dormant for a while. On the other hand, wrapping the classes in anonymous namespaces up-front takes no time at all and it prevents the bug. I think this illustrates one of the rationale behind some of the good coding practices: basic risk management.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
Ok so I'm still getting used to C++ again, so this error may seem simple. I'm attempting to create a simple class with a three member functions (I'm only trying to call one of them in this). So I create the class, instantiate an object, then attempt to call the function using that object and this error comes up:
Code.cpp:(.text+0x15): undefined reference to `Code::genCode()'
I've double checked to see if it was an error with the function itself, but that is not the case. I've seen others post about this issue but there seems to be a multitude of situations and solutions. Anyway here's the code:
#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <list>
using namespace std;
class Code {
public:
int genCode();
int checkCorrect();
int checkIncorrect();
};
int main()
{
Code c1;
c1.genCode();
}
////////////////FUNCTIONS/////////////////////////
int genCode()
{
vector <int> newcode;
srand(time(NULL));
for(int i = 0; i < 9; i++){
int x;
x = (rand() % 6);
if (find(newcode.begin(),newcode.end(), x) == newcode.end())
{
newcode.push_back(x);
}
}
if (newcode.size() > 4)
{
newcode.pop_back();
}
for(int i = 0; i < 4; i++)
{
return newcode[i];
}
}
int checkCorrect()
{
}
int checkIncorrect()
{
}
you need to put class name before method name
the format is
'returnType Classname::methodname
{
codes
}'
int code::genCode()
{
//codes
}
or you also possible to write code in class
Change the implementation of the methods of your class to the following:
int Code::genCode()
{
...
}
int Code::checkCorrect()
{
...
}
int Code::checkIncorrect()
{
...
}
You are defining the functions outside the class. Put them inside the class, then you don't need to declare them inside the class. Directly define them.
#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <list>
using namespace std;
class Code {
public:
////////////////FUNCTIONS/////////////////////////
int genCode()
{
cout << "Inside genCode. Just for Debugging purpose." << endl;
vector <int> newcode;
srand(time(NULL));
for(int i = 0; i < 9; i++){
int x;
x = (rand() % 6);
if (find(newcode.begin(),newcode.end(), x) == newcode.end())
{
newcode.push_back(x);
}
}
if (newcode.size() > 4)
{
newcode.pop_back();
}
for(int i = 0; i < 4; i++)
{
return newcode[i];
}
}
int checkCorrect()
{
}
int checkIncorrect()
{
}
};
int main()
{
Code c1;
c1.genCode();
}
Otput:
Inside genCode. Just for Debugging purpose.
The function
int genCode()
Is what's called a free function. It is not bound to a class.
In order for the compiler to know that genCode is part of a class, you have to tell it by explicitly stating the namespace to which genCode belongs.
int Code::genCode()
However since it appears code Code is entirely contained within one file, following CodeRunner's advice will lead to a cleaner implementation.
But why would anyone want to got the trouble of splitting everything up?
Separating the class definition from the method implementations allows you place the class definition into one file, the 'h header file, and the methods in an implementation file, usually a .cpp file. The header file is then shared with users of the Code object and the implementation file can be compiled into a library and hidden from the callers view.
There are a number of reasons to do this, but most of them have to do with creating pre-compiled libraries and using them to reduce build times.
With a library, you build the library once, and then compile the rest of the code that uses the library over and over until you get it right. Can you imagine how long it would take to build a program if you had to rebuild the C++ standard library every time you fixed a bug and wanted to test?
Had a job like that once. Had to spend four hours compiling third party network code every time I made a fix because the company's paranoid build system rebuilt everything every time. Off by one error? 4 hours. Need to add a debug line? 4 hours. You could make and test three changes a day. Sure, you can batch up a bunch of fixes, but if one failed spectacularly and broke the system, which one was it? Sooner or later you're reduced to a crawl, making tweaks, building, testing, profiling one at a time. Fortunately I was working on contract and paid by the hour.
Another good example is you can have one library that supports Windows and other libraries supporting QNX and other operating systems. All use the same header and the user can write a program that, in theory, will operate on all supported platforms simply by recompiling the user's code. It's never quite that clean, but one can dream.
The library can even be replaced with an updated library without requiring changes or compilation of the user's code and different variants of the library can exist for different needs. A debug version with extra logging, for example.
Perhaps the implementation is not intended for public eyes. The users get to see the header and call functions in the library, but no more.
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
I am forced to use NI Lab Windows CVI, and i would love work with TDD. However i could not find any testframeworks for that IDE. Are there any known solutions?
I just talked to someone at NI.
There are Unit Test Frameworks for NI Lab View wich is something completely different.
There is currently no solution from NI. In the past some people solved their issues using TestComplete - another route might be using CUnit.
EDIT:
Using CUNIT with CVI is really easy - though you still face some language Barriers:
#include "CUError.h"
#include "CUError.c"
#include "CUnit.h"
#include "MyMem.h"
#include "MyMem.c"
#include "TestDB.h"
#include "TestDB.c"
#include "TestRun.h"
#include "TestRun.c"
#include "Util.h"
#include "Util.c"
#include "Automated.h"
#include "Automated.c"
Using theese include statements should allow you to run this code:
static void testFail(void)
{
CU_ASSERT(0);
}
//Suite Definitions
static CU_TestInfo tests_GenList[] = {
{ "Should Fail", testFail },
CU_TEST_INFO_NULL,
};
static CU_SuiteInfo suites[] = {
{ "Generic List Suites", NULL, NULL, tests_GenList },
CU_SUITE_INFO_NULL,
};
void AddTests(void)
{
assert(NULL != CU_get_registry());
assert(!CU_is_test_running());
/* Register suites. */
if (CU_register_suites(suites) != CUE_SUCCESS) {
fprintf(stderr, "suite registration failed - %s\n",
CU_get_error_msg());
exit(EXIT_FAILURE);
}
}
int main (void)
{
CU_initialize_registry();
AddTests();
CU_set_output_filename("Result\\TestAutomated");
CU_list_tests_to_file();
CU_automated_run_tests();
CU_cleanup_registry();
return 0;
}
Also copy these files into your Result directory:
CUnit-List.dtd
CUnit-List.xsl
CUnit-Run.dtd
CUnit-Run.xsl
md2xml.pl
Memory-Dump.dtd
Memory-Dump.xsl
We also use CUnit with CMock (ThrowTheStick) over here. With cvi you can even automate the ruby scripts to execute the test_runner builder with somethine like
"%RUBY_HOME%\bin\ruby.exe" "%UNITY_HOME%\auto\generate_test_runner.rb"
Test_TestCycleFSM.c
in your pre-build steps. You maybe have to compile your project twice to generate the sourcefile and compile it then.
After all, CUnit seems to be the tests suite in C.