How do I correctly configure a UnitTest++ project?

General questions regarding the usage of CodeLite
quokka
CodeLite Curious
Posts: 3
Joined: Thu Apr 28, 2016 6:39 am
Genuine User: Yes
IDE Question: C++
Contact:

How do I correctly configure a UnitTest++ project?

Post by quokka »

I can't figure out how to make UnitTest++ work to test a class in another project in the same workspace.

I tried to follow this guide but it's not working for me: http://codelite.org/LiteEditor/UnitTestPP

I am on Linux Mint 17.3 xfce, running CodeLite version 9.1.0.

First I created a project "DummyClass." I did this by doing the following:
1) Right click on the workspace.
2) Click "Create New Project"
3) Under Console, I select "Simple executable (g++)"
4) For Project name I type DummyClass
5) I check the box that says "Create the project under a separate directory"
6) Click next/next (accept the defaults: Compiler: GCC and Debugger: GNU gdb debugger)

Inside DummyClass I create a new class named IntNum. I do this by right clicking on the virtual folder named "src" inside the DummyClass project. It is the only virtual folder in the project. I don't see the "include" virtual folder in the project like it shows in the guide.

Next I create a new project called "DummyClass_test" by doing the following:
1) Right click on the workspace.
2) Click "Create New Project"
3) Under Console, I select "UnitTest++"
4) For Project name I type DummyClass_test
5) I check the box that says "Create the project under a separate directory"
6) Click next/next (accept the defaults: Compiler: GCC and Debugger: GNU gdb debugger)


I end up with the following:

Image



In DummyClass_test/src/main.cpp, I add a sanity check to make sure I can compile and link UnitTest++ correctly:

DummyClass_test/src/main.cpp:

Code: Select all

#include <unittest++/UnitTest++.h>

TEST( Sanity )
{
    CHECK_EQUAL( 1, 1 );
}

// run all tests
int main(int argc, char **argv)
{
	return UnitTest::RunAllTests();
}
It compiles and runs. In the UnitTest++ console below, I see that I passed 1 test, and the "Passed:" bar is green.

However, then I try to add a test for IntNum in DummyClass.

First I try adding the include directive:

Code: Select all

#include "DummyClass/IntNum.h"

TEST( Sanity )
{
    CHECK_EQUAL( 1, 1 );
}

// run all tests
int main(int argc, char **argv)
{
	return UnitTest::RunAllTests();
}
but I get the error:

Code: Select all

/bin/sh -c '/usr/bin/make -j4 -e -f  Makefile'
----------Building project:[ DummyClass_test - Debug ]----------
make[1]: Entering directory `/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test'
/usr/bin/g++  -c  "/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test/main.cpp" -g  -o Debug/main.cpp.o -I. -I/src -I.
/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test/main.cpp:58:31: fatal error: DummyClass/IntNum.h: No such file or directory
 #include "DummyClass/IntNum.h"
                               ^
compilation terminated.
make[1]: *** [Debug/main.cpp.o] Error 1
make[1]: Leaving directory `/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test'
make: *** [All] Error 2
====2 errors, 0 warnings====
So I change the include directive, and it compiles:

Code: Select all

#include "../DummyClass/IntNum.h"

TEST( Sanity )
{
    CHECK_EQUAL( 1, 1 );
}

// run all tests
int main(int argc, char **argv)
{
	return UnitTest::RunAllTests();
}
But then when I try to instantiate an IntNum,

Code: Select all

#include "../DummyClass/IntNum.h"

TEST( Sanity )
{
    IntNum intNum;
    CHECK_EQUAL( 1, 1 );
}

// run all tests
int main(int argc, char **argv)
{
	return UnitTest::RunAllTests();
}
I get undefined reference errors:

Code: Select all

/bin/sh -c '/usr/bin/make -j4 -e -f  Makefile'
----------Building project:[ DummyClass_test - Debug ]----------
make[1]: Entering directory `/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test'
/usr/bin/g++  -c  "/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test/main.cpp" -g  -o Debug/main.cpp.o -I. -I/src -I.
/usr/bin/g++ -o Debug/DummyClass_test @"DummyClass_test.txt" -L. -L/Debug  -lUnitTest++
Debug/main.cpp.o: In function `TestSanity::RunImpl() const':
/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test/main.cpp:62: undefined reference to `IntNum::IntNum()'
/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test/main.cpp:63: undefined reference to `IntNum::~IntNum()'
/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test/main.cpp:63: undefined reference to `IntNum::~IntNum()'
collect2: error: ld returned 1 exit status
make[1]: *** [Debug/DummyClass_test] Error 1
make[1]: Leaving directory `/home/qk/programming_practice/CodeLiteUnitTest/DummyClass_test'
make: *** [All] Error 2
====4 errors, 0 warnings====
The constructor and destructor of IntNum are already defined in IntNum.cpp, so it's a linking error.

I tried doing what it says in the CodeLite UnitTest++ guide (right click -> UnitTest++ -> Create tests for class), but all that does is create two empty test cases in DummyClass_test/src/main.cpp:

Code: Select all


#include "../DummyClass/IntNum.h"

TEST( Sanity )
{
    IntNum intNum;
    CHECK_EQUAL( 1, 1 );
}

// run all tests
int main(int argc, char **argv)
{
	return UnitTest::RunAllTests();
}

TEST(TestIntNum_IntNum)
{
}

TEST(TestIntNum_TildaIntNum)
{
}
and I still get the undefined reference errors.

What am I doing wrong?

I can get UnitTest++ semi-working by putting the contents of DummyClass_test/src/main.cpp into a renamed file (i.e. DummyClass/src/DummyClass_test.cpp) in the DummyClass project, but then I have to rename the main() function in DummyClass/src/main.cpp to avoid the multiple definition of main() error. So if I want to run the DummyClass's main(), I rename the mangled main() in DummyClass/src/main.cpp back to main(), and rename the main() in DummyClass/src/DummyClass_test.cpp to something else (like main_()), then recompile, and vice versa. So to run either the app main() or the test main() I have manually rename the main functions to avoid the conflict. This really seems like the wrong way to do it. I'd like to do it the proper way, but I don't know what I'm doing wrong. Can anyone help?
User avatar
eranif
CodeLite Plugin
Posts: 6375
Joined: Wed Feb 06, 2008 9:29 pm
Genuine User: Yes
IDE Question: C++
Contact:

Re: How do I correctly configure a UnitTest++ project?

Post by eranif »

Looking at the workspace, DummyClass project generates an executable or a library?
If it is an executable, than you need to change that to generate a library and link that library against the test project.
Its not really a CodeLite issue, but more of a C/C++ linking problem

Eran
Make sure you have read the HOW TO POST thread
quokka
CodeLite Curious
Posts: 3
Joined: Thu Apr 28, 2016 6:39 am
Genuine User: Yes
IDE Question: C++
Contact:

Re: How do I correctly configure a UnitTest++ project?

Post by quokka »

eranif wrote:Looking at the workspace, DummyClass project generates an executable or a library?
If it is an executable, than you need to change that to generate a library and link that library against the test project.
Its not really a CodeLite issue, but more of a C/C++ linking problem

Eran
Here is my attempt at creating the DummyClass project as a static library.

First I created the DummyClass project as a static library.

Then in the UnitTest++ main file (DummyClass_test/src/main.cpp), I use this include directive.

Code: Select all

#include "IntNum.h"
To allow the compiler to find "IntNum.h", I have to add the DummyClass directory to the DummyClass_test project's include paths by doing the following: right-click on the DummyClass_test project, then click Settings, and in the Settings dialog box in the "Compiler" section, add "../DummyClass" to the "Include Paths," such that the full "Include Paths" field looks like this:
  • $(UNIT_TEST_PP_SRC_DIR)/src;.;../DummyClass
Then to get DummyClass_test/src/main.cpp to link to the DummyClass static library, in the same Settings dialog box, in the "Linker" section, I had to add "../DummyClass/Debug" to the "Libraries Search Path," such that my full "Libraries Search Path" field looks like this:
  • $(UNIT_TEST_PP_SRC_DIR)/Debug;../DummyClass/Debug
And in that same "Linker" section, I had to add "DummyClass" to the "Libraries" section, such that my full "Libraries" field looks like this:
  • libUnitTest++.a;DummyClass

Then to get the DummyClass_test project to compile, I first have to compile the DummyClass project. After that, the DummyClass_test project compiles and links to the DummyClass static library.

One problem is that every time I change IntNum.h or IntNum.cpp, I have to repeat those two compilations: First I have to to recompile the DummyClass project to update the static library, and then I have to recompile the DummyClass_test project to link to the updated static library, and then I can run the test.


Is this the correct way of using UnitTest++ within CodeLite?

I think I can eliminate having to compile twice by writing my own Makefile, outside of CodeLite, by writing rules to make the static archive a prerequisite of DummyClass_test, but I would like to stay within the IDE, if possible.

Is there a better method of using UnitTest++ within CodeLite that you can recommend?
User avatar
eranif
CodeLite Plugin
Posts: 6375
Joined: Wed Feb 06, 2008 9:29 pm
Genuine User: Yes
IDE Question: C++
Contact:

Re: How do I correctly configure a UnitTest++ project?

Post by eranif »

Right click on the UnitTest++ project and select "Build Order..." and link between the two projects
Eran
Make sure you have read the HOW TO POST thread
quokka
CodeLite Curious
Posts: 3
Joined: Thu Apr 28, 2016 6:39 am
Genuine User: Yes
IDE Question: C++
Contact:

Re: How do I correctly configure a UnitTest++ project?

Post by quokka »

That did it, it worked.

Thank you.
Post Reply