Hauptmenü

Unit Test?

Begonnen von herrmannj, 10 Mai 2020, 12:54:23

Vorheriges Thema - Nächstes Thema

herrmannj

Schade dass man in main nichts testen kann. Wäre es dann nicht möglich einen sourcefilter zu verwenden und 'package main' gegen 'package hobo' im "Testobjekt" auszutauschen ? Dann müsste das doch gehen, ist ja dann nicht mehr main? Oder?

Sidey

Zitat von: herrmannj am 10 Mai 2020, 21:41:48
Frage: wie müssen Tests organisiert werden um in der bestehenden Hierarchie (Namespace) maximalen Output für den Ersteller zu generieren?

Lass die Tests in FHEM laufen, bis eine bessere Lösung gefunden wurde und lagere aus, was nicht wirklich zu FHEM gehört.
Ich hatte auch mal die wahnwitzige idee ich könnte aus fhem.pl ein fhem.pm machen um es mittels use einzubinden. Das wäre aber zu viel Anpassungarbeit gewesen.

Ich lasse die "UnitTests" innerhalb von FHEM über ein makefile durchlaufen.
Output ist ganz okay finde ich:
https://travis-ci.com/github/RFD-FHEM/RFFHEM/jobs/331167290

Und die nativen Perl Modultests lasse ich separat laufen:
https://github.com/RFD-FHEM/RFFHEM/runs/660623007?check_suite_focus=true

Die Variante von HOBO ist natürlich netter, aber dazu müssten die ganzen tollen Funktionen aus fhem.pl in ein Modul das man mit use einbinden kann. :)

Grüße Sidey


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

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

RichardCZ

Zitat von: herrmannj am 10 Mai 2020, 21:57:47
Schade dass man in main nichts testen kann. Wäre es dann nicht möglich einen sourcefilter zu verwenden und 'package main' gegen 'package hobo' im "Testobjekt" auszutauschen ? Dann müsste das doch gehen, ist ja dann nicht mehr main? Oder?

Ich weiß nicht ob "man kann". Ich kann's nicht.

Und ob das Ding jetzt "main" heisst oder "hobo", ist wurst. Geht beides nicht.
Es sollte so heißen wie der Dateipfad ist. Und nur so und nur 1 package pro Datei.

lib/FHEM/MordsSamsungAV.pm -> package FHEM::MordsSamsungAV;

dann unter t

t/FHEM/MordsSamsungAV/*.t

Deswegen gibt es auch nicht package hobo, sondern

lib/HoBo.pm
lib/HoBo/Command.pm
...


und die zugeh. Testfiles.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

rudolfkoenig

Ich habe ein Test-Framework fuer FHEM Module erstellt und eingecheckt.

Kurz:
% prove t/*/*.t
t/00_MQTT2_SERVER/00_parseMsg.t .... ok   
t/00_MQTT2_SERVER/01_autocreate.t .. ok   
All tests successful.
Files=2, Tests=4,  1 wallclock secs ( 0.04 usr  0.02 sys +  0.36 cusr  0.06 csys =  0.48 CPU)
Result: PASS


Lang:
- (etwas OT): fhem kann ab sofort auch mit einem leeren cfg gestartet werden, bisher war noch mindestens "attr global modpath ." notwendig
- fhem.pl hat eine neue Option -t bekommen. Falls gesetzt, dann wird erst neben dem Argument eine Konfigurationsdatei gesucht (testname.cfg oder fhem.cfg), und danach die Testdatei per require ausgefuehrt. Das hat zur Folge, dass die Testdatei mit 1; beendet werden muss, und irgendwo ein exit(0) aufrufen muss.
- mit -t wird automatisch eine Instanz von FhemTestUtils (neu) definiert, was man zum Pruefen des FHEM-Logs oder Events verwenden kann. FhemTestUtils sammelt alle Logs/Events, und bietet zwei Funktionen an, um in der Liste jeweils mit einem Regexp suchen zu koennen.

Ich habe fuer MQTT2_SERVER zwei Beispiele eingecheckt: was Einfaches, was das Parsen direkt prueft:
# Simple test. NOTE: exit(0) is necessary
use strict;
use warnings;
use Test::More;

{ MQTT2_SERVER_ReadDebug($defs{m2s}, '0(12)(0)(5)helloworld') }
is(FhemTestUtils_gotLog("ERROR:.*bogus data"), 0, "Correct MQTT message");

FhemTestUtils_resetLogs();
{MQTT2_SERVER_ReadDebug($defs{m2s}, '(162)(50)(164)(252)(0).7c:2f:80:97:b0:98/GenericAc(130)(26)(212)4(0)(21)BLE2MQTT/OTA/')}
is(FhemTestUtils_gotLog("ERROR:.*bogus data"), 1, "Bogus message, as expected");

done_testing;
exit(0);
1;

und etwas Aufwendigeres, was per mosquitto_pub-Aufruf ein Geraet erzeugt:
# More complex test, with external program and delayed log/event checking
# Note: exit(0) must be called in the delayed code.
use strict;
use warnings;
use Test::More;

my $usage = `mosquitto_pub 2>&1`;
if(!$usage) { # mosquitto not installed
  ok(1);
  done_testing;
  exit(0);
}

fhem('"mosquitto_pub -i test -t hallo -m world"');
InternalTimer(time()+1, sub() {
  is(FhemTestUtils_gotLog(
        "autocreate: define MQTT2_test MQTT2_DEVICE test m2s"), 1,
        "autocreate log");
  is(FhemTestUtils_gotEvent("MQTT2_test:hallo: world"), 1,
        "autocreate event");
  done_testing;
  exit(0);
}, 0);

1;


prove wird eigentlich mit "prove --exec 'perl fhem.pl -t' t/*/*.t" aufgerufen, aber dank der (eingecheckten) .proverc kann man den Aufruf (wie oben) abkuerzen.

Und so schaut der Aufruf aus, wenn man den Test entwickelt:
% perl fhem.pl -t t/00_MQTT2_SERVER/01_autocreate.t
2020.05.13 12:42:24 1: Including t/00_MQTT2_SERVER/01_autocreate.cfg
2020.05.13 12:42:24 3: m2s: port 1883 opened
2020.05.13 12:42:24 1: Messages collected while initializing FHEM:SecurityCheck:
  m2s is not password protected

Protect this FHEM installation by defining an allowed device with define allowed allowed
You can disable this message with attr global motd none

2020.05.13 12:42:24 0: Featurelevel: 6
2020.05.13 12:42:24 0: Server started with 3 defined entities (fhem.pl:21926/2020-05-13 perl:5.018002 os:darwin user:rudi pid:23070)
2020.05.13 12:42:24 2: autocreate: define MQTT2_test MQTT2_DEVICE test m2s
ok 1 - autocreate log
ok 2 - autocreate event
1..2


Sidey

Das sieht ja schon sehr gut aus.

Werde ich mir näher ansehen und detaillierte Rückmeldung geben.
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

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

RichardCZ

Ich finde das super, endlich bewegt sich was.

Wenn ich einen Vorschlag machen könnte, dann wäre das die gesamte Testsuite nach t/FHEM zu schieben, also einen Level tiefer

t/FHEM/00_MQTT2_SERVER/...

Zum einen bewahrt das vor absehbaren Nameclashes (denn es kann nur ein t-Verzeichnis geben)
zum anderen kann man dann unter t/FHEM/* smoketests schreiben die für alle FHEM Module laufen.

Ach ja, letztere kann ich beisteuern, weil die bei mir - unter t/FHEM/* eh auf einen commit warten.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

herrmannj

Zitat von: RichardCZ am 11 Mai 2020, 10:05:25
Ich weiß nicht ob "man kann". Ich kann's nicht.

Zitat von: RichardCZ am 13 Mai 2020, 20:41:18
Ich finde das super, endlich bewegt sich was.
...
Ach ja, letztere kann ich beisteuern, weil die bei mir - unter t/FHEM/* eh auf einen commit warten.

Wie schnell sich die Zeiten doch ändern ;)


rudolfkoenig

Zitatt/FHEM/00_MQTT2_SERVER/...
Kann ich gerne machen, wenn ich verstehe, wozu: was wollen wir sonst fuer Tests hier reinpacken?

Sidey

Hi Rudi,

Super, ich habe mir die Implementierung angesehen. Das ist schon deutlich besser, als das was ich bisher hatte.
Vor allem die Idee sich in $logInform reinzuhängen. Echt klasse. Ich hab mir da immer einen abgemockt um die Logs abfangen zu können. ;)

Ein paar Anregungen / Fragen habe ich aber dennoch:

Deine Lösung mit "FhemTestUtils_gotLog" und "FhemTestUtils_gotEvent" hat mich zum grübeln gebracht.
Ich hätte es allerdings viel lieber, dass ich auf die Logs direkt zugreifen kann und das nicht eine Funktion für mich darin sucht.
Wieso? Weil ich dann einen Compare aus der Testsuit den Inhalt prüfen kann. Das muss man in anderen Datenstruktuen ebenfalls so anwenden und nebenbei bekommt man im Fehlerfall deutlich bessere Meldungen über was steht wirklich in dem Array und nach was wurde gesucht.

Ich schlage daher vor, Subs in das Modul aufzunehmen, die eine Referenz auf @logs und @events liefern.  (Siehe Patch).
Habe auch noch einen Kopierfehler im define korrigiert

Damit ließe sich, am Beispiel 00_parseMsg.t der Test wie folgt realisieren und vom Test her genauer steuern was in @logs stehen soll oder auch nicht:

use strict;
use warnings;
use Test2::V0;
use Test2::Tools::Compare qw{is bag};

my $fhemLogs=FhemTestUtils_getLogRef;


{ MQTT2_SERVER_ReadDebug($defs{m2s}, '0(12)(0)(5)helloworld') }
is( $fhemLogs,bag {item !match(qr/ERROR:.*bogus data/); end();}, 'Correct MQTT message');

FhemTestUtils_resetLogs();
{MQTT2_SERVER_ReadDebug($defs{m2s}, '(162)(50)(164)(252)(0).7c:2f:80:97:b0:98/GenericAc(130)(26)(212)4(0)(21)BLE2MQTT/OTA/')}
is( $fhemLogs,bag {item match(qr/ERROR:.*bogus data/); etc(); }, 'Correct MQTT message');

done_testing;
exit(0);
1;


Weiterhin, die Ausgabe der Logmedlungen auf der Konsole. Lassen sich diese abstellen?
Ich würde aus der Testsuit eher auf diag zurückgreifen wenn etwas nicht in Ordnung ist.


Ich habe auch festgestellt, dass sich alle Instanzen von FhemTestUtils das gleiche @logs und @events teilen.
Aktuell bin ich noch unsicher, ob man davon je mehr als eine gebrauchen könnte. Registriert man allerdings mehrere, so dürften die Logs mehrfach in @logs auftauchen und das den Test ggf. verfälschen, wenn man z.B. die Anzahl von Logmeldungen zählen würde?


Der in der Readme angegebene perl Aufruf klappt bei mir nicht:

perl fhem.pl t/00_MQTT2_SERVER/00_parseMsg.t
mit
perl fhem.pl -t t/00_MQTT2_SERVER/00_parseMsg.t 
Klappt es.

Der Folgende Satz hat mich auch ein wenig zum Grübeln gebracht:
ZitatEach test needs a config file, with is either fhem.cfg or testname.cfg
Wenn ich es richtig verstehe, dann kann ich eine "Default" Config in jedem Verzeichnis ablegen die aber fhem.cfg benannt werden muss. Hier habe ich keinen Gestaltungsspieltaum.
Möchte ich für einen Test eine Spezielle config, dann muss ich für <testname>.t eine config <testname>.cfg anlegen. Habe ich das so richtig verstanden?




Grüße Sidey

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

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

RichardCZ

Zitat von: rudolfkoenig am 13 Mai 2020, 21:11:14
Kann ich gerne machen, wenn ich verstehe, wozu: was wollen wir sonst fuer Tests hier reinpacken?

Tests für Module in einem lib Verzeichnis (siehe z.b. CoolTuxens "Automation/ShutterControl/*") - die dann unter t/Automation/* leben
dieses (bei mir bereits erfolgreich laufende) staticperl/AppImage Gespann ist doch sicher auch für FHEM künftig interessant
da wird es eine lib/* payload geben.

Prinzipiell geht es auch ohne, aber dann ist eben ein 00_MYSENSORS z.B. auf dem gleichen Level wie "Automation" und in Anbetracht
der Tatsache, dass unter 00_MYSENSORS hierarchisch keine Submodule sind  (also 00_MYSENSORS/Irgendwas.pm), ist es m.E.
nicht zielführend damit den Toplevel t-Namespace vollzukleistern.

Zitat von: herrmannj am 13 Mai 2020, 20:59:51
Wie schnell sich die Zeiten doch ändern ;)

Nicht schnell genug, manche haben noch nicht gelernt richtig zu zitieren:

Zitatzum anderen kann man dann unter t/FHEM/* smoketests schreiben die für alle FHEM Module laufen.

Ach ja, letztere kann ich beisteuern, weil die bei mir - unter t/FHEM/* eh auf einen commit warten.

https://de.wikipedia.org/wiki/Smoke_testing#Smoke_testing_in_der_Softwareentwicklung

"Echte tests" der xx_Name FHEM Module kann ich nicht schreiben, aber Rudolf kann's offensichtlich. Ist doch gut.
Die überhaupt erste Gelegenheit wo man mal komplementär (= in diesem Fall gemeinsam) an einem Strang ziehen
könnte.


Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

Sidey

#25
Zitat von: rudolfkoenig am 13 Mai 2020, 21:11:14
Kann ich gerne machen, wenn ich verstehe, wozu: was wollen wir sonst fuer Tests hier reinpacken?

Ich nehme an, es geht hier darum, die Verzeichnisstrukturin t/ 1:1 aus dem Ordner fhem in dem fhem.pl liegt zu übernehmen.

Zumindest finde ich diesen Punkt einleuchtend, wenn eine Moduldatei in
fhem/FHEM liegt,
dass dann der test dazu auch in
t/FHEM/Modul liegt

Möchte irgendwann dann mal jemand einen Test für etwas schreiben, das in contrib liegt kommt der Test nach
t/contrib/

Und für die andere Diskussion, ob es ein
fhem/lib geben soll, wäre man dann auch gewappnet.


Ein schlagendes Argument hab ich noch, weil ich im übrigen auch schon genau mit dieser Struktur angefangen habe:
https://github.com/RFD-FHEM/RFFHEM/tree/dev-r35_xFSK_oo/t/FHEM/lib/SD_Protocols

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

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

RichardCZ

Zitat von: Sidey am 13 Mai 2020, 23:10:50
Ich nehme an, es geht hier darum, die Verzeichnisstrukturin t/ 1:1 aus dem Ordner fhem in dem fhem.pl liegt zu übernehmen.

Zumindest finde ich diesen Punkt einleuchtend, wenn eine Moduldatei in
fhem/FHEM liegt,
dass dann der test dazu auch in
t/FHEM/Modul liegt

Möchte irgendwann dann mal jemand einen Test für etwas schreiben, das in contrib liegt kommt der Test nach
t/contrib/

Und für die andere Diskussion, ob es ein
fhem/lib geben soll, wäre man dann auch gewappnet.

Jein.

Normalerweise gibt es diese 1:1 Relation nur zwischen lib und t

Ok, wir abstrahieren mal von "Normalerweise". Hier könnte man erstmal den Spagat machen und

FHEM
lib
t


so handhaben, als wäre FHEM ein Unterverzeichnis von lib. Vielleicht ist dem irgendwann so, vielleicht
bleibt das immer eine Spezialwurst. Bis dahin einfach:

lib -> t
FHEM -> t/FHEM


Sogar mit

t/contrib

könnte man operieren. Aber man sollte sich definitiv vor

t/lib

hüten, weil sonst ist man wieder im Pipi Langstrump-Land.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

rudolfkoenig

@Sidey:
ZitatWeil ich dann einen Compare aus der Testsuit den Inhalt prüfen kann.
Da FhemTestUtils_getLog das Ergebnnis von grep zurueckliefert, kann man mit .* die komplette Liste holen.

ZitatWeiterhin, die Ausgabe der Logmedlungen auf der Konsole. Lassen sich diese abstellen?
Klar, ruf sie mit prove auf :)

ZitatAktuell bin ich noch unsicher, ob man davon je mehr als eine gebrauchen könnte.
Z.Zt. ist das kontraproduktiv, bin aber offen es zu aendern, wenn das sinnvoll sein koennte.

ZitatDer in der Readme angegebene perl Aufruf klappt bei mir nicht:
Danke, habs korrigiert.


ZitatWenn ich es richtig verstehe, dann kann ich eine "Default" Config in jedem Verzeichnis ablegen die aber fhem.cfg benannt werden muss. Hier habe ich keinen Gestaltungsspieltaum.
Stimmt, irgendwo ist Schluss. Wobei ich auch noch nicht verstanden habe, warum du hier gestalten willst.


ZitatMöchte ich für einen Test eine Spezielle config, dann muss ich für <testname>.t eine config <testname>.cfg anlegen. Habe ich das so richtig verstanden?
Ja, siehe t/00_MQTT2_SERVER/01_autocreate.cfg


@RichardCZ
ZitatPrinzipiell geht es auch ohne, aber dann ist eben ein 00_MYSENSORS z.B. auf dem gleichen Level wie "Automation"
Verstanden, aber wenn man Modularisierung ernst nimmt dann sollte CoolTux & Co. sein Modul FHEM::XX::YY::ZZ nennen, womit das FHEM Verzeichnis wiederum im Weg stehen wuerde. Hast du auch fuer diese Variante eine Loesung ? :)
Ich mach schon mit, will es aber nur einmal umbenennen.

Sidey

Zitat von: rudolfkoenig am 13 Mai 2020, 23:33:14
@Sidey:Da FhemTestUtils_getLog das Ergebnnis von grep zurueckliefert, kann man mit .* die komplette Liste holen.
Daran hatte ich nicht gedacht, aber wieso sollte ich ein grep auf etwas machen, wenn ich die komplette Liste 1:1 möchte?
Gibt es einen Nachteil sich die Referenz zu holen? Alternativ kann ich mich natürlich auch einfach in $loginform hängen. Bei den Events wird es halt ein bisschen Aufwändiger. :)

Zitat von: rudolfkoenig am 13 Mai 2020, 23:33:14
Klar, ruf sie mit prove auf :)

Hmm, dann bekomme ich aber meine diag Meldungen von der TestSuite auch nicht und prove -v liefert mir dann wieder alles :(
Ich hätte halt gerne nur die Meldungen aus der testsuite gehabt und nicht alles.  Machbar über eine Schalter oder nicht?

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

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

RichardCZ

Zitat von: rudolfkoenig am 13 Mai 2020, 23:33:14
@RichardCZVerstanden, aber wenn man Modularisierung ernst nimmt dann sollte CoolTux & Co. sein Modul FHEM::XX::YY::ZZ nennen, womit das FHEM Verzeichnis wiederum im Weg stehen wuerde. Hast du auch fuer diese Variante eine Loesung ? :)
Ich mach schon mit, will es aber nur einmal umbenennen.

Wenn CoolTux & Co. ihre Module FHEM::XX::YY::ZZ nennen hat das erstmal weniger mit Modularisierung als mit besagter Megalomanie zu tun.
Statt CPAN nennen wir es FHEM.  ;)
Der Punkt hinter Automation/* und nicht FHEM/Automation/* ist ja, dass man vielleicht wiederverwendbaren/generischen Code schreiben möchte der nicht FHEM-spezifisch ist.
Ok. ShuttersControl schafft das vielleicht noch nicht, aber so ein MySensors/* kommt sicher bald hin.

Ich sehe (was den Perl code anbelangt) relativ weit in die Zukunft. Und in dieser weiten Zukunft sehe ich keinen Grund diese Tests von t/FHEM/* wieder irgendwoanders hin zu schaufeln.
Selbst wenn alle FHEM Module irgendwann (in ferner Zukunft) nach lib/FHEM/*.pm wandern sollten, bleibt ja t/FHEM bestehen. Die Sache wird dann nur konsistenter.

Also ich sehe nicht mehr als die eine Umbenennung.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.