Verifying Custom Properties of a QObject in Squish

If you’re testing a Qt-based application with Squish, you probably know the problem: one of your classes has custom properties you would really like to verify, but you cannot seem to get hold of it from a test script. First the bad news: making it available requires changing your application.

The good news: the required changes are really simple!

Consider this example class. It has a collection of members and properties which can be used just fine from C++ code:

class FrogView
{
    Q_OBJECT
public:
    enum FoodType {
        Fly,
        Grasshopper
    };

    FrogView(QWidget *parent = 0);

    QString name();
    void setName(QString name);

    QList<QString> preferredFood();

signals:
    void quack();

public slots:
    void feed(FoodType type);

private:
    QString m_name;
};

Note: You probably noticed at once that we should really use the FoodType enum as return type for preferredFood() instead of returning plain strings. That is true of course, but let’s keep it this way for the sake of the example. You’ll see why!

So far, just the signal “quack()” and the slot “feed(FoodType)” are picked up automatically by Squish. This works because they are already known to Qt’s type system, otherwise the signal/slot mechanic wouldn’t work.  After retrieving a FrogView instance in the test script, they can be used as usual:

frogView = waitForObject(":MainWindow.label_FrogView");
frogView.feed(0)

But wait! “feed()” has an enum parameter, but we’re just throwing an int at it. In C++, it would be possible to access the enum values via the class itself. Here in the test script, we don’t have it at hand, so there must be another way to access the enum values.

Introducing Custom Properties to the Qt Type System

The basic idea is to make our enum known to Qt’s type system – just like signals and slots. (Almost) everything that was registered with Qt can be introspected by Squish. Fortunately, there’s a macro for that. Let’s adapt the class definition a little:

public:
    enum FoodType {
        Fly,
        Grasshopper
    };
    Q_ENUM(FoodType)

Now the enum is known to Qt and can be used from Squish:

frogView.feed(frogView.Grasshopper)

As you can see, the enum values are accessible on each instance of the FrogView class. (Besides, using Q_ENUM also has the neat side effect that qDebug() can print the value name instead of the integer representation!)

Note: Q_ENUM has been introduced in Qt 5.5. If you are using an earlier release of Qt, you’ll need to use the Q_ENUMS macro instead.

Now that our frog is fed and happy, it is time to give it a name!

Doing the Same with Member Functions

The name() and setName() methods of our FrogView class are currently not accessible from Squish. One might suspect that there’s also a Qt macro for registering properties of a class to the type system… Right! Let’s expand the getter/setter methods like this:

    QString name();
    void setName(QString name);
    Q_PROPERTY(QString frogName READ name WRITE setName)

Now we can even use the property ‘frogName’ as the kind of property that is common in scripting languages instead of having to rely on the setter and getter functions:

frogView.frogName = "Slurpy";
test.log(frogView.frogName)

With these two macros, we can cover lots of custom functionality of Qt classes, however there’s still one function left in the original FrogView class that we cannot access from Squish yet.

One More Thing (About Food)

You might remember that our FrogView class also had an option to query the preferredFood() of the frog. Just like me, the frog doesn’t have just one preference but a whole list of dishes it likes, therefore preferredFood() also returns a list of dishes:

    QList<QString> preferredFood();

As long as we define the member like this, it unfortunately won’t be available from a test script. First, we’ll need to make it into a (read-only) property similar to the name()/setName() pair. Second, Squish can only work on data types that can be wrapped in a QVariant, so we’ll need to use QStringList as the return type instead of QList<QString>:

    QStringList preferredFood();
    Q_PROPERTY(QStringList preferredFood READ preferredFood)

With this definition the list of preferred frog food can easily be verified via Squish. (We need to be sure our supplies always match the frog’s preferences!)

for(var i = 0; i < frogView.preferredFood.size(); i++)
    test.log(frogView.preferredFood.at(i))

Now you can access and verify all your custom properties from your Squish tests!

0 Comments

Leave a reply

Your email address will not be published. Required fields are marked *

*