en / de
Expertisen
Methoden
Dienstleistungen
Referenzen
Jobs & Karriere
Firma
Technologie-Trends TechCast WebCast TechBlog News Events Academy

Einfache Testautomatisierung mit Robot Framework

Testing ist wichtig. Denn nur so kann man sich einen Überblick über die Funktionsfähigkeit eines Produkts verschaffen. Trotzdem wird in der Entwicklung eines neuen Produkts das Testing oftmals vernachlässigt. Die Entwicklung und Ausführung von Tests brauchen Zeit. Und so lange Tests durchwegs erfolgreich, sprich «passed», verlaufen, ist deren Mehrwert nicht offensichtlich. Testautomatisierung hingegen verspricht den Aufwand für die Testdurchführung zu reduzieren, wird jedoch oft als sehr aufwändig wahrgenommen. Sinnvoll wäre, wenn jeder Softwareentwickler einfach Tests für neue Funktionen erfassen, und diese bei jeder Code-Änderung ausführen lassen könnte. Gerade in der agilen Softwareentwicklung sind Regressionstests sehr wertvoll. Denn so kann die Funktionstüchtigkeit der Software kontinuierlich gewährleistet werden.

Robot Framework kann für Behavior-Driven Integrations- und Systemtests eine gute Basis sein. Der folgende Artikel soll zeigen, wie einfach man eine beliebige Python-Bibliothek einbinden und damit auch komplexe Testabläufe verständlich erfassen kann.

Ziel: Ein Testender soll gleich schnell (oder schneller) einen Test in Robot Framework beschreiben, als diesen manuell auszuführen.

Vorteil: Jeder Test kann ohne Mehraufwand als Regressionstest verwendet werden.

Wieso Robot Framework?

Es gibt eine Vielzahl von Test Frameworks. Aber was macht Robot Framework interessant?

Eigener Python-Code in Robot Framework

Begrifflichkeiten und Hierarchie

Tests werden auf einem Host gestartet, welcher Befehle mit einem Target (DUT, Device under Test) austauscht.

Installation

Sobald Python auf dem Host installiert ist, lässt sich Robot Framework mit folgendem Befehl installieren:

pip install robotframework

Syntax

Die Test Suites werden in .robot-files definiert und mit *** Bereichname *** unterteilt. Die Unterscheidung zwischen Name von Test Cases / Keywords und deren Inhalt wird, analog zu Python, durch Einrücken definiert.

Keywords und deren Argumente werden durch mind. 2 Leerzeichen getrennt. Dies ist für Softwareentwickler sehr gewöhnungsbedürftig. Aber es erlaubt eine sehr einfaches String-Handling und gut lesbare Keyword-Namen.

Syntax-Highlighting für Robot Framework wird per Plugins in vielen beliebten Editoren unterstützt (Eclipse, IntelliJ IDEA, Notepad++ …).

Minimal-Beispiel: Aufruf von Python-Code in Robot Framework

class LibDummy:  # wie Dateiname
    def lib_dummy_assert(self):
        assert 1 == 1
*** Settings ***
Library    ./LibDummy.py
*** Test Cases ***
Call LibDummy
    lib_dummy_assert

Der Overhead für Robot Framework auf Seiten der Python-Bibliothek ist also minimal. Um nun die Test-Suite MinimalSuite.robot auszuführen, gibt man folgenden Befehl auf der Kommandozeile ein:

robot MinimalSuite.robot

Bereits auf der Konsole sieht man, ob die Tests erfolgreich waren. Die Resultate spiegeln sich auch im Return Code wieder. Ausserdem werden ein detailliertes log.html und eine Zusammenfassung in report.html erzeugt.

Konsolenausgabe

Log als interaktives HTML

Zusammenfassung der Resultate im Report

Die Rohdaten der Resultate werden in output.xml gespeichert. Diese Datei lässt sich dann in Jenkins o.Ä. parsen.

Beispiel: Serielle Schnittstelle in Robot

Angenommen, wir haben ein Gerät über COM5 verbunden. Wenn wir dort GET_SETPOINT senden, erhalten wir die aktuelle Einstellung als Antwort. Wir können mit SET_SETPOINT:300 die Einstellung auf 300 ändern und bekommen als Antwort OK zurück, wenn dies erfolgreich war. Wie können wir dieses Gerät nun per Robot Framework steuern?

import serial  # http://pyserial.readthedocs.io/en/latest/index.html

class LibSerial:
    def __init__(self, serial_port):
        self.__serial = serial.Serial(serial_port)  # open serial port

    def lib_serial_set(self, key, value):
        self.__serial.write("SET_" + key + ":" + str(value) + "\n")
        ret = self.__serial.readline()
        assert ret == "OK\n"  # target returns 'OK' if command was valid

    def lib_serial_get(self, key):
        self.__serial.write("GET_" + key + "\n")
        ret = self.__serial.readline()
        return ret[:-1]  # cut off \n of returned value

    def lib_serial_close(self):
        self.__serial.close()
*** Settings ***
Documentation    Configure Setpoint over Serial Connection using SET_SETPOINT and GET_SETPOINT
Library          ./LibSerial.py  COM5
Suite Teardown   lib_serial_close

*** Test Cases ***
Configure Setpoint and Read It Back
    Set Setpoint    50
    Setpoint Should Be    50

Configure Invalid Setpoint
    Expect Error When Configuring Setpoint    -10

*** Keywords ***
Set Setpoint
    [Arguments]  ${sp}
    lib_serial_set    SETPOINT  ${sp}

Setpoint Should Be
    [Arguments]  ${sp}
    ${read_sp}=    lib_serial_get    SETPOINT
    Should Be Equal As Numbers    ${read_sp}  ${sp}  Expected Setpoint ${sp} but got ${read_sp}

Expect Error When Configuring Setpoint
    [Arguments]  ${sp}
    Run Keyword And Expect Error    AssertionError    Set Setpoint  ${sp}

Und was ist so toll daran?

Man sieht, dass man sehr einfach eine Bibliothek in gut lesbaren Test Cases ansteuern kann. Robot Framework handhabt dabei die übliche Test-Logik. Wenn beispielsweise der erste Test fehlschlägt, wird dieser entsprechend markiert, doch der zweite Test wird dennoch ausgeführt. Ausserdem generiert Robot Framework stets detaillierte, standardisierte Ausgaben.

In diesem Beispiel sehen wir auch, wie Abläufe in gut lesbare Keywords zusammengefasst werden können und wie man diesen Argumente übergibt. Das Protokoll für die Steuerung wird für den Verfasser des Tests abstrahiert. Spätere Tests können nun komfortable, einfach verständliche Keywords wie Setpoint Should Be benutzen. Keywords können wiederum andere Keywords aufrufen und so komplexe Abläufe zusammenfassen, z.B. Update System to latest Version and load default Configuration .

Der besondere Syntax erlaubt, dass die Keywords Leerzeichen beinhalten und man Strings ohne besondere Operatoren zusammensetzen kann (z.B. Expected Setpoint ${sp} )

Oftmals bieten Hersteller von Geräten bereits eine Python-Bibliothek an. In diesen Fällen kann man entsprechend schnell diese in das Framework einbinden. Falls keine bestehende Bibliothek zur Verfügung steht, lassen sich proprietäre Kommunikationsprotokolle über serielle Schnittstellen oder TCP-Sockets verhältnismässig einfach in Python abbilden.

Wie weiter?

Bisher haben wir gesehen, wie einfach eine beliebige Python-Bibliothek in Robot Framework eingebunden werden kann. Nun können wir mit den eingebauten Funktionen von Robot Framework eine komplette Testumgebung aufbauen. Anbei seien einige Möglichkeiten aufgelistet, welche das Framework bietet:

Weiterführende Informationen finden sich auf der Robot-Framework-Homepage, dem User-Guide oder der Dokumentation der BuiltIn-Library.

Robot Framework ist also in der Lage, komplexe Testaufbauten abzubilden, erspart aber die mühselige Eigenentwicklung von häufig verwendeten Test-Funktionen.

Worauf man bei «guten» Tests achten sollte

Sie sehen, durch die Testautomatisierung eröffnen sich unzählige Möglichkeiten. Damit man sich nicht verliert, kann es hilfreich sein, sich an folgenden Punkten zu orientieren:

Man sollte sich auch Gedanken über die Grenzen der Testautomatisierung mit Robot Framework machen. Schwierig zu automatisierende Tests können auch nach wie vor (halb-)manuell ausgeführt werden, z.B. mit Dialogs. Unit-Tests sollen mit Integrations- und Systemtests nicht ersetzt, sondern ergänzt werden.

Kommentare

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Newsletter - aktuelle Angebote, exklusive Tipps und spannende Neuigkeiten

 Jetzt anmelden
NACH OBEN
Zur Webcast Übersicht