Creating a test project - c++

I have a solution consisting of several library project and one application project.
I want to create a separate application test project. However, my problem is how I can write test for the application project since I can't link to it? I've added the application project as a reference in "Common Properties", but I get LNK1120 probably because the application project doesn't generate a lib file to link.
How do I create a separate test project for a project with application as configuration type?

I can think of three solutions to this - none 100% as clean as I'd prefer.
Compile test code into a test library that is conditionally linked to the application program, and is driven by test input to the program. So in effect you use your own app as the test driver
Make you application a shell only and put all unit tested code in to a library that can also be linked into the test app.
same as the last one, but compile the code in the library into the app in the application build, but into the library for the test build.
The second would be my choice.

Related

Using QtTest inside a Library project

I'm confused on how I'm supposed to use the QtTest FrameWork inside a Library project (Windows). I have created a library project and added some tests, but I had a lot of issues trying to run the tests. The key to solve my problem was to set:
TEMPLATE = app
However, I'm making a lib... also app makes an exe, not a dll. I really hope that it's not intent to have to change the project file manually to 'app' when testing and changing to 'lib' for actual building the library. This seems unproductive.
So, what's up with QtTests inside library projects?
Thanks

What is an effective way to organize C++ projects that are going to be unit tested?

I am wondering what would be an effective way to organize C++ projects and classes that are going to be unit tested. I have read many SO posts related to unit test but couldn't find practical examples.
Here are some ways I have collected:
Method A
Project A: Application (.exe) project that "include" the classes from Project C
Project B: Unit test (.exe) project that "include" the classes from Project C
Project C: Static library (.lib) project that keeps all classes that Project A uses
Method B
Project A: Application (.exe) project with all classes inside itself.
Project B: Unit test (.exe) project that "links" to classes in Project A
Method C (from Miguel)
only one project, with three configurations:
Debug: builds your Application .exe in debug mode.
Release: builds your Application .exe in release mode.
Test: builds the unit test framework, replaces your app's main() with the unit testing main()
Which is the more appropriate way? Do you have any other suggestions?
I have previously used the first method quite well. Have most of your code in a static library project, have the main executable project just contain the main function, and have your tests and the test main function in a third project. The two executable projects will link to the static library and reuse the code.
The main benefits in doing it this way are:
The code that is being tested is the exact same build as is used in your application.
You can test both the debug and release configurations to ensure that both work as expected. (You can extrapolate debug and release for any configurations that you might require.)
Build time is minimised since the same built library is used in both executable projects.
Can have the build system build both the test and main executable at the same time, and also run the test executable after building.
There's not that much difference actually, as you can always compile the exe as a static library and link against the unit tests. Conceptually, Method A is slightly cleaner, but there's nothing preventing you from using Method B. It basically boils down to your build system what is easier to do.
I don't think you'll gain much by moving the classes of your application to a static library. You should also consider that you may want to modify your classes when you compile them for testing, for example by adding additional convenience methods that are not necessary for the application, so in the end putting the classes in a library may not help at all since you will need a special version of these classes when running tests.
I would like to suggest the following as a better option than your methods A and B:
METHOD C
only one project, with three configurations:
Debug: builds your Application .exe in debug mode.
Release: builds your Application .exe in release mode.
Test: builds the unit test framework, replaces your app's main() with the unit testing main()
If you think you need to, you can split the Test target into Debug and Release as well.

Beginning Code::blocks and UnitTest++

I'm about to start a C++ project but I'm stuck at the basics.
I want to use the (linux) Code::Blocks IDE, and it's easy to create a normal project. However I want to do TDD using the UnitTest++ framework, and I don't know how to set everything up cleanly.
I've already asked a question about where to put the UnitTest::RunAllTests() command, and they told me the best place is the main() of a separate program.
How do I go about doing this in Code::Blocks? I think I need to create 2 projects:
The "real" project with its own main();
The unit testing project containing the tests and the main() with UnitTest::RunAllTests() inside.
Then somehow have the first project build and run the second during its build process. I don't know how to do that yet but I can find out on my own.
My questions are:
this is the right method?
do I have to create also a project for the UnitTest++ framework, in order to let other people build it on other platforms? Or is dropping the complied library in the project's path enough?
how can I organize the directories of these projects together? It'd be nice to put the tests related to each package in the same directory as that package, but is it ok to have multiple projects in the same directory tree?
I'll partly answer my own questions, as I've managed to get everything working.
Following the instructions on the official documentation page, I've put the UnitTest++ folder with the compiled library and all the source files in my project's path.
Then I created a test project for all the unit testing, with a main function containing the famous UnitTest::RunAllTests(). I put $exe_output as a post-build process here, in order to have the tests executed automatically every time I build this project.
I created the "real" project where my code to be tested will go. In the build settings I specified the test project as a dependency of the real project, so that every time I build the real one, it also builds the test project first.
With these settings I can work on my tests and on the real code, and I only have to build the real one to have the updated tests executed. Any failing test will also make the build fail.
Now two questions remain: "is this the best approach?" and "right now each project lives in a different directory. Is it wiser to leave it this way or should I put each test in the same folder as the real code to be tested?"

Unit Testing legacy C++ Code with CPPUnit

I am tasked with managing a large code base written in vc++ 6.0, I need to start building unit test for portions of the code. I have set up CPPUnit and it works with my projects DLL's the problem I am facing is as follows. The legacy application is made up of 10 static libraries and one huge executable MFC application that contains 99% of the code. My unit test framework is running in another project within the same workspace and will test the 10 libraries no problem all include and references are ok, when I try to do the same for the large MFC application I get a linker error as I do not have a dll for the application. Is there any way to unit test the application without putting the test code directly inside the application.
You should carry on as you are:
You have one test application that references libraries.
You have one main application that also references those libraries.
Either move code from the main application into the existing libraries, or, preferably, move code into new libraries. Then your test application can access more code without ever referring to the application.
You know when you are done when the source for the application consists of one module which defines main() and everything else in in libraries which are tested by the test application.
My experience with unit testing is usually the opposite. Create a project for your test then import code from your other projects.
You can't link to the MFC application probably because your functions aren't exported. They exist, but have no mean to communicate with other applications unlike DLLs.
I know of no way to link against an executable file. Refactoring the code by moving the business logic to a DLL and leaving the application as a "Front-end" would be the most obvious solution. However, since it is legacy code it is likely more appropriate to simply duplicate the code for purposes of unit testing. This is not ideal, and since it is an MFC applicaiton may not be trivially easy.
To test your main application you can set up a test project which includes the source files you want to test - not sure how easy it is to achieve with VC6, do not have it at hand, but in VS2005 and later this is quite straightforward.
So in your solution you end up with a structure like this:
MyLegacySystem.sln
MyApplication.proj
Main.cpp
BusinessRules.cpp
MyApplicationUnitTests.proj
UnitTestsMain.cpp
BusinessRules.cpp
BusinessRulesTests.cpp
If for whatever reason you cannot include your source files in 2 projects, you can pull the sources into your test project by invoking the preprocessor magic:
BusinessRulesStub.cpp:
#include "..\src\BusinessRules.cpp"
However, this is essentially a temporary fix. As already suggested, in the end most of the code should be extracted into separate libraries.
If you can't refactor your project to move the business logic into a new static library, try linking your test project against your project's intermediate object files, which you can probably find in BigProject\debug or BigProject\debug\obj . You can't link to the .EXE as you've discovered.
This achieves the same results as the copy process that Chad suggested while avoiding the actual duplication of source code, which would be a really bad thing.

Visual Studio C++: Unit test exe project with google test?

Using Visual Studio 2010 C++. I'm experimenting with unit testing and decided to try Google Test (gtest). I have an existing project which compiles to an MFC executable (I'm also interested in how to test a project that compiles to a DLL). My understanding of the convention for unit testing is that you should create a new separate project for your tests. So I created a new project in the same solution for my unit tests. But how do I link the projects? Can I test arbitrary functions/methods of my exe project from my test project?
What is the conventional way to do this?
I think the best way to organize unitary test is:
Don't change your main project. The structure should be independent of your test actions. In my opinion, changing your project to a big static lib AND an executable is really not elegant.
Instead, add a post build action to aggregate all obj files into a static lib file that will be used ONLY by your test project.
Create a simple test project, linking to your test framework AND the static library you have previously generated.
Enjoy.
The main advantages is you don't touch the project you want to test and you don't include all source code to your test project.
To see how you can do that for visual studio, you can see this post: Linking to multiple .obj for unit testing a console application
Either put the functionality you want to test into a static library which is linked into both your test project and your MFC project, or put your files in both projects. The first is more complicated, but the second will cause you to compile everything twice....
I have prepared a github repo including Visual Studio 2015 solution in parralel of Billy's answer. You can use it directly without any additional requirement or dependency.
https://github.com/fuatcoskun/GoogleTestVS2015
I hope it helps...