• Noser.com
facebook
linkedin
twitter
youtube
  • NOSERmobile
    • Android
    • HTML 5
    • Hybrid Apps
    • iOS
    • Windows Phone
  • NOSERembedded
    • Medizintechnik
  • NOSERprojektmanagement
  • NOSERtesting
  • NOSERlifecycle
    • .NET Allgemein
    • Application Lifecylce Management
    • Apps
    • Architektur
    • ASP.NET
    • Azure
    • Cleancode
    • Cloud
    • Silverlight
    • Visual Studio / Team Foundation Server
    • Windows 8
    • Windows Presentation Foundation
  • NOSERinnovation
    • Big Data
    • Cloud
    • IoT
    • Operations Research
    • Augmented Reality
    • RFID, NFC, Bluetooth LE

Embedded-Prototyping mit MicroPython

24. Oktober 2019
Christian Mueller
0
Embedded, MicroPython, Python

Bei der Entwicklung von Embedded Software muss man sich mit Crosscompiling, herstellerspezifischen Libraries / Tools / IDEs sowie low-level Sprachen herumschlagen. Diese langsamen Iterationen fallen insbesondere beim Prototyping negativ ins Gewicht. Mit MicroPython ist das Versprechen verbunden, die komfortablen Features von Python3 – inkl. interaktiver Konsole – für die Entwicklung im Embedded Bereich zugänglich zu machen. Kompilieren und flashen ist nicht nötig und Code wird einfacher wiederverwendbar.

READ MORE

Einfache Testautomatisierung mit Robot Framework

26. Juni 2018
Christian Mueller
0
automated testing, continuous integration, Python, Robot Framework, Testmanagement, Teststrategie

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?

  • Einfaches Einbinden von beliebigen Python-Bibliotheken
  • Tests können gut lesbar beschrieben werden und sind entsprechend gut wartbar
  • Bei jeder Ausführung wird ein ausführlicher Log und Report in HTML erzeugt
  • Tests sind in Text-Dateien definiert, welche entsprechend versionierbar sind
  • Oft benutzte Test-Logik ist out-of-the-box vorhanden
  • Viele zusätzliche Bibliotheken verfügbar für Website-Testing, Datenbank-Schnittstellen…
  • Continuous Integration mit Plugins für Jenkins, Bamboo…
  • Open Source, Apache License 2.0

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.

  • Library: Bildet eine Schnittstelle zum Target in Python (oder Java) ab
  • Keyword: Ablauf in Robot Framework, bestehend aus anderen Keywords und / oder Aufrufen von Library-Funktionen
  • Test Case: Ein Ablauf von Keywords, welcher erfolgreich durchgeführt können werden muss
  • Test Suite: Eine Sammlung von Test Cases (oder eine Sammlung von Test Suites)

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:

  • Keywords als Resource-Files in verschiedenen Test Suiten importieren und verwenden
  • Variablen (z.B. Zieladresse des Targets…) als Resource-Files importieren oder über die Kommandozeile setzen
  • Mit Setup und Teardown definieren, was beim Beginn oder Ende eines Test Cases oder einer Test Suite ausgeführt wird
  • Metadaten können während der Ausführung nach Belieben erfasst werden (z.B. Seriennummer des Targets, SW-Version…)
  • Test Suites in Ordnern hierarchisch gliedern
  • Test Cases mit Tags filtern
  • Fertige Bibliotheken für Website-Testing, Datenbank-Zugriffe, FTP, SSH, … einbinden
  • Data-driven Tests formulieren
  • Tests von Skripts (z.B. Python) generieren, um so die Tests aktuell zu halten und die Coverage zu erhöhen
  • Log-Einträge während der Ausführung mit HTML formatieren um so auch Graphen etc. in Logs ablegen
  • Post-Processing von Testresultaten (Zusammenführen von verschiedenen Durchläufen, Filtern…)
  • Dokumentationen generieren

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:

  • Ein stabiler, reproduzierbarer Startzustand ist sehr wichtig. Um unbeabsichtigte Abhängigkeiten zu vermeiden, sollte im Setup jedes Tests alle nötigen Einstellungen des Targets vorgenommen werden.
  • Ein Test Case sollte unabhängig von anderen Test Cases sein. D.h. auch wenn man nur ein einzelner Test Case ausführt, muss dessen Setup und Teardown dafür sorgen, dass der Test erfolgreich ist. Der Zustand des Targets zu Beginn darf dabei keine Rolle spielen.
  • Bei der Integration in Continuous Integration ist es ratsam, möglichst früh einfache, stabile Tests in den Workflow zu integrieren. Man kann dann schrittweise mehr und komplexere Tests hinzufügen. So gewöhnt sich das Team an den Workflow und kann kontrollierter eigene Tests entwickeln.
  • Sleep ist oft ineffizient, da man auch Spezialfälle berücksichtigen muss (temporär hohe Last beim Host oder Target…). Wait Until Keyword Succeeds (Dokumentation) erlaubt hier schnellere Reaktionen.

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.

12

Tag Cloud

.NET android Angular AngularJs Arduino ASP.Net automated testing Azure Big Data C# C++ Cloud continuous integration Elm Embedded Führung gRPC Internet of Things IoT Java Javascript M2M OWASP Projektmanagement protobuf Python Raspberry Pi Reactive Programming REST Scrum Security Softwarequalität SPA Testen testing Testmanagement Teststrategie UX Visual Studio WebAPI windows WPF Xamarin Xamarin.Android Xamarin.Forms

Archive

Current Posts

  • Akzente setzen mit der Android Splash Screen API unter .NET MAUI
  • Do You have Your Personal Space?
  • Automated provisioning with ARM Templates
  • Asynchrone Beobachtungen und Versprechungen in Angular
  • Simplify Your Automated Tests With Fluent Syntax

Last Comments

  • Hans Reinsch bei Der Safety-Plan: Die wichtigsten Antworten mit Checkliste
  • George H. Barbehenn bei Modeling Optocouplers with Spice
  • Noser Blog Touch-Actions in Xamarin.Forms - Noser Blog bei Mach mehr aus Animationen in Xamarin.Forms mit SkiaSharp
  • Noser Blog Focus on the Secure Storage service of Trusted Firmware (TFM) - Noser Blog bei First run of the Trusted Firmware (TFM) application
  • Noser Blog First run of the Trusted Firmware (TFM) application - Noser Blog bei Focus on the Secure Storage service of Trusted Firmware (TFM)

Popular Posts

Xamarin.Android Code Obfuscation

6 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 1 - Aufbruch

5 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 2 - Kein Picknick

4 Comments

Contact us

  1. Name *
    * Please enter your name
  2. Email *
    * Please enter a valid email address
  3. Message *
    * Please enter message
© 2013 NOSER ENGINEERING AG. All rights reserved. Datenschutz | Cookie-Richtlinie