c++ testing herimitic library - c++

I decided to add tests for my library.
The problem is that most (all?) of the test frameworks are using the same approach: build an executable file which contains code to be tested, tests and framework.
But what if I have a library which is heavy (a lot of code inside) but has only a few public functions / classes? In such situation I cannot test it well until:
I export all symbols from library
I build executable file with all library sources included
Ad. 1: it's not nice
Ad. 2: when I work with visual studio it would require me to synchronize library project with 'test' executrable project (adding/removing files etc). So it also doesn't look nice for me.
Are there any other approaches?

If you can do 2) so you should be able to reorganize your file/folder/project like;
1) a static library project containing all the internal function and object
2) a test project using any framework (there is a lot of framework with pro&con for each, my advice if you are beginner select the integrated solution or a simple framework). that test project must DEPEND (add dependcy in solution explorer menu) of the static lib. So you can add test on your internal implemtation
now the external api.
3) your old DLL project keep only the public API definition and implementation. And DEPEND of the static lib.
4) add a test project for your public api
No need to synchronize project and compile code twice, and with effort you could test more than just the external api without any internal code change.

Generally, test-driven programming works well with many and small "units". Having a few and bloated "units" makes the testing phase untolerable!
The only viable solution I see is to isolate specific parts of the code and then step into them with the debugger. Having many private functions usually leads to the aforementioned issue and since you can't access them directly during unit tests, you should really consider using the debugger for the non-obvious.

Related

How to write Visual Studio unit tests for private C++model layer in MVVM Windows Store app?

I am in the process of writing a fairly complex Windows Store app. To keep the code maintainable, I would like to make good use of unit tests. So far my solutions consists of the following:
A C#/XAML project for the app itself and the view layer
A C++ Windows Store project wherein the ViewModel layer consists of managed WinRT ref classes while the model layer is straight C++ and entirely hidden from the view layer.
A C# Windows Store unit test project to test the ViewModel layer.
A C++ project to do some DirectX rendering (part of the view layer and not really relevant for this post)
Testing the C++ WinRT ViewModel classes with the C# project is working fine. It doesn't matter that a different language because everything is public and using the WinRT interface.
However, for testing the model layer classes I am not sure what to do. I would like my test cases to be in a separate project, but I am not sure if this even possible. I want to keep everything here standard C++ for portability reasons. Furthermore, I am trying to keep everything hidden so that I can adhere to strict MVVM design.
How should I write Visual Studio unit tests (like those which are in my ViewModel "Unit Test Library (Windows Store apps)") for my standard C++ model layer?
One option I'm looking at right now is to create a "Native Unit Test Project" and use the folder for my model layer project as an include directory for that. Seems like I'm almost there, but I'm getting "error LNK2019: unresolved external symbol". How can I build the CPP files for the objects that include with the test project.
You should create a native C++ test project to test your business code. But there are several project settings need to be changed:
Set include path to your business code, esp. header files.
Include all source code files in the test project. Or else you will get linker complains unresolved symbol error, because only header files are included, but not implementations (*.cpp).
Link/ignore all libs your business code needs. (same as your production project) Don't forget to set correct link path.
Doing this will increase the compile time (same code compiled twice) as well as binary size (all business code has to be compiled/linked in test binaries).
But as far as I know, if your project is not a dynamic/static library, but an executable or some other format cannot export symbols, this is the only way.

How to setup seperate Boost Test project in Visual Studio 2010

I want to use Boost Test to unit test my code in Visual Studio 2010. I've downloaded and built the latest version of the library.
I've read a lot on the subject here and elsewhere on the internet and people seem to suggest having a second project within your solution exlusively for your tests.
Fine, sounds good. I'm having trouble actually setting this up however. I've yet to find a clear explanation of the best way to set this up.
Do I need to use a Project Reference to make my unit test project reference my main project?
If so, do I still need to add the Include & Source directories of my main project in the properties of my unit test project? If so, what's the advantage of using the Project Reference in the first place?
Do I have to have my main project output a library for my unit test project to link in? Again, I thought that Project References would make this unnecessary but it seems I don't really understand the Project References.
If at all possible could I get a very idiot proof, step by step procedure for setting up a Boost Test unit test project alongside a main project in VS2010?
Would I be better off going with the method laid out here (one project, different configurations to build tests or actual project exe):
http://blog.yastrebkov.com/2010/07/boost-test-setup-and-usage.html
Many thanks,
There is no magic behind setting up a Boost.Test project. Maybe because it's a regular C++ (executable) project in no way different from a "normal" application. This is what I do:
Create a new C++ project. I always choose Win32 Executable with precompiled headers. I have a naming convention, that all test projects using Boost.Test start with "tests.boost.testee_name..."
In "stdafx.h", add the include for <boost/unit_test.hpp> and define the BOOST_TEST_MODULE (I always choose the project name). Also, add all other includes for external components this project requires, e.g. other boost libraries, stl headers etc. This results in considerably faster compilation times.
The testee must be a library (dynamic or static). So "add reference" to all required dependencies. You can of course test header-only libraries, in that case do not add references.
Add source files to your test project, according to Boost.Test manual. The convention I enforce is one BOOST_FIXTURE_TEST_SUITE per file.
For convenience, I have a custom property sheet tailored for boost unit test, which I add to each boost test project. Among others it contains a post-build event, which runs the tests.
I have to add that, lately, I switched to MSTest with Visual Studio 2012 which allows a more comfortable way to manage the tests and test results. Nevertheless, for the most important parts of the software, I am still writing boost tests in order to ensure correctness with older toolsets and potentially other platforms.
Cheers,
Paul

Which C++ Unit Test framework does not require I build my application as a library?

I would like to write some test code for a C++ class. Because the class is part of an application but not a part of library I would like to know which unit test framework does not require building project as a library in order to run unit test code?
I tried the WinUnit but it seems only can test a library.
Any testing framework I know would allow that. It is an issue with the setting for your build environment, not the testing framework itself.
The easiest way to maintain it is to set up a library for your application code though.
I never used WinUnit, but I have used CppUnit and GoogleTest within VisualStudio projects where the code under test was not in a library, but the implementation files for the SUT were referenced (included) in the unit test project and it worked out.
Executables don't export symbols by default. You need to enable that with -Wl,--export-dynamic then link against the produced executable as though it was a library. This also means you need to do proper import/export on the classes you want to use etc.

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.

How do you run your unit tests? Compiler flags? Static libraries?

I'm just getting started with TDD and am curious as to what approaches others take to run their tests. For reference, I am using the google testing framework, but I believe the question is applicable to most other testing frameworks and to languages other than C/C++.
My general approach so far has been to do one of three things:
Write the majority of the application in a static library, then create two executables. One executable is the application itself, while the other is the test runner with all of the tests. Both link to the static library.
Embed the testing code directly into the application itself, and enable or disable the testing code using compiler flags. This is probably the best approach I've used so far, but clutters up the code a bit.
Embed the testing code directly into the application itself, and, given certain command-line switches either run the application itself or run the tests embedded in the application.
None of these solutions are particularly elegant...
How do you do it?
Your approach no. 1 is the way I've always done it in C/C++ and Java. Most of the application code is in the static library and I try to keep the amount of extra code needed for the application to a minimum.
The way I approach TDD in Python and other dynamic languages is slightly different in that I leave the source code for the application and tests lying around and a test runner finds the tests and runs them.
I tend to favour static libs over dlls so most of my C++ code ends up in static libs anyway and, as you've found, they're as easy to test as dlls.
For code that builds into an exe I either have a separate test project which simply includes the source files that are under test and that are usually built into the exe OR I build a new static lib that contains most of the exe and test that in the same way that I test all of my other static libs. I find that I usually take the 'most code in a library' approach with new projects and the 'pull the source files from the exe project into the test project' approach when I'm retro fitting tests to existing applications.
I don't like your options 2 and 3 at all. Managing the build configurations for 2 is probably harder than having a separate test project that simply pulls in the sources it needs and including all of the tests into the exe as you suggest in 3 is just wrong ;)
I use two approaches, for dlls I just link my unit tests with the dll, easy. For executables I include the source files that are being tested in both the executable project and the unit test project. This adds slightly to the build time but means I don't need to separate the executable in to a static lib and a main function.
I use boost.test for unit testing and cmake to generate my project files and I find this the easiest approach. Also I am slowly introducing unit-testing to a large legacy code base so I am trying to introduce the least amount of changes, in case I inconvenience other developers and discourage them from unit testing. I would worry that using a static library just for unit testing might be seen as an excuse not adopt it.
Having said this, I think the static library approach is a nice one especially if you are starting from scratch.
For C/C++ apps I try to have as much code as possible in one or more dlls, with the main application being the bare minimum to start-up and hand-off to the dll. Dlls are much easier to test because they can export as many entry points as I like for a test application to use.
I use a seperate test application that links to the Dll(s). I'm strongly in favour of keeping test code and "product" code in seperate modules.
I go with #1, some reasons are
It allows to check that each lib links correctly
You don't want extra code in the product
It's easier to debug individual small test programs
You may need multiple executables for some tests (like communication tests)
For C++ build and test, I like to use CMake which can run a selection of the target executables as tests and print a summary of the results.
Personnally, I use another approach that relies a bit on yours:
I keep the project-to-test intact. If it's an executable, it should stay an executable. You simply create a post build action in order to aggregate all obj files into a static library.
Then, you can create you test project, linking the test framework and your previously generated static library.
Here are some topics corresponding to your question:
Visual Studio C++: Unit test exe project with google test?
Linker error - linking two "application" type projects in order to use Google Test
I'm using a third-party test-runners with their framework and including testing in build script. Tests are outside of production code (external dll).