Skip to main content

Kivy automation, can be used to do GUI tests.

Project description

Telenium

Telenium provide a framework to remote tests or control Kivy-based application:

  • Selector support using XPATH-like syntax (//BoxLayout[0]/Button[@text~="Close"])

  • Create selector by touching the UI

  • Query or set attribute on any widgets

  • Execute remote code

  • unittests support

  • Integrate as a Kivy modules

  • Web IDE

  • Python 2 (python-jsonrpc not compatible with Python 3 yet, working on it.)

Telenium IDE

Telenium IDE

Telenium IDE export

Telenium IDE export

Installation

pip install telenium

Run the Telenium IDE

It will start a webserver on http://127.0.0.1:8080/ and automatically open a new tab in your favorite webbrowser. You’ll be able to configure where your main.py is, and start writing tests directly:

telenium

You can also edit telenium-json:

telenium tests/test-ui-myfeature.json

Run the application with telenium module

If you don’t use the IDE, in order to remote control your application, you need the Telenium client installed within your application.

Method 1: Run your application with telenium client

Telenium can execute your application and manually add telenium_client to it. Just do:

python -m telenium.execute main.py

Method 2: Add telenium_client as a Kivy modules into your application

Just copy/paste mods/telenium_client.py in your application, then before running your application, initialize it:

from os.path import dirname
from kivy.modules import Modules
from kivy.config import Config
Modules.add_path(dirname(__file__))
Config.set("modules", "telenium_client", "")

You also need to add python-jsonrpc in your dependencies (pip install python-jsonrpc)

Connect to a telenium-ready application

We have a command line client to play with. After the application is started, you can connect with:

::

$ python -m telenium.client

Then play with it. cli is the telenium client where you can invoke remote commands. See the Telenium commands to see what you can do:

>>> id = cli.pick() # then click somewhere on the UI
>>> cli.click_at(id)
True
>>> cli.setattr("//Label", "color", (0, 1, 0, 1))
True

If a command returns True, it means it has been successful, otherwise it returns None.

Create unit tests

Telenium have a module you can use that ease unit tests: it launch the app and execute tests. For now, it has been tested and coded to work only locally using subprocess.

Additionnal methods: - assertExists(selector, timeout=-1) and assertNotExists(selector, timeout=-1) to check if a selector exists or not in the app. They both have a timeout parameter that, if it reach, will fail the test. - cli.wait_click(selector, timeout=-1): easy way to wait a selector to match, then click on the first widget.

Here is a real example that launch an app (default is “main.py”):

  • It first go in the menu to click where it need to save a CSV (SaveButton, CascadeSaveButton then SaveCSVButton)

  • Then wait at maximum 2s the popup to show with a label “Export to CSV”

  • Then click on the “Close” button in the popup

  • Then ensure the popup is closed by checking the label is gone.

Example:

from telenium.tests import TeleniumTestCase

class UITestCase(TeleniumTestCase):
    def test_export_csv(self):
        self.cli.wait_click("//SaveButton")
        self.cli.wait_click("//CascadeSaveButton")
        self.cli.wait_click("//SaveCSVButton")
        self.assertExists("//Label[@text~=\"Export to CSV\"]", timeout=2)
        self.cli.wait_click("//FitButton[@text=\"Close\"]", timeout=2)
        self.assertNotExists("//Label[@text~=\"Export to CSV\"]", timeout=2)

Each new TeleniumTestCase will close and start the application, so you always run from a clean app. If you always need to do something before starting the test, you can overload the setUpClass. This will be executed once before any tests in the class starts:

class UITestCase(TeleniumTestCase):
    @classmethod
    def setUpClass(cls):
        super(UITestCase, cls).setUpClass()
        cls.cli.wait_click("//PresetSelectionItem[@text!~=\"ttyUSB0 on mintel\"]",
                           timeout=10)
        cls.cli.wait_click("//Button[@text=\"Connect\"]")
        cls.cli.wait("//BottomLabel[@text=\"Done\"]", timeout=10)

You can also change few parameters to change/add things in your application for unit testing if needed:

class UITestCase(TeleniumTestCase):
    process_start_timeout = 5
    cmd_env = {"I_AM_RUNNING_TEST": 1}

Telenium commands

select(selector)

Return unique selectors for all widgets that matches the selector.

>>> cli.select("//Label")
[u"/WindowSDL/GridLayout/Label[0]", u"/WindowSDL/GridLayout/Label[1]"]

getattr(selector, key)

Return the value of an attribute on the first widget found by the selector.

>>> cli.getattr("//Label")
u"Hello world"

setattr(selector, key, value)

Set an attribute named by key to value for all widgets that matches the selector.

>>> cli.setattr("//Label", "text", "Plop")
True

element(selector)

Return True if at least one widget match the selector.

>>> cli.element("//Label")
True
>>> cli.element("//InvalidButton")
False

execute(code)

Execute python code in the application. Only the “app” symbol that point to the current running application is available. Return True if the code executed, or False if the code failed. Exception will be print withing the application logs.

>>> cli.execute("app.call_one_app_method")
True

pick(all=False)

Return either the first widget selector you touch on the screen (all=False, the default), either it return the list of all the wigdets that are traversed where you touch the screen.

>>> cli.pick()
u'/WindowSDL/Button[0]'
>>> cli.pick(all=True)
[u'/WindowSDL/Button[0]',u'/WindowSDL']

click_on(selector)

Simulate a touch down/up on the first widget that match the selector. Return True if it worked.

>>> cli.click_on("//Button[0]")
True

Telenium selector syntax (XPATH)

Cheat sheet about telenium XPATH-based selector implementation.

  • Select any widget that match the widget class in the hierarchy: //CLASS

  • Select a widget that match the tree: /CLASS

  • Select a widget with attributes /CLASS[<ATTR SELECTOR>,...]

  • Index selector if there is multiple match: /CLASS[INDEX]

  • Attribute exists: @attr

  • Attribute equal to a value: @attr=VALUE

  • Attribute not equal to a value: @attr!=VALUE

  • Attribute contain a value: @attr~=VALUE

  • Attribute does not contain a value: @attr!~=VALUE

  • Value can be a string, but must be escaped within double quote only.

Some examples:

# Select all the boxlayout in the app
//BoxLayout

# Take the first boxlayout
//BoxLayout[0]

# Get the Button as a direct descendant of the BoxLayout
//BoxLayout[0]/Button

# Or get the 5th Button that are anywhere under the BoxLayout (may or may
# not a direct descandant)
//BoxLayout[0]//Button

# Select the button that is written "Close"
//BoxLayout[0]//Button[@text="Close"]

# Select the button that contain "Close"
//BoxLayout[0]//Button[@text~="Close"]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

telenium-0.2.8.tar.gz (325.5 kB view details)

Uploaded Source

Built Distribution

telenium-0.2.8-py2-none-any.whl (331.8 kB view details)

Uploaded Python 2

File details

Details for the file telenium-0.2.8.tar.gz.

File metadata

  • Download URL: telenium-0.2.8.tar.gz
  • Upload date:
  • Size: 325.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for telenium-0.2.8.tar.gz
Algorithm Hash digest
SHA256 44c59fffa274edbdda5d92586811b74df69f8fcdf09ee2fa2fdee3b1e7934bbe
MD5 ef1026e54c4ffc98da570a9e3d367b6e
BLAKE2b-256 0ed3ac8e615209090d993808e769e3b424ad6c7093d3a9a0553ca0117c743c76

See more details on using hashes here.

File details

Details for the file telenium-0.2.8-py2-none-any.whl.

File metadata

File hashes

Hashes for telenium-0.2.8-py2-none-any.whl
Algorithm Hash digest
SHA256 712ce204c363b3611bee0748a0b6a5e56d0794e2f1c6576b701207868bedb59c
MD5 6d73b5ce2b8f22e820149b40d00bc83c
BLAKE2b-256 0fdd88f66ed1bf3e1707fd8c7b006ec8cc2326309f9283352ad660d0c8b9aa80

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page