Using QT Unit Tests in a project - conflicting main(...) functions - c++

I set my first steps upon the noble path of using unit tests to develop my application, but it proves to be a steep and rough one. I'm developing an application in Qt, so thought to reach for their QTestLib framework. Now, I understand how to make unit tests, but I can't seem to figure out how to incorporate unit testing into a project.
Say I have a console application which just has a main.cpp and a cpp and h file for a class I want to develop, say MyClass. I guess the right thing to do would be to create a corresponding test class MyClassTest with its h and cpp files. But should I put it into the same project? Or rather create a separate project just for unit tests that will have access to files in "main" project (not sure how would I do that yet)?
And if both main application and the test are in the same project, how do I run tests without running the application or the other way round? I tried incorporating files from Qt's Tutorial 1 on unit testing into a console project, but the problem with it is that they use a macro QTEST_MAIN(TestQString) which expands into a main(...) function. This causes conflicts with the main(...) in the main.cpp. Well, I can rename either one, but the problem still stands - how do I then run either the tests or the application itself? If I override QTEST_MAIN macro (which is a bad idea anyway) I disable the tests. If I rename main(...) function in the main.cpp, then the actual application never gets executed. I guess there should be a way to make two separate executables for the project, one running unit tests, and another launching the application, but can't figure out how to go about it.

Definitely create a separate project for your tests. If you arrange the application project and test project in side-by-side directories, you should be able to reference your code units from your application project using relative paths in your test.pro file.
I use the very handy test runner presented on this blog.

Related

How to include my testable project in my Unit test project

I'm trying to create a unit test in QTCreator so I've followed this tutorial from the QT Docs:
https://doc.qt.io/qt-6/qttestlib-tutorial1-example.html
This runs example fine for me.
Unfortunately, this tutorial, and a few others I've found all give examples referencing classes included within the Unit Test project itself. But I would have thought the proper way would be to use my Unit Test project to create tests for the separate actual application that I'm trying to test. (after all, I can't add QTEST_MAIN to my own project as it has its own main).
So how do I include the testable in the unit test project and refer to the functions that I am trying to test?

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.

Organizing unit testing for existing code

I recently received as a new task to maintain and improve existing code written in C++ with MS Visual Studio. The code builds into an exe file (not a dll). I would like to add unit tests for the code and the problem I encountered is how to organize my testing projects. Basically I want to have 2 projects, one would be the original project I received and the second the testing project.
I saw on the Internet that usually when the subject being tested is built into a dll it's quite easy you have to statically link in your testing project the lib built from the main project and you have access to the function being tested. But how can this be done when the subject under test is an exe file?
Surely you can arrange the solution into projects that share code, where one project outputs to exe and the other(s) to DLL?
Whatever the project deliverable is, unit testing is testing the smallest units: the functions. A unit test typically follows the tripe A pattern: Arrange (create the environment for the test), Act (invoke the method under test), Assert (verify the method behaved as expected).
There are several possible project[s] structures: modify the project so that it compiles into a DLL, a production executable and a unit test program. The executable source has to be as small as possible, possibly just the main() function that create an Application object. It is also possible to have three projects, one for the DLL, one for the application and the third one for the tests.
An alternative is to embed the unit tests inside the executable and to have a mean to invoke them, e.g. with a special --unit-test parameter.

Seeking suggestions for Unit Testing C++ app spread over several dlls

New to unit testing and have an app that is spread out over several dlls. What are some suggestions for unit testing the app? If I put the unit tests in their own project, i can only test the published interface for each dll. Is that what most people do? Or should I put the unit tests in with the code in the dlls and test there? What would be the best way to coordinate all the tests at that point?
Most of the examples I've seen for using the various frameworks don't really address this and I've search elsewhere but haven't found much information.
Thanks.
Update:
I guess to clarify a bit I have class A and class B in a dll. Class B is used by Class A, but only Class A is exposed. I'm wanting to get unit tests in place before refactoring this existing code.
So the question is should I put unit tests in with the dll code to test class A and class B directly and/or have the unit tests in a separate project and test class A and class B through the exposed class A?
My home-rolled approach to this is to build two different targets:
the DLL itself
a test executable
The code base is the same except for main.cpp which will contain a DLL main for the DLL and a standard C/C++ int main() for the test executable. All the unit tests are in-line with the actual code, controlled by a preprocessor #define:
#ifdef TESTING
tests here
#endif
The main() for the executable calls all the tests via a registration framework.
Most of the time I work with the executable version with TESTING defined. When I want to build the DLL, I switch targets and undefine TESTING.
Unit testing in C++ means rather class testing. DLL testing would be rather integration testing. Both are necessary, but it's better to test things at as low level as possible. Take a look on v-model: http://en.wikipedia.org/wiki/V-Model_(software_development).
If I put the unit tests in their own project, i can only test the published interface for each dll.
As opposed to features in the DLL that client code cannot access?
If code doesn't contribute to the functions the DLL exposes, then delete it from the code base. If it does, then you can write a test that exercises that code path.
In general, thoroughly testing the public interface of a DLL should be sufficient and, as Pete indicated, should indeed exercise all code paths.
Regarding Neils' answer, choosing a test framework that does not require you to build EXEs but rather directly operates on DLLs could further simplify matters. Being the author of cfix, I'd naturally recommend giving cfix a try: http://www.cfix-testing.org/
I use boost.test to test my dlls and executables. I create a seperate unit test project/executable for each dll and exe to test. Because I test the internals of the dll I do not link them with the test project, but include the source I want to test directly in the project. Finally the automated build runs all the unit test projects.
We use CMake to build our projects and this has a nice component CTest that bundles up all our tests for us and runs them as a group.