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.
To compile player_tester, just:
cd player_tester
qmake
make
This will create a player_tester executable file.
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'
Important
funq-server and the tested executable player_tester must be compiled with the same Qt version. You can check it with ldd for example.
If you just installed funq-server with pip (or did not specified any specific qmake path), then you are probably good.
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!