Organization of automated GUI testing

    During development, we try to cover our code not only with obscenities, but also with unit tests. However, covering everything with tests does not always work. In addition, there remains a GUI for which writing tests is a rather laborious job. For all these problems, the requirement remains unchanged that each subsequent Kamit to the repository should not spoil the existing functionality.

    In this article I want to tell what tools we use to test our desktop applications written in Qt.

    Half a year ago, while researching GUI testing tools, froglogic 's Squish came into my view . Of the advantages of this solution, the following can be noted:

    • Squish's close friendship with Qt classes (including items in QGraphiscScene);
    • cross-platform;
    • support for scripting languages ​​(JavaScript, Python);
    • automated test text generation;
    • convenient system for running tests from the console.


    On the other side of the scale lay the cost of the license 93,000 rubles. (this is at the August exchange rate of 2650 euros).

    Since none of the competitors offered such goodies for the money, and I did not find similar free solutions, reluctantly I bought a license.

    So, with the background finished, let's move on to creating tests. For demonstration, I chose one of our public projects - MDC . The task is simple, check whether MDC can connect to ICQ, Gtalk, mail.ru. The topic is especially relevant in the light of the latest surprises of AOL :). The appearance of the contact sheet window will be considered a sign of connection.

    1. We collect Squish from sources with the same Qt version with which MDC will be compiled.
    2. We collect MDC debug mode (c release Squish cannot work).
    3. Launch Squish.
    4. Create a Test Suit for MDC.
    5. Choose the language in which we will write the tests.
    6. We configure application launch parameters (command line parameters, environment variables, etc.).
    7. We create a new test case in record mode (Squish starts MDC and remembers in a script all the actions that you will do with the application).
    8. We check his work.




    Thus, we got the text of the test, which we will use as a basis.

    1. def main():
    2.   waitForObject(":_QWidget")
    3.   sendEvent("QResizeEvent", ":_QWidget", 22, 22, 769, 474)
    4.   waitForObject(":_QGraphicsItem")
    5.   mouseClick(":_QGraphicsItem", 221, 193, 1, Qt.LeftButton)
    6.   waitForObject(":_QLineEdit")
    7.   dragItemBy(":_QLineEdit", 153, -191, 26, 198, 1, Qt.LeftButton)
    8.   waitForObject(":_QLineEdit")
    9.   sendEvent("QMouseEvent", ":_QLineEdit", QEvent.MouseButtonRelease, 179, 7, Qt.LeftButton, 1)
    10.   waitForObject(":MDC: Авторизация_QGraphicsView")
    11.   type(":MDC: Авторизация_QGraphicsView", "")
    12.   waitForObject(":MDC: Авторизация_QGraphicsView")
    13.   type(":MDC: Авторизация_QGraphicsView", "squish@mail.ru")
    14.   waitForObject(":MDC: Авторизация_QGraphicsView")
    15.   type(":MDC: Авторизация_QGraphicsView", "")
    16.   waitForObject(":MDC: Авторизация_QGraphicsView")
    17.   type(":MDC: Авторизация_QGraphicsView", "1234")
    18.   waitForObject(":MDC: Авторизация_CStartUpWidget")
    19.   sendEvent("QMoveEvent", ":MDC: Авторизация_CStartUpWidget", 577, 70, 734, 62)
    20.   mouseClick(":MDC: Авторизация_QWidget", 66, 372, 1, Qt.LeftButton)
    21.   waitForObject(":MDC v1.0.3.1.nightly_CContactListWidget")
    * This source code was highlighted with Source Code Highlighter.


    Using this text without changes is certainly possible and for a wide range of tasks this is quite enough, which makes it possible to work with Squish not only to developers, but also to less qualified employees, but this code is not suitable for our task.

    Squish supports 2 types of object naming: symbolic name and real Name. When automatically creating test text, Squish uses a symbolic name, which is not always convenient. So, for example, the contact sheet window is automatically defined as

    symbolic name: MDC v1.0.3.1.nightly_CContactListWidget

    where MDC v1.0.3.1.nightly is the title of the window, and CContactListWidget is the type of this widget. There is a version in the window title that will quite obviously change and the object set in this way will never be found. In this case, use real name: {name = 'contactList' type = 'CContactListWidget' visible = '1'}. Where name is set as a constant in MDC code via setObjectName

    1.    m_widget = new CContactListWidget(this_ptr);
    2.    m_widget->setObjectName("contactList");
    * This source code was highlighted with Source Code Highlighter.


    Thus, regardless of the window title, we can always find the widget we need and the final code of our test will look like this:

    1. def main():
    2.   waitForObject(":_QWidget")
    3.   sendEvent("QResizeEvent", ":_QWidget", 22, 22, 629, 418)
    4.   waitForObject(":_QLineEdit")
    5.   dragItemBy(":_QLineEdit", 140, -183, 26, 198, 1, Qt.LeftButton)
    6.   waitForObject(":_QLineEdit")
    7.   sendEvent("QMouseEvent", ":_QLineEdit", QEvent.MouseButtonRelease, 166, 15, Qt.LeftButton, 1)
    8.   waitForObject(":MDC: Авторизация_QGraphicsView")
    9.   type(":MDC: Авторизация_QGraphicsView", "")
    10.   waitForObject(":MDC: Авторизация_QGraphicsView")
    11.   type(":MDC: Авторизация_QGraphicsView", "squish@mail.ru")
    12.   waitForObject(":MDC: Авторизация_QGraphicsView")
    13.   type(":MDC: Авторизация_QGraphicsView", "")
    14.   waitForObject(":MDC: Авторизация_QGraphicsView")
    15.   type(":MDC: Авторизация_QGraphicsView", "1234")
    16.   mouseClick(":MDC: Авторизация_QWidget", 154, 369, 1, Qt.LeftButton)
    17.   waitForObject(":{name='contactList' type='CContactListWidget' visible='1'}")
    * This source code was highlighted with Source Code Highlighter.


    It is easy to make a test script for connecting to jabber and icq from it, replacing the login, password and click coordinates. The video below shows the launch of a test suit, consisting of three test cases (icq, mail.ru, jabber)



    After that, this test suit can be made to run after unit tests have been completed with each successive cam so that you always have such a beautiful picture on hand: But this is another story, which, if it is interesting, I will write with pleasure. In this article, I only briefly touched on the functionality of Squish deliberately without touching on issues such as synchronization primitives, working with Qt objects through the API. I plan to write about these things in the following posts.







    Also popular now: