Tutorial¶
This section aims to show by the example how to setup first funq tests on a project.
Requirements¶
This tutorial is based on a sample QT application that you can find here: https://github.com/parkouss/funq/tree/master/server/player_tester.
This sample application must be compiled to an executable binary file, player_tester.
Important
Please keep in mind that funq-server currently does only works with QT4 - be careful to not compile player_tester with QT5 !
The two packages funq and funq-server must be installed. You can check that funq-server is installed by running:
funq -h
And that funq is installed with:
nosetests -h | grep 'with-funq'
Tests file tree¶
The file tree of a funq project is basically a folder that contains test files and a funq configuration file, funq.conf.
First, create a tutorial folder next to the player_tester binary file:
mkdir tutorial
cd tutorial
Now you have to write the configuration file funq.conf. Here is the most minimalistic configuration file:
[applitest]
executable = ../player_tester
Write your first test¶
You can now write your first test. Put the following content in a file called test_1.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
--------- Module's documentation ---------
This file is part of the funq tutorial. It currently defines
one test method.
"""
from funq.testcase import FunqTestCase
import time
class MyTestCase(FunqTestCase):
# identify the configuration
__app_config_name__ = 'applitest'
def test_my_first_test(self):
"""
--------- Test method documentation ---------
"""
# do nothing for 3 seconds
time.sleep(3)
This file contains one test, that do nothing except wait for 3 seconds.
Note
The “applitest” configuration is described in the funq configuration file by the section of the same name.
Note
Subclass funq.testcase.FunqTestCase ensure that each test method will start the application and close it properly.
Test execution¶
Well done ! Let’s run this first test. Type the following command:
nosetests --with-funq
One window must appear, and close after a few seconds. The output on the terminal must look like this:
.
----------------------------------------------------------------------
Ran 1 test in 3.315s
OK
Note
The option --with-funq given to nosetests allow to use the funq plugin that will read the configuration file and execute your tests.
Note
nosetests has multiples options to allow for example the generation of an xml file to format tests result. See nosetests -h.
And voilà! You have written and launched your first funq test. Now let’s go a bit further by adding two tests and use an aliases file.
Let’s first create the aliases file.
Aliases file¶
This file associate a name (an alias) to graphical objects identified by their path. This behavior allow to keep running the written tests even if the widgets moves in the tested application or if the code of the tested application is refactored.
applitest.aliases file:
# the main central widget
mainWidget = fenPrincipale::widgetCentral
# and some other widgets
btnTest = {mainWidget}::btnTest
dialog1 = fenPrincipale::QMessageBox
dialog1_label = {dialog1}::qt_msgbox_label
tableview = {mainWidget}::tableView
treeview = {mainWidget}::treeView
Note
This file support variables substitution by using brackets, allowing to avoid useless and dangerous copy/paste.
Note
Some aliases are predefined. See Predifined graphical kit aliases.
Now you need to modify the funq.conf configuration file to indicate the use of this aliases file. Add the following line in the applitest section:
aliases = applitest.aliases
Do something with the widgets¶
Let’s write another tests in a new file, test_widgets.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This file is part of the funq tutorial. It briefly shows widget
interaction.
"""
from funq.testcase import FunqTestCase
from funq.client import FunqError
class TestCase2(FunqTestCase):
# identify the configuration
__app_config_name__ = 'applitest'
def test_libelle_btn_test(self):
"""
Test the test button libelle
"""
# use the "btnTest" alias
btn_test = self.funq.widget('btnTest')
properties = btn_test.properties()
self.assertEquals(properties['text'], 'Test')
def test_open_dialog(self):
"""
Test that a dialog is open when user click on the test button.
"""
self.funq.widget('btnTest').click()
dlg_label = self.funq.widget('dialog1_label')
self.assertEquals(dlg_label.properties()['text'], "Button clicked")
def test_tableview_content(self):
"""
Test the data in tableview.
"""
view = self.funq.widget('tableview')
items = list(view.model_items().iter())
self.assertEquals(len(items), 16)
for item in items:
text = "row {r}, column {c}".format(r=item.row,
c=item.column)
self.assertEquals(item.value, text)
def test_some_treeview_content(self):
"""
test some data in the treeview
"""
model = self.funq.widget('treeview').model_items()
item = model.item_by_named_path([u"item 1", u"item 1-2"])
parent_item = model.item_by_named_path([u"item 1"])
self.assertEquals(item.value, u"item 1-2")
self.assertIn(item, parent_item.items)
You can see that the member variable self.funq is the entry point to manipulate the tested application. It is an instance of funq.client.FunqClient.
Now you can start tests again:
nosetests --with-funq
Note
This time, 5 tests are launched! It’s normal because you have written 5 tests divided up in 2 files.
To launch the tests of one file only, name it on the command line:
nosetests --with-funq test_widgets.py
Important
It is really important even for functional tests to not write tests that depends on others tests. In other words, the order of test execution must not be important. This allow to limit side effects and to find quickly why a test failed. This being said, nosetests does not assure any order in test execution.
Going further¶
This is the end of this tutorial. To go further, you must look at the API documentation!