Skip to content
ohinckel edited this page Jan 29, 2018 · 10 revisions

Tests

Um sicherzustellen, dass Funktionen innerhalb von SmartHomeNG während der Weiterentwicklung und evtl. Umstrukturierungen weiterhin funnktionieren, werden sogenannte Unittests geschrieben. Diese sind, ebenfalls wie alles andere in SmartHomeNG, in Python programmiert.

Bei der Weiterentwicklung von SmartHomeNG sollten die Tests nach jeder Änderung ausgeführt. Dadurch kann sichergestellt werden, dass bestehende Funktionalität weiterhin fehlerfrei funktioniert und eventuelle Fehler frühzeitig erkannt werden.

Ausführung

Die Ausführung der Tests basiert auf zwei Technologien:

  • pytest - Framework für die Testausführung
  • tox - Utility für unterschiedliche Testsläufe

pytest

Die Tests werden mittels pytest (siehe Doku) ausgeführt. Dies ist ein Framework mit dem Tests strukturiert abgelegt und in unterschiedliche Dateien verteilt werden koennen. Das Framework bietet weiterhin Funktionen an mit denen diverse Testszenarien geprüft werden können (Assertions).

tox

Das Utility tox wird verwendet um pytest auszuführen. Es unterstützt allerdings auch noch weitere Features: so kann z.B. ein sogenannter Build erzeugt werden in dem unterschiedliche "Environments" konfiguriert werden die unterschiedliche Aufgaben erledigen können. Ausserdem kann eingestellt werden, wie die Test-Discovery durchgeführt werden soll und für welche Python Versionen Tests ausgeführt werden sollen.

Damit ist es möglich die Ausführung so zu gestalten, dass einerseits eine Umgebung für die direkte Ausführung der Tests vorhanden ist, andererseits auch eine Umgebung für einen Syntax-Check (flake) oder sogar eine Umgebung um einen Dokumentationsbuild zu starten.

Bei SmartHomeNG wird allerdings nur die Ausführung der Tests sowie (bei bedarf, und daher auskommentiert in der Konfiguration) des Syntax-Checks (flake).

Ausführung in der Konsole

Möchte man die Tests nach einer Weiterentwicklung ausführen, so muss der Befehl tox ausgeführt werden. Damit wird das Utility tox gestartet, welches standardmäßig pytest ausführt.

Ein Testlauf sieht so aus:

$ tox
[...]
============================= test session starts ==============================
platform linux -- Python 3.3.6, pytest-2.9.2, py-1.5.2, pluggy-0.3.1 -- /home/travis/build/smarthomeNG/smarthome/.tox/py33/bin/python3.3
cachedir: .cache
rootdir: /home/travis/build/smarthomeNG/smarthome, inifile: tox.ini
plugins: cov-2.5.1, timeout-1.2.1, betamax-0.5.1
timeout: 30.0s method: signal
collected 219 items 
tests/test_config.py::TestConfigConf::test_confread_ignores_empty_name PASSED
tests/test_config.py::TestConfigConf::test_confread_lists_spaces PASSED
tests/test_config.py::TestConfigConf::test_confread_multiline PASSED
[...]
plugins/database/tests/test_single.py::TestDatabaseSingle::test_single_returns_last_value_outside_range PASSED
plugins/database/tests/test_single.py::TestDatabaseSingle::test_single_sum PASSED
==================== 218 passed, 1 skipped in 21.50 seconds ====================
___________________________________ summary ____________________________________
  py33: commands succeeded
  congratulations :)

Diese Ausführung verwenden den aktuell ausgecheckten Quellcode und Branch. D.h. befindet man sich aktuell in develop Branch, so werden die Tests darin ausgeführt.

Die Konfiguration wird in der Datei tox.ini:

  • Sektion pytest legt allgemeine Einstellungen fuer pytest fest: Pfade oder Namenschema für Test-Dateien, Test-Funktionen und Test-Klassen
  • Sektion testenv legt eine auszuführende Testumgebung fest: Umgebungsvariablen, pytest-Kommando, notwendige Dependencies

Aufteilung der Tests

SmartHomeNG besteht aus zwei Bereichen: Code und Plugins. Für beide Bereiche gibt es bzw. kann es Tests geben, die getrennt voneinander abgelegt werden.

Tests für Core

Die Tests für den SmartHomeNG Core liegen direkt im Hauptverzeichnis im Verzeichnis tests. Das Verzeichnis hat folgende Struktur:

  • mock - Verzeichnis in dem Teile des Core als Mocks (keine reale Implementierung von Klassen, sondern nur leere Hülsen)
  • resources - Verzeichnis in denen Dateien abgelegt werden die für die Ausfürhung von Tests notwendig sind (z.B. eigene items.yaml).
  • test_XXXX.py - Dateien in denen Tests für XXX implementiert sind (z.B. test_config.py)

Wenn Teile des Cores getestet werden sollen, empfiehlt es sich diese in einer entsprechenden Datei abzulegen. So sind Tests fuer das einlesen der Konfiguraton (Implementierung in lib/config.py) in einer Datei mit dem Namen test_config.py abgelegt. Oder Tests für Funktionen aus lib/utils.py liegen demnach in test_util.py.

Bei der Ausfürhung der Tests werden dort alle Tests berücksichtig, die im tests/ Verzeichnis liegen und dem Namensschema test_XXX.py entsprechen. Die eigentlichen Testfunktionen muessen dem Schema test_XXX() entsprechen.

Beispiel:

import unittest

class ExampleTests:

    def test_XXX(self):
        # execute some code, an verify results
        self.assertEqual(1, ...)
        self.assertFalse('123' in ...)

Tests für Plugins

Genauso wie es sich auch für Core Tests verhält, verhält es sich auch bei den Plugin-Tests. Diese Tests werden in das Plugin-Verzeichnis in tests abgelegt. Sobald auch hier Tests vorhanden sind, werden diese automatisch ausgeführt. Auch die Namenskonvention ist identisch (Dateien nach dem Schema test_XXX.py, Funktionen nach dem Schnema test_XXX()) und die Verzeichnisstruktur sollte beibehalten werden (mock, resources - falls notwendig).

Werden die Tests für Plugins umfangreicher, empfiehlt es sich diese in separate Dateien aufzuteilen um den Überblick zu vereinfachen. Gleicher Code kann auch in eine eigene Datei oder Module ausgelagert und in den jeweiligen Testdateien eingebunden werden.

Travis-CI

Damit die Tests automatisch bei jeder Änderung des Codes ausgeführt werden, ohne dass dies manuell angestoßen werden muss, wird Travis-CI verwendet. Dort sind beide Bereiche von SmartHomeNG eingebunden um die Tests automatisiert auszuführen:

Konfiguration

Damit Travis-CI weiss, was zur Ausführung der Tests ausgeführt werden soll, gibt es in jedem Repository eine Konfigurationsdatei mit dem Namen .travis.yml. Dort ist beispielsweise hinterlegt, dass die Tests mit tox ausgeführt werden sollen, dass sie mit bestimmten Python Versionen ausgeführt werden sollen, oder dass es sich um ein Python-Projekt handelt (Travis-CI kann prinzipiell alle Arten von Projekten und Programmiersprachen unterstützen).

Einstellungen in .travis.yml (und deren Wert):

  • language - legt die Programmiersprache fest (python)
  • python - enthät eine Liste von Python-Versionen die ausgeführt werden sollen (Liste mit 3.3 bis 3.5)
  • before_install - konfiguriert ein oder mehrere Befehle die vor install ausgeführt werden (git Kommando um Submodule zu initialisieren)
  • install - konfiguriert ein oder mehrere Befehle die vor der eigentlichen Ausführung ausgeführt werden (pip Kommando um Requirements zu installieren, tox-travis, virtualenv)
  • script - definiert das eigentlich auszuführende Skript (Ausführung von tox)

Travis-CI für damit die Tests für alle angegebenen Python-Versionen aus. Durch die Angabe von mehreren Python-Versionen wird eine Ausführungsmatrix bei Travis-CI erzeugt, die alle Versionen beinhalten. Eine solche Ausführungsmatrix kann auch durch andere Parameter (wie z.B. Definition von Umgebungsvariablen) erzeugt werden.

Ausfrühung

Die Ausführung der Tests läuft in alle Repositories gleich ab und verwendet die gleiche Konfiguration und das gleiche Skript (jeweils dupliziert in den Repositories und sollten gleich gehalten werden). Der einzige Unterschied ist der Wert REPOSITORY_ORIGIN in der .travis.yml, wechler den Name des Repositories behinhaltet für das die Konfiguration gilt.

Werden nun Änderungen in die Repositories gepusht wird ein Build-Job in Travis-CI angestoßen (funktionert mit einem GitHub-Hook). Travis-CI führt den Build anhand der Konfiguration aus, in der letzendlich die Ausführung des Skriptes .travis.sh steht.

Folgende Schritte werden ausgeführt (laut Konfiguration .travis.yml):

  1. Travis-CI checkt standardmäßig das Repository in der Revision des letzten Commits aus
  2. Anschließend werden die Requirements installieren (z.B. tox)
  3. Danach wird das Skript .travis.sh ausgeführt

Die Ausführung des Skriptes ist wie folgt (in .travis.sh):

  1. Ermitteln in welchem Branch die Repositories ausgecheckt werden sollen (master vs. develop)
  2. Auschecken der Repositories, sofern sie noch nicht von Travis-CIS ausgecheckt wurden
  3. Einrichten der Umgebung, sodass die Checkouts verwendet werden (z.B. plugins Repo in core verlinken)
  4. Starten der Test-Suite mit tox

Es wird die folgende Verzeichnisstruktur auf Travis-CI hergestellt:

  /home/travis/build/smarthomeNG    - Standardverzeichnis von Travis
    /plugins                        - Checkout des plugins-Repo
    /smarthome                      - Checkout des smarthome-Repo

Zu 1) Wird ein Build in einem Branch angestoßen so wird der entsprechende Name des Branch in der Umgebungsvariable TRAVIS_BRANCH gesetzt. Diese Variable wird verwendet um zu pruefen ob der master oder develop der fehlenden Repositories ausgecheckt werden soll.

Zu 2) Travis-CI checkt standardmäßig das Repository aus, für den der Build angestoßen wurde. Ergaben sich Änderung im core Repository, wird dieses ausgecheckt, ergaben sich Änderungen im plugins Repository, wird das ausgecheckt. Je nach dem fehlt dann das plugins oder das core Repository, welches dann per Skript noch zusätzlich ausgecheckt im zuvor ermittelten Branch wird.

Zu 3) Sind alle Repositories ausgecheckt, werden entsprechende Links gesetzt, damit das ausgecheckte plugins Repository unterhalb des ausgecheckten core Repository zu finden ist.

Zu 4) Ist die Umgebung mit den jeweilgen Repositories eingerichtet, kann der Testlauf gestartet werden.

Ältere Artikel zu Items

Ältere Logik Beispiele


Release Notes

Die aktuellen Release Notes und die Release Notes der zurückliegenden Versionen sind in der Dokumentation im Abschnitt Release Notes zu finden.

Updates

Work in Progress und Planungen


Clone this wiki locally