How to link tests from static library in test runner executable? - c++

I have a Visual Studio solution organised like this:
ProjectA // A static library I'm working on
ProjectB // A static library containing UnitTest++ test suites for ProjectA
ProjectC // An executable test runner which links to ProjectA and ProjectB
ProjectB contains two files which look like this:
// RunTests.h
#ifndef RUNTESTS_H
#define RUNTESTS_H
#include "UnitTest++.h"
int runAllTests();
#endif
and this:
// RunTests.cpp
#include "RunTests.h"
int runAllTests()
{
return UnitTest::RunAllTests();
}
As well as several files containing test suites e.g.:
// FooTests.cpp
#include "RunTests.h" //
#include "Foo.h" // From ProjectA
TEST(SomeTest)
{
CHECK(true);
}
ProjectC consists of a single file:
// main.cpp
#include "RunTests.h" // from ProjectB
int main()
{
return runAllTests();
}
The reason I have the tests and the test runner separated, is that I have another project which uses the same tests to analyse code coverage, which I need to keep separate as it is not cross-platform, whereas the test runner is.
The issue is, that when I compile and run ProjectC, no tests are actually run (UnitTest++ runs, but with zero tests). This is because ProjectC does not reference any symbols relating to the tests from ProjectB, so the linker doesn't link the object files from ProjectB.lib.
It is my understanding that if ProjectB was an executable, I would not have this issue (presumably because the linker would link all the object files), as per the documentation:
The general idea is that you keep one Main.cpp file with the
entry-point which calls RunAllTests().
Then you can simply compile and link new .cpp files at will, typically
one per test suite.
Each of the Test*.cpp files will contain one or more TEST macro incantations with the associated
test code. There are no source-level dependencies between Main.cpp and
Test*.cpp, as the TEST macro handles the registration and setup
necessary for RunAllTests() to find all tests compiled into the same
final executable.
How can I resolve this problem without having to declare all the tests in header files that ProjectC can see (which would kill UnitTest++'s ease of use)? One possibility I've noticed in Visual Studio is:
Project Settings > Configuration Properties > Linker > Input > Force Symbol References
However it would be rather tedious to have to add every single symbol, every time I write a new unit test. Is there some way I can force it to include the entire contents of ProjectB.lib? Or perhaps some code-based solution?
EDIT: What I'm looking for is something like this but for Visual Studio.

I was trying to use UnitTest++ the same way you've described and ran into the same problem. I ran across a suggestion in another forum that seems to work for my unittest executable (i.e. ProjectC).
For ProjectC:
Project Settings > Common Properties > (select ProjectB) > Use Library Dependency Inputs: True
This worked for me. I think what this does is effectively link any object files from ProjectB into ProjectC (as opposed to linking the library).

Related

"_main already defined" while using gtest

I have a solution with two projects in it
One of them is a console application, and the other one is a Google Test project
My project has a .h file and a .CPP with a main() in it
My gtest consists of a .CPP file which calls the .h file using #include and a main function to RUN_ALL_TESTS()
I need a main in my project but I also need a main in the gtest project, but having two main() doesn't let me build the gtest successfully
Is there a workaround to this?
Sorry if it's a silly question, I have no clue how to use gtest because various sites keep presenting different ways
First of all you should have a dedicated file main.cpp for your main() function, which contains nothing else.
E.g. your project structure could look like:
project1
file1.h
file1.cpp
main.cpp
I'm not familiar wiht gtest specifically, but usually unit test frameworks have a separate file for the gtest main function, e.g. gtest_main.cpp. Tests are in one or more files like file1test.cpp etc.
So you would compile and link your project1 with file1.h, file1.cpp and main.cpp to get an executable.
For unit tests you would compile and link file1.h, file1.cpp, file1test.cpp and gtest_main.cpp for a unit test executable.
Structure could be like
project1
file1.h
file1.cpp
main.cpp
project1test
file1test.cpp
gtest_main.cpp
EDIT additional infos on linking:
In project1test you would include file1.h with #include "../project1/file1.h".
For correct linking right-click on project1test project
--> Configuration Properties --> Linker --> Input --> Additional Dependencies --> Add "..\project1\Debug\file1.obj"
As #Alan Birtles pointed out it would be even more clearer if you had the following structure:
project1library
file1.h
file1.cpp
project1application
main.cpp
project1test
file1test.cpp
gtest_main.cpp
The you would get a static/dynamic library project1library.lib/.dll, an executable project1application.exe and a unit test executable project1test.exe.
The advantage is that you would just link the library in your unit test project with
--> Configuration Properties --> Linker --> Input --> Additional Dependencies --> Add "..\project1library\Debug\project1library.lib"
If you have more than one file you need from your project, you don't have to add every obj file, but just one lib file.
But making sure that everything was rebuilt correctly on changes can be more difficult and error prone with a lib, an executable and a unit test project.
Standart usage of gtest is for unit testing.
Usually, unit tests don't check main :).
I recommend you to use standart gtest main function (don't define custom main function). it allows you to use command line to filter running tests.
If you don't want to use gtest main, IMHO, you shouldn't include gtest_main library.
I used macros for this problem. I have defined a TESTING macro which evaluates to true when compiling the unit tests and otherwise to false:
#ifndef TESTING
// the source main
int main() {
...
}
#endif // !TESTING
You can also use this later for "test" code in your sources. What I do sometimes (not good design IMO):
class Klass:
#ifdef TESTING
friend class KlassUnitTestClass; // allows access to private members in my google test unit class. Disabled when i build sources
#endif // !TESTING

Can I add googletest to existing visual c++ project? [duplicate]

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...

Eclipse CDT - How to build googletest unit tests as a separate project?

I have two projects. One called projectA and the other called projectA-tests.
The first project is my actual project, and the second project contains GoogleTest unit tests for classes in projectA.
I have coded one very simple unit test so far and everything builds OK. Note that this first simple test depends on a single .h file of projectA that has only a static class method defined in the same .h file (no .cpp file). It's actually a "StringUtils" class with methods like ::startsWith() and so on.
After adding a second test I'm having linking problems. This second test depends con a Class of projectA that is declared in a .h file and defined in a .cpp file. I'm getting an undefined reference regarding this Class, trying to build this second test.
projectA-tests compiler settings are configured to include projectA/src in project -> properties -> C/C++ build -> settings -> C++ compiler -> includes. (I guess this is why the first compiles ok, because it only requires a .h file which is covered by this "includes" setting).
What I don't know is how to configure the C++ linker in projectA-test to include all .o files of projectA in the linkage process.
I'm more experienced in Java, and the equivalent would be simply adding the other project source folder as dependency of the build path. Whay is Eclipse CDT's C++ equivalent?
Thanks!

Linker error - linking two "application" type projects in order to use Google Test

I am trying to test a function with Google Test.
It seems that everything is set up correctly, and it builds and executes fine without gtest... (There is a bit of complexity in the code, so I cannot list all the source files here, but without adding gtest, the files are linking properly, and running as they should).
It is an application type project. It has a number of library dependencies... irrelevant.
The test project is added as a separate project to the solution. It has the tested project as a dependency. The .h file of the test project only points to the gtest... The .cpp (not main, which is the standard InitGoogleTest main) adds its own header file, the header file of the tested project, and has the test shown below.
There is a TestedProject.lib created automatically, when the project builds, even though it is an application. I have added TestedProject.lib as a library dependency to the TestProject (in Link).
Class x
{
public:
x(){} // I didn't really need this, I only added the class so I have access to
~x(){}; // non-class methods with gtest - but it still doesn't work
bool myFunction(std::string a, double b, bool c);
};
implementation:
bool x::myFunction(std::string a, double b, bool c)
{
// implementation
return false;
}
somewhere_else
{
x x_instance;
y = x_instance.myFunction("a", 1, false); // works, all builds, executes, life is great
}
Add unit test:
class TheTest : public ::testing::Test
{
protected:
x x_instance;
};
TEST_F(TheTest, Fail)
{
EXPECT_FALSE(x_instance.myFunction("a", 1, false));
}
Doesn't build. Link error (modified, like the sample code above, with simplified names, I hope I didn't mess up content)
Error 2 error LNK2019: unresolved external symbol
"public: bool __thiscall x::myFunction(class std::basic_string<char,struct std::char_traits<char>,double,bool)"
(?myFunction#x##QAE_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##00000NNNN_N1#Z)
referenced in function "private: virtual void __thiscall TheTest_Fail_Test::TestBody(void)"
(?TestBody#TheTest_Fail_Test##EAEXXZ) C:\path\file.obj
I have done this before - solved link errors - wrote a couple of tests with Google test - but I can't see anything missing.
As a test, I wrote a little
int test(){return 4;}
in the header file, in the class declaration...
and then, replaced the test with
EXPECT_EQ(x.test(), 4);
It worked. Great. But that would mean to have all the tested code in a single file, a cpp or something... which is simply unreasonable. There are a few files in this Application project.
How can I fix this issue ? How can I make Google Test link and test with a class with a header and an implementation file ? When that header/implementation is in a different project, of "Application" type ?
The only similar issue I have found, so far: C++ linking issue on Visual Studio 2008 when crosslinking different projects on same solution
Please, help me find a solution.
There is a another solution, which I prefer because it means you can avoid to change your main project:
Add a "post build action" to the main project in order to create a static library for the exact same source files.
Then you can simply add this dependency to you gtest project.
Each time you'll compile your main project it will build the application AND the static library.
This way you don't have to create a third project and keep configurations synchronized.
Hope it helps.
So I'll have an answer:
I have 2 solutions to my question:
1) Break up the application project in 2 projects, one will become a library, with most of the code; the other will be an application, containing a tiny main() that calls the entry point of the real code (like a parameter parsing method or something).
Then, I can add a unit testing project - to test the lib.
2) Don't break up the project. Add a gtest project, don't create any dependencies. Add the files to test into the gtest project. The gtest project will be a separate executable... with all it needs to be happy. (Advantage: no dependencies for testing)
I prefer the first version.
There is another solution for this.
Just create a new project for Google Test Framework.
(of course, under your existing application solution).
And then, after you make sure all your Google Test Framework setup correctly.
(you can test it under the newly created solution)
Manually include the code your want test (use Add -> Existing Item) from your main project, and then you can test your code without generate additional lib.
The good part of this is that when you test some application which requires DLL from windows, it requires the application uses Multi-threaded Debug DLL.
(in your Project property settings, go to C/C++ -> Code Generation -> Runtime Library see what you got)
And Google Test Framework uses a very different RunTime Library (Multi-threaded Debug (/MTd)).
At the stage of linking, the compiler will cry that it has some difficulty links the generated lib from your application with Multi-Thread DLL and the google framework's lib (which is Multi-threaded).
In this way, you can avoid the dependency problem of both project. (one for /Mtd and one for /Md)

Is there an easy way to setup a link seam with Visual Studio 2010's build system?

I used to have a static library which was imported by both my main program and my tests. However, I needed global variables inside of my static library to be constructed, and there's no way to force Visual Studio to do that.
What I'd like to do then is to have a project which compiles all the common C++ files, a project which compiles and links the unit tests (with the common C++ files), and a project which links the actual application.
How can I do this in Visual Studio 2010?
EDIT: Because clarification has been asked, here's what I mean:
InterfaceIUse.hpp
#include <memory>
struct IInterface
{
virtual ~IInterface() {}
virtual void SomethingIDependOn() = 0;
};
std::auto_ptr<IInterface> FactoryMethod();
CodeUnderTest.cpp
#include "InterfaceIUse.hpp"
void FunctionUnderTest()
{
//Blah blah blah
}
IExistOnlyInTheMainProgram.cpp
#include "InterfaceIUse.hpp"
std::auto_ptr<IInterface> FactoryMethod()
{
//I return the real implementation of the interface.
}
IExistOnlyInTheTest.cpp
#include "InterfaceIUse.hpp"
std::auto_ptr<IInterface> FactoryMethod()
{
//I return the mock implementation of the interface.
}
The idea is to compile the right .cpp implementation of the given factory, which will allow the dependencies of the code to be tested to be dependency injected.
Doing this kind of link seam is easy with makefiles -- but makefiles are undesirable because I'm forced to manually maintain header dependencies in the makefile.
I have done similar setup in VS2008, which I think still applicable for you in VS2010.
To start, I setup my project hierarchy as Build, ProductionCodeBase and TestCodeBase.
Common interface/headers are extracted into folder accessible by all projects.
Then in my "Build" project, I manually add object file(s) from ProductionCodeBase into "Release" configuration, and object file(s) from TestCodeBase into "Debug" configuration.
Don't forget to set project dependencies so that object file are valid when linking in "Build".
Do note that you can create project that only compile source code into object files without attempt to link them. Just go to "Tool Build Order" for that particular project and disable corresponding linker.