QML

QML Testing

Unit tests

  • Written in QML
  • Frameworked used is QtQuickTest

  • Tests are written from the developer point of view
  • Examples are found from UI Toolkit project and template from Qt Creator application wizard.

  • Running tests
    • locally: execute qmltestrunner in the same directory where your tests lives
    • CI: implement make check target, example.

What should be covered?

  • Give priority to public APIs. Check all functions and if the function should change some internal state, check that state before and after.
  • Initial values for properties

How to install

sudo apt-get install qtdeclarative5-dev-tools qtdeclarative5-test-plugin

Getting started with unit testing

A simple Ubuntu UI application

This is the component/application under test.

Directory structure

   1 $ find .
   2 ./myapp.qml
   3 ./MyComponent.qml
   4 

The application source code (myapp.qml)

   1 import QtQuick 2.0
   2 
   3 Rectangle {
   4   width: 600
   5   height: 480
   6   MyComponent {
   7       anchors.centerIn: parent
   8   }
   9 }
  10 

The component source code (MyComponent.qml)

   1 import QtQuick 2.0
   2 
   3 Rectangle {
   4  width: 360
   5  height: 360
   6  property bool myFlag : false
   7 
   8  Text {
   9      id: myLabelId
  10      objectName: "myLabel"
  11      anchors.centerIn: parent
  12      text: "My Label"
  13  }
  14 
  15  onMyFlagChanged: myLabelId.text = myFlag ? "Hello" : "World"
  16 }
  17 

Writing a unit test for MyComponent.qml

In this we write a simple unit test and execute it.

Directory structure

We should place the unit tests under tests/unit.

   1 $ mkdir -p tests/unit
   2 $ find .
   3 ./Makefile
   4 ./MyComponent.qml
   5 ./myapp.qml
   6 ./tests
   7 ./tests/unit
   8 ./tests/unit/tst_myapp.qml
   9 

Creating the unit test (tst_myapp.qml)

Unit test name should begin with tst_ so that tests are identified properly by the QtQuick Test Framework.

   1 import QtQuick 2.0
   2 import QtTest 1.0
   3 /******* NOTE: the Ubuntu.Test module is not yet available at the time of writing ******/
   4 import Ubuntu.Test 0.1
   5 import "../.." as App
   6 
   7 Item {
   8   id: root
   9   width: 200
  10   height: 200
  11 
  12   App.MyComponent {
  13       id: objectUnderTest
  14       anchors.margins: 20
  15       anchors.fill: parent
  16   }
  17 
  18   TestCase {
  19       name: "MyAppUnitTest"
  20       when: windowShown
  21 
  22       property variant myCompLabel;
  23 
  24       function initTestCase() {
  25           myCompLabel = Tools.findChild(objectUnderTest,"myLabel");
  26 
  27           compare(myCompLabel!==undefined,true,"There should be myLabel");
  28           compare(objectUnderTest.myFlag,false,"Initial value for myFlag should be false.");
  29           compare(myCompLabel.text,"My Label","myLabel.text initial value is 'My Label'");
  30       }
  31 
  32       function test_toggleMyFlag_data() {
  33           return [
  34                       { myFlag: true, text: "Hello", tag: "When myFlag is true, then text is 'Hello'"},
  35                       { myFlag: false, text: "World", tag: "When myFlag is false, then text is 'World'"}
  36 
  37                   ];
  38 
  39       }
  40 
  41       function test_toggleMyFlag(data) {
  42           objectUnderTest.myFlag = data.myFlag;
  43           tryCompare(objectUnderTest.myFlag,data.myFlag);
  44           compare(myCompLabel.text,data.text);
  45       }
  46   }
  47 }
  48 

This test demonstrates the data driven testing, in which you define a table of values which you are going to use inside a test function.

Add ‘make check’ target (Makefile)

   1 $ cat Makefile
   2 check:
   3 
   4  . cd tests/unit qmltestrunner
   5 

Adding a bazaar hook for pre_commit

TBD

Touch/Testing/QML (last edited 2014-03-20 21:02:57 by andrewsomething)