[http://www.systest.ch/testing/qtrunner/qttestrunner_sample.png]

[[TableOfContents]]

== General Remarks ==
  
 *As with the other GUI test runners for the CppUnit testing framework the QtTestRunner can be used to unit test any kind of C++ software, it's not limited to Qt applications.

 *QtTestRunner as currently shipped with CppUnit 1.10.2 is based on Qt version 2.x, this page describes how to build QtTestRunner with Qt 3.x . IMPORTANT: it does not work with Qt4, as it is not backwards compatible with Qt3.

 *The QtTestRunner GUI as provided has the disadvantage of clenching test failure reports consisting of several lines into a single line in its failure list, which makes them rather unreadable. This document describes how to solve this drawback easily with little changes in QtTestRunner source code. 

 *In the remaining documentation the identifier '''CPPUNIT''' stands for the top directory of the CppUnit installation and the identifier '''QTDIR''' stands for the top directory of the Qt installation.

 *At least amongst MS Windows programmers it became common sense to distinguish different library types with an appropriate file name suffix. Libraries in debug mode often have a 'd' and dynamic libraries have a '_dll', which leads to combinations such as 'd_dll', for example cppunitd_dll.dll. This naming convention can be seen as a matter of taste but as learned from experience it's also helpful for Linux/Unix development. A reason for this is the fact that the GNU linker 'ld' by default links with shared images. If there are two library files with the same file name but different file types (.a and .so) in a directory then 'ld' will link with the .so type even when it gets the .a file as an input parameter (this behaviour can be overriden of course, but it's not obvious at first sight). Therefore the scripts presented here create the different flavors of the QtTestRunner library with different file names which makes the creation and verification process more transparently.

'''Note about Qt 4.x:'''

 *Upgrading QtTestRunner to Qt4 is not a simple matter of running the Qt3 to Qt4 migration tools available at [http://doc.trolltech.com/4.0/porting4.html]. Some methods present in the Qt3 API have been removed from Qt4, such as QThread::postEvent used in QtTestRunner's source code. If you manage to make QtTestRunner work with Qt4 please post a patch! - I'll try.

 *Trolltech intends to release its internally used test framework Qt``Test to the public in one of its next Qt 4.x releases, thereby QtTestRunner could get obsolete (?). 

 *[http://sourceforge.net/projects/qtwin Qt/Win free project] provides a patch to compile Qt 4 Open Source Edition with Visual Studio and Borland C++.

== General Requirements ==

 *The Qt framework is installed, if not yet, then get it from [http://www.trolltech.com/download]. 

 *An environment variable named '''QTDIR''' must point to the top directory of the Qt installation on the system where the QtTestRunner library will be created and used.

 *qmake is Trolltech's tool for generating Makefiles out of Qt project files (.pro). qmake presets the {{{CONFIG}}} system variable with the options used to build the Qt libraries. Should any options be missing to build the QtTestRunner library using one of the .pro files presented here than provide them by yourself in accordance with your Qt installation. Such options can be: {{{exceptions rtti stl}}}. How the Qt libraries were originally built is stored in different files, for example in file {{{QTDIR\.qtwinconfig}}} on MS Windows platforms and in {{{QTDIR/.qmake.cache}}} on all platforms. Other files are also involved in the Makefile creation process such as {{{qmake.conf}}}. Please read the qmake documentation for more information.

== QtTestRunner for Microsoft Windows ==

This section describes how to create and test the QtTestRunner library for Windows (2000, XP) with Microsoft VC++ 7.0 and Qt 3.x. The library can either be built with the Microsoft IDE or from the command line using qmake with Qt project files (.pro). Working with the IDE is the preferred approach because it ensures that all environment settings are correct and one isn't bothered with the proper settings of the {{{PATH}}}, {{{INCLUDE}}} or {{{LIB}}} environment variables.
  
 *It's important that all libraries used in a program use the same runtime library, i.e. if the QtTestRunner library used in a test program was created with the multi-threaded DLL runtime then the CppUnit library must have been built analogous. 

 *For building the QtTestRunner library as a DLL the '''QTTESTRUNNER_DLL_BUILD''' preprocessor definition is required when compiling the QtTestRunner source files. 

 *Programs using the QtTestRunner DLL must be compiled with the '''QTTESTRUNNER_DLL''' preprocessor definition. This isn't required when linking with the static QtTestRunner library. 

 *When the QtTestRunner library is built as a DLL with the scripts described below it always gets linked with the corresponding CppUnit DLL, but there is nothing against linking it with the static CppUnit library. 

=== Prerequisites ===
  
 *The CppUnit libraries are in the {{{CPPUNIT\lib}}} directory. Most likely there will be static and dynamic versions of the CppUnit library in debug and release mode namely {{{cppunitd.lib}}}, {{{cppunit.lib}}}, {{{cppunitd_dll.lib}}}, {{{cppunitd_dll.dll}}}, {{{cppunit_dll.lib}}} and {{{cppunit_dll.dll}}}. 

 *The source code of QtTestRunner is located in {{{CPPUNIT\src\qttestrunner}}}. 

=== Building the QtTestRunner Library with the Microsoft IDE ===

The solution and project files mentioned in this section were created with the Microsoft Development Environment 2003 for VC++ 7.0 and the .NET framework 1.1.
    
 1. Since there is no solution file included in the CppUnit distribution, you should download the packed archive file [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip]. This file contains all the QtTestRunner source files as well as the solution file '''QtTestRunner.sln''' and the project files '''qttestrunner.vcproj''' and '''qttestrunner_dll.vcproj''' suitable for the IDE. 

 1. Either
  *unpack the [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] file into a temporary location and then copy {{{QtTestRunner.sln}}}, {{{qttestrunner.vcproj}}} and  {{{qttestrunner_dll.vcproj}}} to {{{CPPUNIT\src\qttestrunner}}} or

  *delete the contents of {{{CPPUNIT\src\qttestrunner}}} and then unpack the [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] file into this directory, i.e. replace all the QtTestRunner files with the unpacked ones. 

 1. Open {{{QtTestRunner.sln}}} with the IDE which will show the two projects {{{qttestrunner}}} and {{{qttestrunner_dll}}} in the solution explorer.

 1. To successfully build the QtTestRunner library as a DLL the Qt library name must be adjusted in the linker's additional  dependencies settings of the {{{qttestrunner_dll}}} project to correspond with your Qt version. For creating a static QtTestRunner library the Qt library isn't needed. 

 1. Choose the configurations of interest in the IDE and let the build  process start. After successfull completion there will be, depending on the chosen configurations, static and dynamic versions of the QtTestRunner library in debug and release mode in the {{{CPPUNIT\lib}}} directory, namely {{{qttestrunnerd.lib}}}, {{{qttestrunner.lib}}}, {{{qttestrunnerd_dll.lib}}}, {{{qttestrunnerd_dll.dll}}}, {{{qttestrunner_dll.lib}}} and {{{qttestrunner_dll.dll}}}. 

=== Building the QtTestRunner Library from the Command Line ===

The [http://www.trolltech.com/products/qt/qmake.html qmake] and nmake utilities are used when creating the QtTestRunner library from the command line. However, if possible build the library with the IDE, otherwise you could end up spending some time for adjusting environment variables. This is especially true if different VC++ versions are installed on a system.
  
 1. [http://www.systest.ch/testing/qtrunner/qttestrunnerlib.pro qttestrunnerlib.pro] is a slightly improved qmake project file compared to qttestrunner.pro as provided with the CppUnit distribution. Download [http://www.systest.ch/testing/qtrunner/qttestrunnerlib.pro qttestrunnerlib.pro] and save it in {{{CPPUNIT\src\qttestrunner}}} or download [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] and extract {{{qttestrunnerlib.pro}}} from it into {{{CPPUNIT\src\qttestrunner}}}.

 1. Open a command window and set the working directory to {{{CPPUNIT\src\qttestrunner}}}.

 1. Enter[[BR]] {{{qmake qttestrunnerlib.pro}}}[[BR]] to create the file {{{Makefile}}} in the current directory. To run qmake like this {{{QTDIR\bin}}} must be in the {{{PATH}}} environment variable.

 1. Enter[[BR]] {{{nmake}}}[[BR]] which uses {{{Makefile}}} to build the QtTestRunner library. By default the library is built as static in debug mode. See the comments in [http://www.systest.ch/testing/qtrunner/qttestrunnerlib.pro qttestrunnerlib.pro] for how to build it in another fashion. After successfull completion there will be, depending on the chosen configurations, static and dynamic versions of the QtTestRunner library in debug and release mode in the {{{CPPUNIT\lib}}} directory, namely {{{qttestrunnerd.lib}}}, {{{qttestrunner.lib}}}, {{{qttestrunnerd_dll.lib}}}, {{{qttestrunnerd_dll.dll}}}, {{{qttestrunner_dll.lib}}} and {{{qttestrunner_dll.dll}}}.

 * In [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] the script {{{make_lib.bat}}} is included, which does the two previous steps at once.

=== Related Pictures ===

This picture shows where to set preprocessor definitions in the project properties dialog of the Microsoft IDE:

[http://www.systest.ch/testing/qtrunner/preprocessor_defs.png]

This picture shows where to set the runtime library in the project properties dialog of the Microsoft IDE:

[http://www.systest.ch/testing/qtrunner/runtime_lib.png]

This picture shows where to define additional input files for the linker in the project properties dialog of the Microsoft IDE:

[http://www.systest.ch/testing/qtrunner/linker_input.png]

== QtTestRunner for Linux/Unix ==

This section describes how to create and test the QtTestRunner library for Linux (2.6.5-7.95-smp) with g++ (2.95.3) and Qt 3.x. The library is built from the command line using qmake with Qt project files (.pro). Building the library on other Unix OS should work as well.

 *When the QtTestRunner library is built as a shared image (dynamic library) with the scripts described below it always gets linked with the {{{cppunit}}} library. Whether this is the shared or static CppUnit library depends on the CppUnit installation. See the general remarks at the beginning of this page about this issue. For the QtTestRunner library to work it's irrelevant which CppUnit library type it gets linked with. 

=== Prerequisites ===

 *The CppUnit libraries are in the {{{CPPUNIT/lib}}} directory. Most likely there will be static and dynamic versions of the CppUnit library either in debug or release mode, depending on your installation, named {{{libcppunit.a}}} and {{{libcppunit.so}}} as well as a helper file {{{libcppunit.la}}}.

 *The source code of QtTestRunner is located in {{{CPPUNIT/src/qttestrunner}}}.

=== Building the QtTestRunner Library ===

The [http://www.trolltech.com/products/qt/qmake.html qmake] and make utilities are used for creating the QtTestRunner library from the command line.
  
 1. [http://www.systest.ch/testing/qtrunner/qttestrunnerlib.pro qttestrunnerlib.pro] is a slightly improved qmake project file compared to qttestrunner.pro as provided with the CppUnit distribution. Download [http://www.systest.ch/testing/qtrunner/qttestrunnerlib.pro qttestrunnerlib.pro] and save it in {{{CPPUNIT/src/qttestrunner}}} or download [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] and extract {{{qttestrunnerlib.pro}}} from it into {{{CPPUNIT/src/qttestrunner}}}.

 1. Open an XTERM or similar console window and set the working directory to {{{CPPUNIT/src/qttestrunner}}}.

 1. Enter[[BR]] {{{qmake qttestrunnerlib.pro}}}[[BR]] to create the file {{{Makefile}}} in the current directory. To run qmake like this {{{QTDIR/bin}}} must be in the {{{PATH}}} environment variable.

 1. Enter[[BR]] {{{make}}}[[BR]] which uses {{{Makefile}}} to build the QtTestRunner library. By default the library is built as static in debug mode. See the comments in [http://www.systest.ch/testing/qtrunner/qttestrunnerlib.pro qttestrunnerlib.pro] for how to build it in another fashion. After successfull completion there will be, depending on the chosen configurations, static and dynamic versions of the QtTestRunner library in debug and release mode in the {{{CPPUNIT/lib}}} directory, namely {{{libqttestrunnerd.a}}}, {{{libqttestrunner.a}}}, {{{libqttestrunnerd_shared.so}}} and {{{libqttestrunner_shared.so}}}.

 * In [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] the tcsh shell script {{{make_lib}}} is included, which does the two previous steps at once.

== Verifying the QtTestRunner Library ==

 *A sample application helps in verifying that the QtTestRunner library works as expected.

 *Get an overview by reading the [http://www.systest.ch/testing/qtrunner/sample/doc/index.html Sample Testing Application] online documentation.

=== Prerequisites ===

 *An environment variable named '''CPPUNIT''' must point to the top directory of the CppUnit installation.

 *The CppUnit and QtTestRunner libraries reside in the {{{lib}}} subfolder of where the {{{CPPUNIT}}} environment variable points to.

=== Verification on Microsoft Windows ===

The solution and project files mentioned in this section were created with the Microsoft Development Environment 2003 for VC++ 7.0 and the .NET framework 1.1.

 1. Download the packed archive file [http://www.systest.ch/testing/qtrunner/sample/SampleTestApp.zip SampleTestApp.zip]. This file contains the source codes of the sample application and sample unit tests, the doxygen configuration file for creating its online documentation and the solution files {{{SampleTestApp.sln}}} and {{{SampleTestApp_with_DLL.sln}}} respectively.

  * '''Sample``Test``App.sln''' includes the '''Sample``App.vcproj''' project file for building the sample application and the '''Sample``Unit``Test.vcproj''' project file for building the sample unit test program with the CppUnit and QtTestRunner static libraries linked in.

  * '''Sample``Test``App_with_DLL.sln''' includes the same  '''Sample``App.vcproj''' project file for building the sample application but differs in that it includes the '''Sample``Unit``Test_with_DLL.vcproj''' project file which is configured for building the sample unit test program and linking it with the CppUnit and QtTestRunner dynamic libraries. 

 1. Unpack [http://www.systest.ch/testing/qtrunner/sample/SampleTestApp.zip SampleTestApp.zip] to a location of your choice.

 1. To test the static QtTestRunner library open {{{SampleTestApp.sln}}} with the IDE which will show the two projects {{{SampleApp}}} and {{{SampleUnitTest}}} in the solution explorer.

  a. To successfully build the unit test program the Qt library name must be adjusted in the linker's additional dependencies settings of the Sample``Unit``Test project to correspond with your Qt version.

  a. Choose the configurations of interest in the IDE and let the build process start for both projects. After successfull completion there will be a {{{SampleApp.exe}}} representing the sample application program and a {{{SampleUnitTest.exe}}} representing the unit test main program. These executables now can be run independently. 

 1. To test the QtTestRunner DLL open {{{SampleTestApp_with_DLL.sln}}} with the IDE which will show the two projects {{{SampleApp}}} and {{{SampleUnitTest_with_DLL}}} in the solution explorer. 

  a. Here too, adjust the Qt library name in the linker's additional dependencies settings to correspond with your Qt version. Do it for the {{{SampleUnitTest_with_DLL}}} project.

  a. Again choose the configurations of interest in the IDE and let the build process start for both projects. After successfull completion there will be a {{{SampleApp.exe}}} representing the sample application program and a {{{SampleUnitTest.exe}}} representing the unit test main program. These executables now can be run independently. 

  a. Make sure that {{{CPPUNIT\lib}}} is in the {{{PATH}}} environment variable so that the unit test program {{{SampleUnitTest.exe}}} can load the DLL's at run-time. 

=== Verification on Linux/Unix ===

The configuration files needed to build the sample application are written for Linux (2.6.5-7.95-smp) with g++ (2.95.3) but should work fine in similar environments.

 1. Download the packed archive file [http://www.systest.ch/testing/qtrunner/sample/SampleTestApp.zip SampleTestApp.zip]. This file contains the source codes of the sample application and sample unit tests, the doxygen configuration file for creating its online documentation and the qmake configuration files {{{SampleTestApp.pro}}},  {{{SampleApp.pro}}} in the {{{SampleApp}}} subdirectory and {{{SampleUnitTest.pro}}} in the {{{SampleUnitTest}}} subdirectory.

  *'''Sample``Test``App.pro''' includes the '''Sample``App.pro''' project file for generating the Makefile for the sample application and the '''Sample``Unit``Test.pro''' project file for generating the Makefile for the sample unit test program.

  *By default the unit test program gets linked with the Qt``Test``Runner static library and the static or dynamic CppUnit library depending on which type is found on your system. Adjust the {{{CONFIG}}} system variable in {{{SampleUnitTest.pro}}} to link with other types of the Qt``Test``Runner library. See the comments in this .pro file.

 1. Unpack [http://www.systest.ch/testing/qtrunner/sample/SampleTestApp.zip SampleTestApp.zip] to a location of your choice.

 1. Open an XTERM or similar console window and set the working directory to where the .zip file was unpacked.

 1. Enter[[BR]] {{{qmake SampleTestApp.pro}}}[[BR]] to create a {{{Makefile}}} in the current directory. To run qmake like this {{{QTDIR/bin}}} must be in the {{{PATH}}} environment variable.

 1. Enter[[BR]] {{{make}}}[[BR]] which uses {{{Makefile}}} for building the Makefiles and then 'making' the targets in the subdirectories.

 1. After successfull completion there will be a {{{SampleApp}}} executable representing the sample application program and a {{{SampleUnitTest}}} executable representing the unit test main program. These executables now can be run independently.

  a. Make sure that {{{CPPUNIT/lib}}} is in the {{{LD_LIBRARY_PATH}}} environment variable so that the unit test program {{{SampleUnitTest}}} can load the shared images at run-time in case of being linked with them.

 *The {{{SampleApp}}} and {{{SampleUnitTest}}} executables can be built separately. Just use qmake with their .pro files for generating Makefiles and then 'make' them.

== Multi Line Failure Reports ==

What's left is the little code correction before building the library to improve the readability of multi 
line failure reports in the GUI. What is meant here can best be explained with 
pictures.

This is how it looks with the QtTestRunner included in the CppUnit distribution:

[http://www.systest.ch/testing/qtrunner/qttestrunner_orig.png]

And this is how you probably prefer to have it displayed:

[http://www.systest.ch/testing/qtrunner/qttestrunner.png]

The failure reports are displayed in Q``List``View``Items which can be set to be "multi line". By default this property is disabled. Therefore two source files of QtTestRunner, found in {{{CPPUNIT\src\qttestrunner}}} need to be changed in order to have this property used right.

In file {{{TestFailureListViewItem.cpp}}} the property gets set by adding the {{{setMultiLinesEnabled (true)}}} statement in the class constructor as shown below:

{{{
TestFailureListViewItem::TestFailureListViewItem(
                           TestFailureInfo *failure,
                           QListView *parent ) : 
    QListViewItem( parent ),
    _failure( failure )
{
	setMultiLinesEnabled (true);
}
}}}

In file {{{TestRunnerDlgImpl.cpp}}} unnecessary white space needs to be stripped away in method {{{ TestRunnerDlg::reportFailure( TestFailureInfo *failure ) }}} by replacing the statement

{{{
item->setText( indexMessage, thrownException->what() );
}}}
with
{{{
item->setText( indexMessage, QString(thrownException->what()).stripWhiteSpace() );
}}}

That's all there is to do. By downloading [http://www.systest.ch/testing/qtrunner/qttestrunner.zip qttestrunner.zip] you get the already corrected source files.
