Posts Tagged ‘Qt’

The QTestLib framework is a tool for unit testing Qt based applications and libraries. I find it precious and simple to use, though it lacks some important features, supported, for example, by GTest. I’m not talking about mocking – for this you generally need an out-and-out framework (like GMock) – instead, I’m referring to simple things like fast deploying. Suppose you have written a test class like this:

#ifndef WIDGETTEST_H
#define WIDGETTEST_H

#include <QObject>

class WidgetTest : public QObject
{
 Q_OBJECT
private slots:
 void My_first_test();
 void On_button_pressed_should_save_the_world();
};

#endif //WIDGETTEST_H

The simplest approach to run all tests is to call QTest::qExec in your main:

#include "WidgetTest.h"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    WidgetTest wtest;
    return QTest::qExec(&wtest, argc, argv);
}

Now what if you add a new test class? This approach brings you about:

  • Adding a new test (ok, this is normal),
  • Including its header in main.cpp (bad),
  • Laying a hand on the code in main.cpp (super bad), maybe xor-ing all the results.

This can be a pain for your productivity – before, the term “deploying” was related to “up and running on continuous integration systems” (e.g. TeamCity).

So, the first thing is about this. How to provide a simple and fast way to add new test classes with minimal impact? I’d like to write support code once.

The approach I currently use is this:

  • I have a test runner that holds a list with all the test objects to run,
  • each test class includes this runner and uses a special macro to add itself to the list,
  • main.cpp includes the runner and uses another macro to run all tests.

Let me show you the code:

#ifndef TESTRUNNER_H
#define TESTRUNNER_H

// Qt includes
#include <QTest>
#include <QSharedPointer>
// std includes
#include <algorithm>
#include <list>
#include <iostream>

//////////////////////////////////////////////////////////////////////////
// Test Runner allows automatic execution of tests
class TestRunner
{
public:

static TestRunner& Instance()
{
   static TestRunner instance;
   return instance;
}

template <typename T>
char RegisterTest(char* name)
{
   if ( std::find_if( begin(m_tests), end(m_tests), [&name](QSharedPointer<QObject>& elem)
   { return elem->objectName() == name; }) == end(m_tests) )
    {
      QSharedPointer<QObject> test(new T());
      test->setObjectName(name);
      m_tests.push_back(test);
   }
   return char(1);
}

int RunAll(int argc, char *argv[])
{
   int errorCode = 0;
   std::for_each( begin(m_tests), end(m_tests), [&] (QSharedPointer<QObject>& test)
   {
      errorCode |= QTest::qExec(test.data(), argc, argv);
      std::cout << std::endl;
   } );

   return errorCode;
}

private:
   std::list<QSharedPointer<QObject>> m_tests;
};

// Use this macro after your test declaration
#define DECLARE_TEST(className)\
    static char test_##className = TestRunner::Instance().RegisterTest<className>(#className);

// Use this macro to execute all tests
#define RUN_ALL_TESTS(argc, argv)\
    TestRunner::Instance().RunAll(argc, argv);

#endif // TESTRUNNER_H

The trick is to define static variables (chars in this case) that will be constructed before the program starts (registering the tests to the runner). Instead of chars (that I know, it seems like a hack, it’s not a good design), we could use another object that handles the registration during its construction:

template <class T>
class TestAdder
{
public:
 TestAdder(const QString& name)
 {
   auto newTest = new T();
   newTest->setObjectName(name);
   TestRunner::Instance().RegisterTest(newTest);
 }
};

TestRunner defines a simpler function:

void RegisterTest(QObject* test)
{
   auto testName = test->objectName();

   if ( std::find_if(begin(m_tests), end(m_tests), [&testName](QSharedPointer<QObject>& elem)
        { return elem->objectName() == testName; }) == end(m_tests) )
       m_tests.push_back(QSharedPointer<QObject>(test));
}

And the macro turns into the cleaner:

#define DECLARE_TEST(className) static TestAdder<className> t_##className(#className);

By the way, here is how our widget test looks like:

--- WidgetTest.h" ---
#ifndef WIDGETTEST_H
#define WIDGETTEST_H

#include "TestRunner.h"
// Qt includes
#include <QObject>

class WidgetTest : public QObject
{
 Q_OBJECT
private slots:
 void My_first_test();
 void On_button_pressed_should_save_the_world();
};

DECLARE_TEST(WidgetTest)
#endif //WIDGETTEST_H

--- WidgetTest.cpp ---
#include "WidgetTest.h"

void WidgetTest::My_first_test()
{
  ...
}

void WidgetTest::On_button_pressed_should_save_the_world()
{
   ... important test 🙂 ...
}

And main.cpp is straightforward:

#include "TestRunner.h"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    return RUN_ALL_TESTS(argc, argv);
}

It’s simple, isn’t it? Now you can add tests easily. Disabling a test? Create an “empty” macro like DECLARE_TEST_DISABLED(className) that does nothing, or just comment the line DECLARE_TEST(className).

The second issue I’m dealing with is about test fixtures: what if you find yourself writing two or more tests that operate on similar data? For example, GTest allows you to reuse the same configuration of objects for several different tests. It is damned shrewd about this and it uses inheritance to make each test function have its own copy of the data. I heartily recommend you to dive into the internals!

Here I’d like to keep on exploiting QTest’s running mechanism (e.g. automatic execution of all the private slots of a test class), maybe adding some tricks to increase our productivity. So, we know QTest treats four slots in a special way:

  • initTestCase() will be called before the first testfunction is executed,
  • cleanupTestCase() will be called after the last testfunction was executed,
  • init() will be called before each testfunction is executed,
  • cleanup() will be called after every testfunction,

Quick recap, we have:

#ifndef WIDGETTEST_H
#define WIDGETTEST_H

#include "TestRunner.h"
// Qt includes
#include <QObject>

class WidgetTest : public QObject
{
 Q_OBJECT
private slots:
 void My_first_test();
 void On_button_pressed_should_save_the_world();
private:
 SomeData m_data;
};

DECLARE_TEST(WidgetTest)
#endif //WIDGETTEST_H

And we want m_data to be fresh and renewed before each test function gets executed. In a first attempt we could renew m_data in the init slot – that will be called before each testfunction is executed. Ok this sounds good, but what if SomeData is noncopyable/nonassignable (like QObject is)? A possible solution employs pointers – actually I use a smart pointer to avoid deleting the object by hand:

#ifndef WIDGETTEST_H
#define WIDGETTEST_H

#include "TestRunner.h"
// Qt includes
#include <QObject>
// std includes
#include <memory>

class WidgetTest : public QObject
{
 Q_OBJECT
private slots:
 void init();
 void My_first_test();
 void On_button_pressed_should_save_the_world();
private:
 std::unique_ptr<SomeData> m_data;
};

DECLARE_TEST(WidgetTest)
#endif //WIDGETTEST_H

--- WidgetTest.cpp ---

...

void WidgetTest::init()
{
   m_data.reset( new SomeData(aParameter) );
}

Thus, every time a test function is executed, it will have a “new” m_data. This way you can pretend that QTest has fixtures! Another valuable thing you should reckon in is about inheritance: suppose you have a couple of tests that only use common (not shared!) data (say a couple of widgets initialized in a certain way). You can extract this aspect in a class – such as “SpecialWidgetTestBase” – and make your tests inherit from it:

...

class SpecialWidgetTestBase : public QObject
{
   Q_OBJECT
private slots:
   void init(); // reset the unique_ptrs
protected:
   std::unique_ptr<QWidget> m_specialWidget;
   std::unique_ptr<QTextEdit> m_specialTextEdit;
};

...

class GUIPerformanceTest : public SpecialWidgetTestBase
{
   Q_OBJECT
private slots:
   void On_image_load_benchmark();
   void When_mouse_move_benchmark();
};
DECLARE_TEST(GUIPerformanceTest)

...

class GUIActionsTest : public SpecialWidgetTestBase
{
...
};
DECLARE_TEST(GUIActionsTest)

Both your tests will have base class’ protected data resetted before each test function runs! But if a subclass (say GUIActionTest) had redefined the init slot, the parent class’ one would not have been executed – init is not “recursive”. In this case:

  • make the init() function in the base class a public slot,
  • call it from the init() of the derived class,
  • make other stuff in the init() of the derived class (e.g. other resetting)

The last thing I’m going to handle is very trivial, but often can make your work faster: output. I want QTest to color its results. A nasty red line if a test fails, a gentle green one if a test passes. So, please, it’s your productive programmer speaking: make your output colored, I don’t care how, a stupid post-processing executable suffices:

MyProgram.Tests.exe | MakeMyEyesightHappy.exe

And you can peacefully configure your IDE (or editor) to execute a custom command. For example, under Windows, the stupid program can be easier (and terribly better) than this:

#include <windows.h>
#include <iostream>
#include <string>
#include <regex>

enum Color { blue=1, green, cyan, red, purple, yellow, grey, dgrey, hblue, hgreen, hcyan, hred, hpurple, hyellow, hwhite };

using namespace std;

void SetConsoleColor( Color color )
{
   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (WORD) color);
}
WORD GetConsoleColor ()
{
   auto consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
   CONSOLE_SCREEN_BUFFER_INFO con_info;
   GetConsoleScreenBufferInfo(consoleHandle, &con_info);
   return con_info.wAttributes;
}

class ColorGuard
{
public:
 ColorGuard() : m_color(GetConsoleColor())
 {}

 ~ColorGuard()
 {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), m_color);
 }

private:
 WORD m_color;
};

int main()
{
  string line;

  regex fail("(FAIL.*)");
  regex pass("(PASS.*)");

  while (getline(cin, line))
  {
    ColorGuard guard;

    if (regex_match(line, fail))
    {
      SetConsoleColor(hred);
    }

    if (regex_match(line, pass))
    {
      SetConsoleColor(hgreen);
    }

    cout << line << endl;
  }

  return 0;
}

And you’ll finally have a colored report! Don’t forget to take care of your output: you can also customize the TestRunner seen before making advanced stuff – for example filtering (QTest already provides some filtering, see here).

Then, you know how to improve your QTest process and productivity. Use a test runner, you’ll focus only on tests and you won’t be distracted from deploying them. If you need test fixtures, use pointers (better if smart!) and identify abstractions if some test classes have common data. At last (but not least), don’t ignore the output: the more it is evident, the more fast and productive you become!

Advertisements


Meshcripter (fancy portmanteau between the words Mesh and Scripter – Mesh Scripter) is an OpenGL and Qt tool for mesh management and real-time interaction, written in C++. It is equipped with a text console through which one performs almost all mesh operations, rendering customizations, and functions definition.

The powerful Qt-Script module provides a Javascript-like language, endowed with several objects that allow a console-based interplay. These objects (called scripters) set up a separate level of indirection (namely, a new layer), particularly convenient for modifiability and expandability issues. New scripters are simple to add and old scripters are change-prone.

The first release of Meshcripter was called Homology Tools because it was designed to grasp some of Homology and Algebraic Topology concepts, such as chain, incidence matrix, and boundary operator. Specifically, it was written to employ the Metrized Chains Method in a real context. The main idea is to embed all the properties (geometry, topology and physics – talking about simulations) of a complex (namely, a Cell Complex) in a single mathematical framework, making possible simultaneous changing of these properties (e.g. a mesh refinement influences automatically the physics of the scene). Homology Tools made use of this method to compute physics impact on the mesh (e.g. solution of a field problem) and to visualize it, by a color map (e.g. a heat field on a doughnut). One was able to import and export all the structures (e.g. matrices and vectors) used by this method, refine and manipulate the mesh, just explore the mesh or render few parts of it, etc.

These ideas have not entirely disappeared in Meshcripter. Some of the Metrized Chains Method routines and a few other things were removed. The new goal of Meshcripter is to focus on mesh interaction, manipulation and visualization. Anyhow, one can manually define functions for Metrized Chains Methods behavior, because the rendering mode by color maps is left enabled!

Hence, Meshcripter provides several topological and mathematical features. Users are able to explore the mesh and perform operations on it, supported by a solid rendering and a powerful language. Persistence is supported by CGAL.

This new adventure begins in Jan 2011. I’ve just created a new branch of hTools, now it is Meshcripter. The first step is “cleaning” unwanted features (they are very few), then I’ll need to improve the base code (a sort of refactoring). Next, I hope I’ll be ready for new operations implementation.

I’m going to employ this category to report interesting things, showing videos when it is possible. Stay tuned!