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:
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: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:-#include "gizmo.h"
in some source files.[gizmo_0.cpp,...gizmo_N.cpp]
source files, if any.[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 ofmy_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 thatmy_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 differentmain
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 thatgizmo_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 itThen write your Googletest test cases in it
Write the following source file
gizmo_test.cpp
Create a project
gizmo_test
- in Eclipse or whatever development environment or build system you use - that builds thegizmo_test
executable by:gizmo_test.cpp
+[gizmo_0.cpp,...gizmo_N.cpp]
gizmo_test.o
+[gizmo_0.o,...gizmo_N.o]
, pluslibgtest
and any other libraries on which your gizmo library dependsYou have two projects. The one that makes
my_prog
and the one that makesgizmo_test
. In your development environment or build system, make the build ofmy_prog
depend on the build ofgizmo_test
, so that when you change anything that affects the gizmo library and rebuildmy_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:-
libgizmo
that builds a gizmo object library (static or dynamic, as you see fit).gizmo_test
as above, except that instead of compiling and linking[gizmo_0.cpp,...gizmo_N.cpp]
, it just linkslibgizmo
, and make this project depend on thelibgizmo
project.my_prog
as you have it now, but instead of compiling and linking[gizmo_0.cpp,...gizmo_N.cpp]
, just linklibgizmo
, and make this project depend on thegizmo_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.