Automatisches Testen

Begonnen von Sidey, 19 September 2018, 19:36:51

Vorheriges Thema - Nächstes Thema

Sidey

Hallo,

Ich überlege schon seit längerem, ob man seine Module automatisiert testen könnte.

Damit habe ich auch schon mal ein wenig getestet.

Zwei Versuche hatte ich bislang unternommen
- FHEM mit einer Config starten, welche einen Testfall abdeckt und dann wird es tricky: Befehle an das eigene Modul kann man mittels Telnet einfach auslosen. Danach müsste man das Logfile Parsen. Z.B. auf Fehler, einen Stacktrace . Ob der FHEM Prozess abgeschmiert ist, bekommt man auch recht einfach mit.
Hat man ein Modul, welches Daten von einem Physischen Geräte verarbeitet, muss man dieses simulieren, was möglich aber auch aufwändig ist.

- Das Modul selbst könnte man aber auch starten und die FHEM Umgebung simulieren.
Diese Variante würde mir viel besser gefallen, da einzelne Funktionen des Moduls getestet werden könnten.
Bislang habe ich es aber nicht geschafft so ein FHEM Modul ohne FHEM zum Laufen zu bekommen :(

Vielleicht hat ja schon einmal jemand selbiges versucht oder Interesse an so einem Projekt.

Grüße Sidey

Gesendet von meinem XT1650 mit Tapatalk

Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

rudolfkoenig

Ich wuerde FHEM mit einer test-fhem.cfg starten, was nach der Definition der benoetigten Instanzen die Test-Befehle direkt enthaelt. Ich wuerde da neben trigger/set/get auch die Modulfunktionen mit {} direkt aufrufen.

Das Ergebnis zu analysieren duerfte komplizierter sein, und je nach Aufgabe unterschiedlich:
- notify/watchdog
- perl-Code, was Rueckgabewert oder gesetzte Attribute/Readings prueft
- Log3 umdefinieren, und nach dem Befehl pruefen, ob bestimmte Log-Ausgaben erfolgt sind.

Das alles ist nur eine Ideensammlung, ohne konkrete Erfahrung damit gemacht zu haben.

Sidey

Hallo Rudi,

Danke für deine Antwort.

Vermutlich ist es das beste, den Test aus einer laufenden FHEM Instanz zu entwickeln.

Nach meinem Post habe ich auch tatsächlich was von markusfeist gefunden.
Vom Prinzip hat er auf einem Travis-CI Server FHEM installiert und es mit einer minimal Konfiguration gestartet.
Weniger ist hier besser denke ich :)

Da sein Modul einen TCP Server bereitstellt hat er dann Daten an den Socket geschickt.
Hier muss halt jeder selbst schauen, wie er Daten am besten in das System bringt :)

Bis hier eigentlich noch einfach.
Über die Telnet Schnittstelle von FHEM sendet dann Befehle ab und wertet die Rückgabe aus. Solange alles passt, wird der Test als erfolgreich gesehen.

Das Vorgehen trifft nicht gänzlich den Begriff unittest, da FHEM durchaus mit getestet wird, allerdings könnte man ja wie Du auch schreibst, die Perl Funktionen einzeln aufrufen und den Rückgabewert verifizieren.

Spannend wird es dann an den Stellen, an denen z.B. Dispatch oder ReadingUpdate aus dem eigenen Modul aufgerufen werden.
Möchte man hier nur wissen, ob der richtige Parameter übergeben wurde, so müsste man diese Funktionen mocken.

Mit dem Überschreiben von Funktionen habe ich mich aber noch nicht beschäftigt.
Wäre eine Idee.



Hier der Link zum Ansatz von Markus:

https://github.com/markusfeist/FhemMobileAlerts/tree/master/test

Grüße Sidey

Gesendet von meinem XT1650 mit Tapatalk

Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Sidey

Hallöchen,

Ich hab mir Mock::SUB angesehen.
Damit ist es möglich Funktionen in einem Perl Modul zu überschreiben.

Also habe ich mir eine fbem.pm (symlink) erstellt und das Modul via use in ein kleines Hilfsprogramme gepackt.

Soweit so gut dachte ich, aber FHEM ist ein Script und kein Modul.
Durch den use Befehl wird FHEM dann ausgeführt ohne, dass man nun die Funktionen noch mocken könnte.

Da gäbe es nun zwei Optionen:

1) in FHEM.pm erkennen ob es als Script oder mit use aufgerufen wurde und anschließend zurück an das Hauptprogramm übergeben.
Wenn ich das grob überblicke, muss nur das eigentlich Hauptprogramm in eine SUB z.b. run gepackt werden.
Wird FHEM direkt aufgerufen dann wird die Funktionen run aufgerufen.
Läuft FHEM als Modul, muss die run sub durch das hilfsscript immer wieder  aufgerufen werden.
Dazwischen kann man FHEM Funktionen überschreiben (mocken) usw.

2) Ein eigenes Modul schreiben, welches dazu dient FHEM Funktionen zu überschreiben. Eventuell können da auch die Testfälle mit eingebaut werden.
Das Modul könnte man über eine geeignete Definition die FHEM.cfg ja einfach laden und über Telnet Befehle steuern, sofern nötig.
Vermutlich kann man es auch in die 99_myutils schreiben.

Beides hat vor und Nachteile, Meinungen erwünscht. :)


Grüße Sidey


Gesendet von meinem XT1650 mit Tapatalk

Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

betateilchen

Zitat von: Sidey am 19 September 2018, 19:36:51
Ich überlege schon seit längerem, ob man seine Module automatisiert testen könnte.

Was sind denn das für neue Sitten? Module vor der Veröffentlichung testen???
Ist es nicht ein eisernes Grundprinzip von FHEM, die QS für neue Module durch die Anwender im Einsatz machen zu lassen?

So war es zumindest bisher üblich, vor allem bei vielen Modulen, die in den letzten 2-3 Jahren veröffentlich wurden. Ob ich das gut finde oder nicht, steht auf einem anderen Blatt.

Im Ernst:

Deinen Ansatz finde ich grundsätzlich gut. Aber um eine sinnvolle Test-Infrastruktur für FHEM aufbauen zu können, müsste man große Teile von FHEM komplett umstricken und weiter kapseln. Verwendung von Namespaces wäre da schon ein erster Schritt.

Für die Umsetzung Deiner Idee wünsche ich Dir viel Erfolg - aber verrenne Dich nicht allzu sehr in die Thematik :)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

CoolTux

Zitat von: betateilchen am 20 September 2018, 15:54:16
Deinen Ansatz finde ich grundsätzlich gut. Aber um eine sinnvolle Test-Infrastruktur für FHEM aufbauen zu können, müsste man große Teile von FHEM komplett umstricken und weiter kapseln. Verwendung von Namespaces wäre da schon ein erster Schritt.

Wie gut das ich aktuell anfange mit Namespaces zu arbeiten. Und auch einige meiner älteren Module werde ich entsprechend umbauen.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Sidey


Danke für die Anmerkungen.


FHEM komplett durchtesten war und ist nicht mein Anspruch :)

Und das Testen bei den Anwendern hat meistens doch auch ganz gut funktioniert. 

Es ist halt so, dass die Module, an denen ich entwickele auch andere Personen mit entwickeln.
Die Komplexität der Abläufe trägt auch noch das ein oder andere dazu bei.
Ich würde mich halt wohler fühlen, wenn ich einfach, z.B. mit unit Tests, verifizieren könnte, ob sich ein Verhalten ändert.

Was letztendlich der richtige Code ist, muss man ja eh selbst herausfinden.

Ich denke ich schau mir die Variante mit dem eigenen Modul an. Das scheint mir zunächst wenig invasiv zu sein. Baut halt aber darauf auf, dass FHEM nicht durch fehlerhaften code Abschmiert.
Wenn dass passiert, hilft aber meistens ohnehin nur der Blick in das Logfile.


In so ein Thema kann man sich schnell verrennen. Ich glaube ich denke schon mindestens 1 Jahr darüber nach, was ich hier machen könnte.


Grüße Sidey

Gesendet von meinem XT1650 mit Tapatalk

Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Sidey

Wenn es jemanden Interessiert...

Ich habe die Variante mit dem Modul (ich habe es 98_unittest) genannt ausprobiert:

https://github.com/RFD-FHEM/RFFHEM/blob/dev-r33-travis-update/test/98_unittest.pm

Das sind bislang wirklich nur Basis tests, aber das sieht bis hier ganz gut aus.

Ich lasse den Test einfach nach dem Event INITIALIZED loslaufen und prüfe den Inhalt vom Hash eines anderes Gerätes. (Ich habe mich auf den Type und den Inhalt des readings state beschränkt.)

Das mocken der Funktion Log3 habe ich auch probierte auch. Ob es eine gute Idee ist, die Log Funktion zu kapern weiss ich noch nicht.
Ich muss jetzt erst mal eine Strategie überlegen, wie ich mal einen kleinen sinnvollen Test erstelle :)

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Sidey

Ich fasse mal zusammen was ich in den letzten Tagen so geschafft habe.

Vielleicht ist es ja auch für den ein oder anderen Entwickler interessant. :)

1. Ich habe ein Repository auf github, welches ich mit Travis CI und Coveralls verknüpft habe.

2. Bei jedem Push oder Pull-Request wird ein Build Job auf Travis CI gestartet.

3. Travis CI clont das git, installiert FHEM via deb Paket und pimpt das installiere FHEM dann via Kopieren von Dateien mit den Modulen aus dem git Repo.

4. Für das Testen habe ich ein kleines Hilfs Modul geschrieben:
https://github.com/RFD-FHEM/RFFHEM/blob/dev-r33-travis-update/test/98_unittest.pm
Das Modul hat im wesentlichen nur die Aufgabe eine Umgebung für den Test zur Verfügung zu stellen.
SUB UnitTest_Test_generic
Das Hilfsmodul führt Perlcode mittels Eval aus der im DEF Teil angegeben wurde.

Die Defininition übergebe ich mittels eines Shell Scriptes in eine laufende FHEM Instanz via Telnet, da es damit einfacher ist, das Ergebnis auszuwerten.
https://github.com/RFD-FHEM/RFFHEM/blob/dev-r33-travis-update/test/test-runner.sh

Das Shellscript wertet auch das Ergebnis vom Test aus und schreibt ihn nach STDOUT von der Shell. Dadurch kann ich die Ausgabe im Travis Build Log sehen.

So sieht eine Test Definition z.B. aus:
https://github.com/RFD-FHEM/RFFHEM/blob/dev-r33-travis-update/test/test1-definition.txt

Alternativ kann man es auch in die FHEM.cfg schreiben.

Damit FHEM auf dem Travis Server mit den richtigen Perl Einstellungen läuft muss es unter dem User Travis und nicht FHEM laufen.
Ich starte FHEM daher ohne init scripte, da ich auch noch einen Report möchte, welche Teile von meinem Code mit dem Test abgedeckt werden.
Ich lasse den Test übrigens aktuell mit drei verschiedenen Perl Versionen laufen. Und bekomme für jede Version ein eigenes Ergebnis.

perl -MDevel::Cover fhem.pl fhem.cfg

Der Report wird geschrieben, nachdem der Perl Prozess ein SIGTERM erhält. Ich habe mich für folgende Variante zum Beenden von Perl entschieden, da ich mit dem Upload des Reports warten muss, bis dieser fertig erstellt wurde:
sudo timeout 30 killall -vw perl || sudo killall -vws9 perl

Damit der Report auf Coveralls geladen werden kann kopiere ich ihn wieder ins GIT und lasse ihn auf coveralls bereitstellen:
 - cp -R /opt/fhem/cover_db ./

 - cover -select FHEM/00_SIGNALduino.pm -report coveralls


Ich weiss nicht ob der Report öffentlichen zugänglich ist, aber es sieht dann so aus:

https://coveralls.io/builds/19147953/source?filename=FHEM/00_SIGNALduino.pm#L1538

Code Zeilen die durch einen Test abgedeckt werden, sind grün hinterlegt.
Rot hinterlegte Zeilen sind nicht abgedeckt. Das funktioniert auch schon ganz gut und so sehe ich gleich, dass ich ein paar Bedingungen nicht verifiziere.



Wenn ich nun einen weiteren Test erzeugen möchte, erstelle ich eine neue TestDefiniton uns lasse diese laufen.

In folgendem Test habe noch die FHEM Funktion Diapatch überschrieben, da ich nur wissen möchte, ob die erwarteten Daten an diese Funktion übergeben wurden:
https://github.com/RFD-FHEM/RFFHEM/blob/dev-r33-travis-update/test/test3-definition.txt

Ganz ideal ist es nicht, dass ich FHEM komplett laufen lassen muss, da Devel:: Cover komplett FHEM analysiert.

Das war es erstmal mit meinem Bericht.

Gesendet von meinem XT1650 mit Tapatalk

Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Loredo

Vielleicht hilft es auch, wenn du als Basis das FHEM Docker Image verwendest.
Das FHEM Image dafür gibt es schon und es wird ebenfalls auf Travis gebaut:
https://github.com/docker-home-automation-stack/fhem-docker


Es wäre wohl ein leichtes dieses als Basis zu nehmen und quasi nur das test-integration.sh Script so zu erweitern, dass neben dem generellen hochfahren des Containers und eines erfolgreichen Health Check zusätzlich noch Module geladen und auf Funktion geprüft werden.
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Sidey

Hallo zusammen,

die Testerei funktioniert mittlerweile recht gut. Die Variante über das docker Image habe ich leider noch nicht ausprobieren können.
Das würde vermutlich das herunterladen und entpacken von FHEM etwas beschleunigen.

Ich habe aber noch ein kleines Schönheitsproblem.
Den Testcode (das ist perl code) schreibe ich aus einem shell script in die DEF von der TestDefinition:

RETURN=$(echo "$CMD" | /bin/nc localhost 7072)


In $CMD steht dann z.B. folgendes (Beispiel um die fingerprintFN zu testen):

defmod test_fingerprint UnitTest dummyDuino (
{
my $dmsg ="W84#FE42004526";;
my ($ret_name,$ret_dmsg) = SIGNALduino_FingerprintFn($targetHash->{NAME},$dmsg);;
is($ret_name ,"","check FingerprintFN name return");;
is($ret_dmsg ,$dmsg,"check FingerprintFN dmsg return");;
}
)



Genau genommen habe ich es aber nicht hinbekommen die Zeilenumbrüche zu maskieren. Ich muss aktuell alle Zeilenumbrüche entfernen und Kommentare funktionieren dadurch auch nicht im code.

Wenn jemand eine Idee hat, wie man über die Kommandozeile die Zeilenumbrüche erhalten könnte wäre ich sehr dankbar.


Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Sidey

Zitat von: Loredo am 28 September 2018, 21:07:13
Vielleicht hilft es auch, wenn du als Basis das FHEM Docker Image verwendest.
Das FHEM Image dafür gibt es schon und es wird ebenfalls auf Travis gebaut:
https://github.com/docker-home-automation-stack/fhem-docker


Es wäre wohl ein leichtes dieses als Basis zu nehmen und quasi nur das test-integration.sh Script so zu erweitern, dass neben dem generellen hochfahren des Containers und eines erfolgreichen Health Check zusätzlich noch Module geladen und auf Funktion geprüft werden.

Sorry dass ich erst jetzt darauf antworte. Ist schon etwas her.
Ich habe das Docker Image bislang noch nicht verwendet, würde es in Erwägung ziehen ein Image darauf aufbauen zu erstelleb, allerdings stellen sich da zwei "Problemlchen".

1) Gibt es die Images mit verschiedenen Perl Vesionen
2) Hat es einen besonderen Grund, dass das Image auf debian basiert. Das ist prinzipiell erst mal ein recht großes Image dadurch.

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Loredo

Verschiedene Perl Versionen gibt es in dem Image nicht, da es für den produktiven Betrieb keinen Sinn macht. Es dürfte aber nicht so schwer sein mehrere Perl Versionen darin zu installieren. Das kann man wahrscheinlich auch in einem auf fhem/fhem aufbauenden Dockerfile und perlbrew tun.


Debian wurde als Standard gewählt, weil es die meisten vorpaketierte Software mitbringt. Auch ist es die wohl am meisten verwendete Plattform. Solange alles funktioniert, sollte dir die Plattform eigentlich ziemlich egal sein, darum geht es ja bei einem Docker Image.


Da wir hier keine Micro Services in einem riesigen Schwarmcluster betreiben, ist die Image Größe meiner Meinung nach ziemlich irrelevant, da nicht ständig gepullt wird. Auch ist Speicherplatz im niedrigen 1-stelligen Gigabyte Bereich heutzutage auch überhaupt kein Problem mehr, auch nicht auf Embedded Geräten.


Ich unternehme aber schon seit längerem größere Anstrengungen (1, 2) eine Grundlage dafür zu schaffen, dass man auch ein "Lite" Image bauen kann, bei dem die benötigten Teile beim ersten Start automatisch nachinstalliert werden. Das "Full" Image wird es aber nach wie vor dann geben, weil die Installation beim ersten Start des Containers sehr bis extrem lange dauern kann (je nach Hostsystem).
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER