RSS

Category Archives: Uncategorized

Xpresser: Easy visual tests with Python

Automating tests is an essential goal of any QA Engineer. It saves precious human resources and allows to maintain a healthy continuous integration. Unit and integration tests are closest to the developer’s work: libraries, classes and functions. However, when a project is GUI-intensive or use software with poor introspection/accessibility capabilities, visual tests are very helpful. In this regard, we at Canonical are developing some good QA tools and one of them is Xpresser.

So, what is Xpresser? It’s a Python framework to do visual tests. It was originally developed by Gustavo Niemeyer. Xpresser’s main feature is to find saved images in the desktop. For example, if we want to check whether the Messaging Menu is active, we first save the blue icon and then command Xpresser to find it: Xpresser checks the whole visible desktop, as a regular person would do with its eyes. Xpresser is not only able to find images, but also to click on them. So in the previous case, will could open the Messaging Menu when active to then check whether Thunderbird is open. Xpresser even allows to simulate the keyboard.

To illustrate this, watch this useful screencast done by Chris Wayne, who works with us at Canonical as QA Engineer in OEM.

Plain easy, isn’t it?

Xpresser is currently available in this PPA ppa:xpresser-team/ppa for Ubuntu Precise and Oneiric.

 
4 Comments

Posted by on July 16, 2012 in Uncategorized

 

Continuous Integration with Jenkins and Launchpad

This post will describe how we are using Jenkins and Launchpad together to achieve Continuous integration.

Right now we are running our tests right after the code is (manually) reviewed and just before pushing them to trunk. We refer to this part of the process as autolanding and there are tools (tarmac) which can automate the process. However the manual process of code review can take quite some and our jenkins jobs are not triggered until the review is ready.

We would like to run tests much sooner, though. Ideally the workflow would be as follow:

  1. A new Merge Proposal in launchpad is created
  2. Jenkins job is triggered and starts the defined testing on defined configurations (e.g. tests on precise-i386, precise-amd64, quantal-i386, quantal-amd64, etc)
  3. Once all the tests finished the merge proposal is updated with the test result and a link to the jenkins job

In our case we are using libvirt and VMs to achieve a clean and isolated test environment. Therefore we are doing some post-test clean-up actions (reverting the VM to a predefined snapshot).

Our jenkins setup looks roughly like this.

In this case there are jenkins jobs:

  1. unity-ci – job which gets triggered as soon as a new merge proposal exists for lp:unity and does the testing
  2. generic_update-mp – parametrized job which will take test result, merge proposal and few other parameters and updates the merge proposal in launchpad with the result.

Flowchart for the whole process:

The setup for autolanding is very similar:

The only difference is that

  1. unity-autolanding job is triggered when a merge proposal is approved
  2. generic-land job will also merge the branch from merge proposal to trunk and does the actual push to trunk

The flowchart is slightly more complicated as there are more possible failure points (e.g. the testing might pass but the autolanding will fail because we require non-empty commit message and the commit message was not specified):

Right now we have a prototype in Python using a ScriptTrigger plugin for jenkins which is implementing all of this. I will describe in the next post how use it in practice together with some examples.

 
Leave a comment

Posted by on June 14, 2012 in Uncategorized

 

Testing Unity3D with Autopilot

Previously, Gerry Boland wrote eloquently about the testing solution in place for the Unity2D project. When writing something as complicated as a desktop shell, there is a need for functional testing as well as low-level unit testing. For the 2D team, this role is filled by testability.

In the 3D team, we have autopilot: Autopilot aims to make writing functional tests for Unity as easy as possible. Previously, features that were too hard to test with unit tests were written as a “manual test”. Manual tests are text documents stored in the Unity source tree. When we prepare a point release of Unity we iterate through all the manual tests and ensure they all pass. This is obviously less than ideal – running the entire suite of manual tests takes a lot of time, and stops a developer from writing more code. Most of these tests can be automated.
Here’s an example that was written after someone noticed a bug in the dash command lens:

Dash search
-----------
This test makes sure that the right command is run when you search
using the dash. (see lp:856205)

#. Press Alt+F2
#. Press 'g'. Make sure you see some command name (like gcc)
#. Quickly type 'edit<Enter>' - so you'd run 'gedit'.

Outcome
  The dash disappears, and gedit is run. If nothing happens or the first
  command is run (in this case gcc), this test failed.

This is a reasonable test specification, but does not need to be a manual test, we can automate this, and have autopilot perform the same actions as a user would. If we break down the test specification into smaller steps, we end up with the following:

  1. Reveal the command lens.
  2. Type “g”, and wait for the command lens to refresh and show us some results.
  3. Quickly type “edit” and hit “Enter”.
  4. Wait (with a timeout) for the gedit application to launch.
  5. If gedit was launched, the test passed. If the timeout was reached, the test failed.

Autopilot tests are standard python unit tests, so the resulting test will look familiar to people used to reading python unit tests:

def test_run_before_refresh(self):
    """
    Hitting enter before view has updated results must
    run the correct command.

    """
    kb = Keyboard()
    self.dash.reveal_command_lens()
    kb.type("g")
    sleep(1)
    kb.type("edit", 0.1)
    kb.press_and_release("Enter", 0.1)
    self.addCleanup(call, "killall gedit".split())
    app_found = self.wait_until_application_is_running("Text Editor", 5)
    self.assertTrue(app_found)

This test is part of a larger class that contains several similar tests – I have omitted the rest of the class for clarity. There’s a few things happening here:

  • On lines 9, 11, and 12 we’re generating X11 keyboard events (we can handle mouse events as well). This allows us to manipulate the various parts of the desktop shell just like a user would.
  • On lines 8 and 14 we’re querying various parts of the unity shell for information. When we reveal the command lens we check that it’s actually showing by asking Unity internal state information. When we check for running applications we’re talking with the Bamf daemon.

We generate the X events using python-xlib and the xtest extension. Of course, we don’t want programmers to have to deal with Xlib themselves, so we wrap all Xlib calls into two classes: “Keyboard” and “Mouse”. They work exactly as you’d expect.

Getting information is a bit more interesting: many classes within unity contain information we would like in autopilot. In order to expose this information, a class must:

  1. Derive from the Introspectable class (defined in “Introspectable.h”)
  2. Implement the “GetName” and “AddProperties” methods.

Browsing the unity C++ source files will reveal many instances of introspectable objects. Introspectable objects form a tree within unity, with the main shell instance at the top. To build the tree, an introspectable instance can call the “AddChild” and “RemoveChild” methods. In this manner, a tree of objects is built. The full tree is huge, but you can see a small part of it below:

Even from this small part of the tree you can tell a lot about the state of my desktop shell: I have only one launcher (on monitor 0). Launcher keyboard navigation (as initiated by pressing Alt+F1 or Super+Tab) is not active, I have at least three launcher icons (actually many more, but they’re cut out of the image), including D-feet, gnome-terminal and the Quassel IRC client.

All this information (and more) is available to autopilot tests. The combination of a vast amount of information, and the fact that Python is incredibly fast to work in makes it trivially easy to write autopilot tests. This is one of the key ways in which we’re testing unity for the precise release cycle.

Running the Tests

Running the tests is simple. From the root of the unity source tree, you can list all the autopilot tests like this:

$ ./tools/autopilot list

You can run the entire autopilot suite like this:

$ ./tools/autopilot run

…or you can specify one or more tests you want to run (the entire suite takes a long time) like this:

$ ./tools/autopilot run autopilot.tests.test_command_lens.CommandLensSearchTests.test_run_before_refresh

Currently we have around 100 tests, and many of these are parameterized to expand in certain conditions. For example, if the test machine has multiple monitors configured, almost all the launcher tests are configured to run once on each monitor. We use a similar technique to ensure that we support multiple international languages in the dash.

On Jenkins

The entire autopilot test suite runs on jenkins as well. We’ve recently started recording failing autopilot tests, which helps us diagnose failing tests. This is especially important, as the test machine may have different hardware or software configuration from a developer’s machine: being able to see the test failing makes diagnosing errors a lot easier.

You can help!

We’re always happy to have people writing autopilot tests. If you know a bit of Python, and are willing to learn about testing Unity, please find me (“thomi”) in the #ubuntu-unity channel on irc.freenode.net – I’m happy to guide anyone who would like to get involved through writing, testing, and submitting your first autopilot test.

 
Leave a comment

Posted by on March 9, 2012 in Uncategorized

 

Automated Testing of Qt apps with Testability Driver

Testing is hugely important to us at Canonical. We all strive to have Ubuntu reliable, consistent and fast. But we’re human, and we make mistakes. Sometimes a bugfix will break something else, and for something as complex as a desktop shell, it’s easy to miss these breakages. While manual tests can help reduce these regressions, realistically we need an automated system to emulate the users inputs and verify our software works as it should – and scream bloody murder if it doesn’t!

In Unity 2D (my project!), we have just introduced an automated User Experience testing system, based on a test framework called Testability Driver (I’ll just call it ‘Testability’ from now on). First off, a clarification:

Testability is for Qt-based applications only!

A limitation: yes, but this requirement comes with a great reward: Testability allows inspection of the tree of QObjects in a Qt application while it is running!

It can read and write object properties, call methods and slots, verify signals are emitted, as well as fake mouse/keyboard/gesture inputs, grab visual outputs, and measure performance.

And best of all, Testability is open source and maintained by Nokia! That means everyone can run and contribute tests! 🙂

To show it off, here is a screengrab of the Testability Visualizer application which allows you to connect to a running application, dig into the QObject tree and investigate what’s going on (here, the Unity 2D Launcher – it will be good to zoom in):

Image

On the left is an interactive snapshot of the UI, in the centre is the QObject tree which you can navigate, and on the right is the list of the selected QObject’s properties, methods and signals you can interact with.

On display in that screengrab are some of the attributes of the QDeclarativeImage object which draws the Terminal icon in the launcher (this is defined in QML!) – you can read off the source of the image, the x,y coordinates, width & height, and a whole lot more.

All these properties, methods, signals, etc, are scriptable via Ruby. Thus we can emulate every interaction that a user can make with the application, and determine the reaction matches our expectation.

And all this power comes with almost no changes* to the source code! (* = just need to add object names, see later)

This forms the foundation for the Unity 2D User Experience testing suite.

How Testability Works

First some definitions:
“target” = the machine with the software being tested
“host” = the machine running the test suite, and controlling the target

Testability works as follows

  • any Qt application using Qt4.6+ can be tested by executing it with the “-testability” switch.
  • a standalone server “qttasserver” runs in the background.
  • With the -testability switch, the Qt library tries to load a “libtestability.so” plugin which establishes a connection between the application and qttasserver, giving qttasserver access to the root node of the QObject tree.
  • qttasserver then climbs the QObject tree, reads all the info it can and converts it to an XML format. It also can receive commands and cause the application to react upon them (click here, type, etc..).
  • A series of Ruby scripts connect to qttasserver, receive and parse this XML and allow us to script tests and interactions with the application.

Image

Note that there is a clear divide between the machine of the target and of the host.

This means Testability is great for testing software on embedded devices too. (Indeed Meego has been using it for that exact task!). It also reduces the risk that packages used to run the test suite could interfere with the software being tested.

However there’s nothing stopping you having the target and host the same machine.

[The Unity 2D test framework also includes an extra helper library to control the X server, to control the mouse and keyboard, and to manipulate windows on the desktop. As far as X is concerned, a human is controlling it.]

With the ability to fake any form of user input, and directly read the output from the shell applications
themselves, we can test almost every behaviour of the desktop shell. And as a result, the quality of the user’s experience will only go up.

How to get Testability and start writing tests

Unfortunately Testability is not available in Ubuntu’s repositories just yet, but I have it packaged in a PPA. Installation takes a few steps, so I suggest that interested people consult this wiki page.

Tests are just Ruby scripts, so running tests is just a matter of running a Ruby script!

I think it easiest to show how to use Testability with an example:

# Example test for Unity 2D with Testability Driver.
#
# Note: this probably won't succeed on your installation. Only works
# on unity-2d trunk *right now*, something that will change soon.# This is only a taster!require 'tdriver'
include TDriverVerify

# Establish connection to 'qttasserver' on target
@sut = TDriver.connect_sut(:Id => 'sut_qt')

# Execute the application to test, supplying '-testability' flag
@app = @sut.run( :name => 'unity-2d-launcher',
                 :arguments => '-testability' )
# ------------- Start of Testing Code ----------------

# Check Launcher is 65 pixels wide
verify_true(1, 'Launcher is not 65 pixels wide') {
  @app.LauncherView()['width'] == '65'
}

# Check that Terminal tile is using correct icon source
verify_true(1, 'Terminal icon in Launcher is wrong') {
  @app.LauncherList( :name => 'main' ) \
      .QDeclarativeItem( :name => 'Terminal' ) \
      .QDeclarativeImage( :name => 'icon' )['source']     == 'image://icons/utilities-terminal'
}
# this is a bad test, as the name "Terminal" can be # localised, meaning a fail if you're using a non-English # installation. Choosing good objectNames is important!

# ------------------- Clean up -----------------------
# This closes (kills actually) the launcher when we're done.
@app.kill

There is some boiler-plate code there, but the bits I want to point out are:

@app.LauncherView()['width']

This causes Testability to search for an object of type “LauncherView()” in the QObject tree, and if found reads its “width” property and returns it. Then in Ruby, we can check this value matches what we expect (65).

The second test does a similar operation, but needs a little more help. As there are many tiles, we need to help Testability to find the exact tile we want. We do this by adding some object names (“main”, “Terminal”) to the C++/QML.

By consulting with the Visualizer image above, maybe you can see how Testability navigates the tree to find the icon source for the Terminal tile!

Once you can track down objects uniquely, you can then start interacting with them, send mouse clicks, set properties, call methods, etc. This power gives you great flexibility in testing your application!

Demo

As a demo, here is a video of a part of the Unity 2D test suite in action. On the right is Ubuntu Oneiric running inside VirtualBox, where the Launcher will be tested. On the left is my host machine terminal running the test suite.

Various hide/show tests are being performed, with windows in the way, mouse being controlled, keyboard shortcuts being pressed etc.

Our policy is that every new feature and bug fix in Unity 2D will now be tested like this. You can see our growing test suite here. This will ensure Unity 2D remains reliable, consistent and fast. Thanks to Testability!

Tests will improve your project’s quality too. Will you give it a try?

– Gerry Boland

 
5 Comments

Posted by on February 1, 2012 in Uncategorized

 

Tags: , , ,