How can I test the functions I write before using them in my main C++ application?
Say I have a main.cpp that uses function foo() declared in mylib.h and defined in mylib.cpp.
I would like to test foo() extensively on "toy" situations, to check that it behaves as expected.
How can I do this in Eclipse? For my need it would be enough to have a test.cpp so that I can test single functions at the occurrence. I just would do this adding a "test" option to my makefile that compiles "test.cpp" rather than "main.cpp" but I don't know how to do this in Eclipse.
Any other less naive advice is appreciated as well.
You should have two projects :
project with your main, that uses the library
project where you implement your library, with the unit test main. This main needs to initialize the unit test framework, and execute tests
So, if you haven't, pick an unit testing framework, and add tests.
Related
I have a C++ project in Visual Studio, and have added another project exclusively for testing. Both of these projects are EXEs (console apps). So how do I use the first project inside the second?
Just to clarify, the question here would be somewhat self-evident if the first project was a library that one could simply include in the second project but, being an EXE, this is where the problem lies.
Per your comments, you have a C++ console application (MyApp) for which you have developed some application-specific classes that you want to unit-test with googletest in
Visual Studio. How?
As you say, if you wanted to unit-test a library the way to do it would be
obvious. You would:
1) Create a project to create a unit-testing application (UnitTest).
2) Configure the include-search directories so that the compiler can find the library's headers.
3) Configure the library-search directories so that the linker can find the library itself.
4) Add the library itself to the linker inputs.
5) Make the UnitTest project dependent on the library project, so that building UnitTest ensures MyApp is up-to-date.
6) Code the UnitTest app per googletest docs.
But since the classes you want to unit-test are specific to MyApp, you don't have any
library.
A drill-sergeant answer to that is: You don't have a library containing the classes you want to unit-test? So make one!
That way you use 3 projects:-
MyAppLib, generating library that contains all the functionality you want to unit-test.
MyApp, generating the same executable as at present, but linking MyAppLib
UnitTest, generating an executable that unit-tests MyAppLib, also linking MyAppLib
However if you don't like the drill-sergeant answer you can work around it.
From the usual build-system point of view (the one designed into Visual Studio),
the important output of the MyApp project is the build-target - the .exe.
The .obj files generated are just intermediate by-products. VS offers you no support
for treating these by-products as automatic linker inputs of a dependent project, and if a dependent project was also an .exe of the same sort - as it is your case - then such automatic linkage would be impossible anyhow because the main entry point would be multiply defined.
But from the unit-testing point of view it's the other way round. The .exe is of no interest, whereas (some of) the .obj files wholly or partly contain the implementations of the classes you want to unit test. In the text-book case where class foo is defined in foo.h and implemented in foo.cpp, the object file foo.obj is needed in the linkage of UnitTest.
For simplicity, assume that MyApp employs just one application-specific class foo,
defined in foo.h and implemented in foo.cpp. Then you have two options for building UnitTest.
a) You can add foo.cpp to the source files of UnitTest. Don't copy it of course. Just Add an existing item from the source folder of MyApp. Then you're done, but this
course has the downside that foo.cpp is exposed to untoward editing within
the UnitTest project.
b) You can treat foo.obj just like a static library required for the linkage of UnitTest and follow steps 1) - 6) above. This means in particular at step 3) that the {Debug|Release} build of UnitTest is configured with library-search directories that include \path\to\MyApp\{Debug|Release} (either in relative or absolute form).
In reality, for option b), there's very likely more than one .obj file from MyApp that you will have to link in UnitTest, and quite likely that their number will grow with time. Maintaining the right linkage of UnitTest could become a chore, and you might come to the conclusion that the drill-sergeant was right after all.
Depends. Google Test is (primarily) a Unit Testing framework (oversimplifying, testing classes). You can absolutely use is for other types of tests, but it doesn't have "built in" functionality for other types of testing, you'll have to write it yourself.
If you are trying to system test your executable, than you can run the process. I suggest using Boost.Process if you are using a multi-platform system or already have a boost dependency. Else, look here: launch an exe/process with stdin stdout and stderr?
The "tests" you write will call the executable, and can input stdin or stdout accordingly.
For example:
std::string path_to_exectuable = "thepath";
TEST(FooTester,CheckHelpScriptReturns0)
{
using bp =::boost::process;
std::vector<std::string> args; args.push_back("--help");
bp::context ctx;
ctx.stdout_behavior = bp::capture_stream();
bp::child c = bp::launch(exec, args, ctx);
bp::status s = c.wait();
ASSERT_TRUE(s.exited())<<"process didn't exit!";
ASSERT_EQ(s.exit_status(),0)<<"Help didn't return 0";
}
I was in a similar situation and I set this up in a way that effectively accomplishes the same goal of Mike Kinghan's answer as far as the compiler is concerned, but goes about it a different way from the user's perspective.
What I did was create a custom Configuration that I called "Testing". You create a new configuration by opening the project settings, choosing "Configuration Manager..." and selecting "New..." in the configuration selection box.
When prompted, I chose to copy the settings from the default "Debug" configuration, so that I can use the debugger with my tests just the same as if I was in the "Debug" configuration.
Under the new Testing configuration, I set the options for the compiler and linker to use google test as you normally would.
The important change in the properties is that I define a preprocessor variable which I have called "TESTING".
I rewrote my "main.cpp" to look something like this:
...
// includes
// functions
// whatever
...
#ifdef TESTING
#include <gtest/gtest.h>
#endif
int main(int argc, char **argv) {
#ifdef TESTING
::testing::InitGoogleTest(&argc, argv);
int val = RUN_ALL_TESTS();
getchar(); // not necessary, but keeps the console open
return val;
#endif
// rest of main() as normal...
}
What I'm trying to indicate is that I only changed a few lines right around where main is defined, I don't have to make gross changes spread throughout the file.
Now that this is all set up I simply made a new source folder for my tests, and create ".cpp" files in there. To avoid bloating the normal executable, I wrap these files with a check for the TESTING variable, so I have something like this:
tests/Test.cpp:
#ifdef TESTING
#include <gtest/gtest.h>
#include "my_class_header.h"
TEST(TestMyClass, test_something) {
// perform some test on class
}
#endif
I think these files still get "hit" by the compiler under Debug and Release configurations, so having a ton of these might slow down the build, but the Debug and Release objects wont get bloated with testing code.
The two takeaways are:
Using this method, the testing code is still organized separately from the application code, but it still resides in the same Visual Studio project, which may or may not be beneficial. Personally I like not having to manage/worry about a second project.
Like Mike Kinghan said, managing and linking .obj files yourself can become a chore, but by using this method, the default Visual Studio settings manage this for you.
One downside is that effectively redundant copies of all object files will get created in the "Testing" output directory. With more configuration, surely there must be a way to "share" the Debug object files, but I didn't have a reason to go that far.
This is a very simple method which may be a lot easier than refactoring your application into separate libraries and a main. I don't love using preprocessor wankery, but in this case it's fairly straightforward, not too much code bloat, and accomplishes exactly what it needs to. You could always trigger the tests another way, without using the preprocessor.
If you are not very rigid about having the tests in a different project, you can write the tests in your application project. Then just make the application execute the tests when receiving certain command line arguments, and execute the normal application logic otherwise, i.e.
int main(int argc, char* argv[])
{
if (argc >= 2 && std::string(argv[1]) == "--tests")
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
else
{
// Application logic goes here
}
}
TEST(ExampleTests, TestSQRTCalculation) // assuming all the right headers are included
{
EXPECT_NEAR(2.0, std::sqrt(4.0), 0.000001);
}
This avoids creating an unnecessary library for the sole purpose of testing, although you can still do it if it is correct structure-wise. The downside is that the testing code goes into the executable you are going to release. If you don't want that I guess you need an additional configuration which specifies a pre-processor directive to disable the tests.
Debugging the tests or running them automatically at post build is easy, simply by specifying "--tests" as debug args or at post build command line respectively.
If you want to test a console app you can run a test that opens a console window and run the exe file of the first app.
Then in your googletest catch the standard output from the exe you just ran.
[For more control over the first app you might need to have the first app parse arguments sent to it, e.g. some flags like -x or what ever you need.]
I have prepared a github repo including Visual Studio 2015 solution in parralel of Mike's "drill-sergeant" suggestion. You can use it directly without any additional requirement or dependency.
https://github.com/fuatcoskun/GoogleTestVS2015
I hope it helps...
I have a basic question regarding Googletest in Eclipse.
I am using the test-runner plug in to run the Googletests.
But I need to specify a binary which runs my unit tests (of course that makes sense.)
The problem is that in my project I now have two main functions, one to run the actual program and one
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
to run the google tests.
Each time I want to run one I comment the other out, which of course is stupid.
But what practice do you use to handle this situation?
Googletest C++ is a unit-testing framework. That means it is intended for testing
implementations of C++ APIs. It isn't intended for testing programs.
For practical purposes a C++ API is what you get in a C++ header file. The
implementation of such an an API might be:
Just the header file itself. (The implementation is entirely inline)
The header file plus a single C++ source file
The header file plus a bunch of C++ source files
To generalize, the implementation of a C++ API is a header file plus
0 or more source files.
Say your program my_prog invokes an API that you or your team have developed
for managing gizmos. The implementation is something like:
gizmo.h
[gizmo_0.cpp,...gizmo_N.cpp]
where [...] means optionally ...
Maybe my_prog relies on other APIs for which you or your team are responsible,
but we'll stick with just one. my_prog uses the gizmo API by:-
Using #include "gizmo.h" in some source files.
Compiling the [gizmo_0.cpp,...gizmo_N.cpp] source files, if any.
Linking the [gizmo_0.o,...gizmo_N.o] object files, if any.
(gizmo_0.obj, etc. if you're on Windows)
Testing your implementation of the gizmo API with Googletest is supposed
to confirm that this implementation is correct, independently of my_prog
or any other program that relies on it to manage gizmos. So incorporating
the unit-testing of the implementation in the implementation of my_prog is misguided:-
Maybe your colleague writes another program that also needs to manage gizmos
with this implementation. Maybe you write another one. Is whoever writes this
other program supposed to repeat the process of incorporating gizmo unit-tests
into it - The same ones? Different ones? - and making the program conditionally
compile as either a gizmo test-harness or as whatever it's supposed to be in real life?
And how do you know that the gizmo implementation isn't somehow entangled with
functionality that's unique to my_prog, or with the implementation of some
other API that my_prog uses in the same way - so that when you or somebody
else tries to reuse it in another program, it breaks or behaves wrongly?
No program that relies on this gizmo implementation is the place to put
its unit-testing. Making my_prog conditionally compile different main functions so it can
double as a unit-test harness for your gizmo library is similar to cutting a hole in the
crotch of your jeans for your head to fit through.
The way you're supposed to unit-test the gizmo library is to write a program that is the
test-harness for this library, and nothing else. This program, say gizmo_test, will
use the gizmo API in just the same way as any other program would use it, but
for the sole purpose of testing the gizmo library. All that gizmo_test will do is execute tests
of the gizmo library, by invoking its API.
As a first approximation, the GoogleTest recipe for gizmo_test is:
Write a header file, gizmo_test.h
#include "gizmo.h" in it
#include <gtest/gtest.h> in it
Then write your Googletest test cases in it
Write the following source file gizmo_test.cpp
#include "gizmo_test.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Create a project gizmo_test - in Eclipse or whatever development environment or build system you use -
that builds the gizmo_test executable by:
Compiling the source files gizmo_test.cpp + [gizmo_0.cpp,...gizmo_N.cpp]
Linking the resulting object files gizmo_test.o + [gizmo_0.o,...gizmo_N.o], plus libgtest and any other libraries on which your gizmo library depends
You have two projects. The one that makes my_prog and the one that makes gizmo_test. In your development environment or
build system, make the build of my_prog depend on the build of gizmo_test, so that when you change anything that affects
the gizmo library and rebuild my_prog, gizmo_test gets rebuilt first.
That's a first approximation. Did you notice a while back that I started talking about your gizmo library? That's what
you've got (or should have). In C++ and programming generally, the implementation of an an API is called a library.
And maybe you also noticed some fragility, inconvenience and wastage in the recipe for gizmo_test. You have the same set of gizmo source files
[gizmo_0.cpp,...gizmo_N.cpp] in both projects. So you might edit, compile and link them differently in two projects. And they'll get compiled in both projects, either differently,
which is wrong, or identically, which is pointless.
Of course if this set of source files is empty - the gizmo library is nothing but gizmo.h - there's no such problem. But if it's not empty,
there is.
As you know, in C++ we don't use a library by building its source files in every program that uses it - not unless it's a header-only library.
A library is built by itself into an object library (either static or dynamic), and to use it a program just includes the library's
header file(s) and links the object library.
That's how a program should use your gizmo library too. So to the final approximation:-
Make a project libgizmo that builds a gizmo object library (static or dynamic, as you see fit).
Make a project gizmo_test as above, except that instead of compiling and linking [gizmo_0.cpp,...gizmo_N.cpp], it just links libgizmo, and make this project
depend on the libgizmo project.
Make a project my_prog as you have it now, but instead of compiling and linking [gizmo_0.cpp,...gizmo_N.cpp], just link libgizmo, and make this project
depend on the gizmo_test project.
So you have three projects by the time you build the first program that uses the gizmo library. Each subsequent program that uses the gizmo library needs one
more project, like the my_prog project.
Googletest is designed for testing C++ libraries, and this is how you're supposed to use it.
Now I know nothing about your program or how you are currently deploying Googletest test cases in your project. Maybe there aren't any well-defined API implementations in it
that those test cases are supposed to exercise, that you can factor out into free-standing libraries. Possibly that could be because your program is so very simple that
unit-testing its "components" is non-applicable, and you'd be wiser just to write blackbox tests of the program. More likely it would be because you've so far failed
to design a program architecture that is capable of being unit-tested. If that's what you find, you need to fix it, and then apply Googletest the right way. It will be worth the
effort.
And in case it needs pointed out, unit-tests are not program tests, so as well as unit-testing any libraries your program relies on, if they are your responsibility, you also need blackbox tests of your program.
Indeed a valid question. I believe that Mike Kinghan's detailed response explains how you should use google-test but nothing is set in stone and in the end, you can use google-test in any way you want.
So, since I actually encountered a similar situation, what I did was rather simple.
I modified the production file source code so that the main function will change from this:
void main(void)
to this:
#ifndef TDD_ENABLED // TDD_ENABLED is defined only in the unit test project
void main(void)
#else
void main_app(void)
#endif
this way when you are running unit tests, the original 'main' function is converted to 'main_app' and you avoid conflicts with the 'main' of google test. When you are running the original production code project, the 'main_app' function is named again 'main' as it should. So, technically, from your production code perspective, nothing has changed.
I'm using Boost unit tests BOOST_AUTO_TEST_CASE
It requires to remove main() function to execute the test cases.
The question is
What directives should be used for switching between Normal/UnitTest modes? I have cross-platform application for Windows and Unix.
I have only one suggestion: use something like #ifndef TESTING in main.cpp and use manual change #define TESTING line ?
Is there any better solution?
Thanks
Unit tests should go into a separate translation unit. If you have foo.hpp and foo.cpp for your library, you have something like foo_test.cpp for the unit tests. Your build environment would then be made aware of a new "test" target which builds and runs those tests.
I am trying to use GTest to test my code but one of the things that bothers me is that it always gets compiled in. This slows down my release builds. A GTest test looks like this
TEST(CaseName, TestName)
{
ASSERT_EQ(3, 3);
}
I want to be able to comment out all of my test by a simple define. I can wrap every test in #ifdef's but that is really ugly. I would like to not include the GTest headers and instead define TEST myself in a way to get rid of the test.
What I Have So far.
I have a macro that defines it as a static function so that it should get optimized out but the assert's inside the test still get compiled (and are undefined). This means that I would also have to define every ASSERT and EXPECT which is tedious to say the least.
#define TEST(tcase, test) static void uselessFunction##tcase##_##test(void)
I could stick with this but I would much prefer something nicer. Hopefully there are some macro-magicians out there to help.
Rather than using macros like this, it might be better to put all your tests into files which are compiled into a test executable, and put all your production files into a library which is linked by the test exe.
In this way, you can have gtest run against both Debug and Release builds, but only compile the test code when you build the test executable.
Is there any way to easily test C++ classes in java way.
In java you can add static function main and run it directly from IDE
class Foo{
...
public static void main(String args[])
{
System.out.println("Test class foo here");
}
}
is it possible to do it in Visual C++ ?
Of course you can create another project, but it is bad solution(you sould create project, and then add it to solution or run another copy of Visual Studio)
Another way is to modify main() function, or CWinApp::InitInstance() but if you change file
Foo.h, VS will rebuild all files from project, depending on it (we just want to test Foo.h & Foo.cpp)
The best way i founded is to create another project (console), add Foo.h and Foo.cpp to it, add public static function run() to my class Foo and run it from main() function in console project like this
//unitTester.cpp
include "Foo.h"
int main(...){
Foo::run();
return 0;
}
in such way i can test my class Foo separately (without recompiling the big project)
When I feel like writing unit tests, I usually add another project that links in the test code + the classes being tested. The test code I write using the Boost Test Library, which nicely integrates with Visual Studio. I make my actual project dependent on the test project. The test project runs its executable as a post-build step. Therefore, as long as the tests fail, I cannot even build the main project.
The workaround I use is to use a #define to decide what mode the app is in.
I usually have a def.h file, which would have
#define TEST
Then on the main file you write,
#ifdef TEST
// test code
#else
// main code
#endif
This condition check can be done in several places too if for testing you need to change things in several places. If this testing code needs changes in several files also, all you have to do is to include def.h in those source files.
Hope this helps
Use the Boost Test Library. If your application has a GUI, its a littlebit difficult to integrate, but once it works, its quite simple and straightforward to write tests.