Hallo zusammen, im Rahmen meiner Bachelor Arbeit habe ich mich mit Teststrategien für Embedded Systeme auseinander gesetzt und unter anderem Analysiert wieso vergleichsweise wenig Software automatisiert getestet wird. Ein Grund hierfür ist meiner Meinung nach, dass in vielen (Legacy) Projekten interne Software-Abhängigkeiten das erstellen von Testfällen erschweren. Idealer Weise wird zur Reduktion von Abhängigkeiten die „Link-Time Substitution“(LTS) eingesetzt. Dies setzt aber voraus, dass bereits bei erstellen der Module auf Testbarkeit geachtet wird und einzelne Source-Files nur wenige Funktionalität realisieren. Oftmals kommt es jedoch vor, dass einzelne Source-Files viele Funktionen haben, sodass hier die LTS kaum eingesetzt werden kann. Hier setzt meine Arbeit an: ich habe ein System entworfen, welches in der Lage ist über den GDB File interne Abhängigkeiten aufzulösen und so die Testbarkeit zu vereinfachen. Nun habe ich die Erlaubnis erhalten, dass das Projekt veröffentlicht wird: https://github.com/intel/Dependency-Reduction-Unit-Framework/ Ich hoffe ich kann hiermit ein wenig zur verbesserten Testabdeckung beitragen. Für Fragen stehe ich gerne zur Verfügung Basti195
Basti B. schrieb: > Teststrategien für > Embedded Systeme auseinander gesetzt und unter anderem Analysiert wieso > vergleichsweise wenig Software automatisiert getestet wird. In Embedded Systemen spielt die Zeit einen sehr große Rolle und nicht nur das Ergebnis. Automatisierte Tests testen immer genau in der gleichen verhersehbaren Reihenfolge und das macht es schwer, Deadlocks, Race Conditions usw. zu finden. Ein Ergebnis kann zwar richtig sein, das Programm reagiert aber falsch, wenn es zu spät vorliegt. Insbesondere äußere Ereignisse von Sensoren, gestörte Daten oder menschliche Eingaben lassen sich schwer automatisieren. Dadurch werden Tests für Embedded Systeme sehr komplex.
Beitrag #6331887 wurde von einem Moderator gelöscht.
Peter D. schrieb: > ... viel sinnvolles Zeug > Dadurch werden Tests für Embedded Systeme sehr komplex. Genau das gleiche trifft auch auf Enterprise Anwendungen zu. Automatisiertes Testen scheitert meist an den unvorhergesehenen Situationen, auf die man beim manuellen testen (meist versehentlich) stößt. Und dann gibt es noch Stellen Wo manuelle Interaktion zwingend notwendig ist (in meinem Fall z.B. die Bestätigung eines Zahlvorgangs bei Paypal). Das soll und kann man gar nicht automatisieren. Klar kann man Papal durch einen Mock ersetzen, aber dann merkt man auch nicht, wenn die Anwendung irgendwann plötzlich nicht mehr kompatibel ist weil Paypal etwas geändert hat. Bei Elektronik ist es doch nicht anders. Da kann man manche Dinge auch nur mit der echten Hardware testen, und damit meine ich nicht nur die Elektronik sondern auch die Mechanik samt Umgebung. Automatisierte Tests sind gut und schön, aber sie können manuelle Tests nur zum Teil ersetzen. Die Verkäufer der Automaten sehen das natürlich ganz anders.
Basti B. schrieb: > unter anderem Analysiert wieso vergleichsweise wenig Software > automatisiert getestet wird. Ähm, seit ISO9001 und Scrum müssten automatisierte Tests Standard sein, schliesslich kann sich keiner leisten, einen Bug, der irgendwann gefixt wurde, erneut als Bug auszuliefern. Das übliche Vorgehen dürfte wohl Jenkins im nightly build sein, und bei jedem Programm ohne Benutzeroberfläche reicht es, Funktionen mit passenden Parametern aufzurufen. Das Problem ist, dass viele Programme und Module ohne ein grosses drumherum nicht laufen. Dafür möchten einem Frameworks ja Testklassen empfehlen. Unser Vorgehen ist es, für Libraries (DLL oder statisch gelinkt) jeweils ein (sonst nicht vetwendetes) Hauptprogramm zu schreiben, mit dem scriptgesteuert jede Funktion/Methode mit jedem Parametersatz aufrufbar ist, die Ergebnisse, auch Exceptions, auf Erwartungswerte geprüft werden. Old-School, von der Kommandozeile. Bei Embedded eben über den Debugger oder Simulator. Der Programmierer schreibt schon Testfälle, in denen jede Verzweigung in seinem Programm zumindest ein Mal im if und ein mal im else Fall durchlaufen wird, jede Exception ausgelöst wird. Genau so wird das Hauptprogramm getestet. Damit weiss man aber immer noch nicht, ob jeder Zweig der Systemfunktionen, die sich auch noch bei jedem update ändern können, gecheckt wird. Bugs kommen also auch von den Anwendern als Meldung, und als erstes sind die dann mit dem Test-Tool nachzuvollziehen. Werden sie gefixt, bestätigt das Test-Tool mit genau dem Testfall den fix. Und wird dauernd nachgecheckt. Da ggf. Abhängigkeiten vom Betriebssystemversion und -updatestand bestehen, laufen einige Tests in eingefrorenen virtuellen Maschinen, das kann Jenkins ja. Um Probleme mit Multithreading nachstellen haben wir Spezialfunktionen drin, die gezielte Prozessabläufe erlauben. Schwieriger ist es, Programme mit Bedienoberfläche und graphischem Output zu kontrollieren, dafür gibt es aber Hilfsprogramme. Hiess eins davon WinRunner ? Jedenfalls gut, dass du dir Gedanken machst, und was anbietest.
MaWin schrieb: > Der Programmierer schreibt schon Testfälle, in denen jede Verzweigung in > seinem Programm zumindest ein Mal im if und ein mal im else Fall > durchlaufen wird, jede Exception ausgelöst wird. So stellt man sich das vor. Und wer bezahlt das?
Stefan ⛄ F. schrieb: > So stellt man sich das vor. Und wer bezahlt das? Dank Scrum der Auftraggeber, denn der hat den Auftrag unterschrieben, ohne vorher zu wissen was er zu zahlen hat, da er ja auch nicht gesagt hat, was er haben will. Man hat ihm nur gesagt, wie man es bauen würde. Aber: ordentliche Tests zahlen sich langfristig aus. Man glaubt gar nicht, wieviele Fehler in einem selbstgeschriebenen strcmp o.ä. stecken können.
MaWin schrieb: > Dank Scrum der Auftraggeber, denn der hat den Auftrag unterschrieben, Ich lebe leider nicht in der heilen Welt, wo man nach Lehrbuch arbeiten darf. Wenn wir dem Auftraggeber zu langsam oder zu teuer werden, müssen wir mit Abbruch des Projektes rechnen - natürlich ohne Bezahlung. Umgekehrt hat uns aber noch niemals ein Kunde abgestraft, wenn wir übermäßig eilig gehandelt haben. Für das Testen und die Dokumentation gibt man uns (zusammen gerechnet) typischerweise 30% bis 50% der gesamten Entwicklungszeit. Was dabei heraus kommt, kannst du dir denken. "Notlösung" wäre dazu ein passender Begriff, oder "geht so gerade noch". Aber immerhin besser als gar nichts. Ich hatte auch mal in einer Firma gearbeitet, wo man mit voller Absicht gar nicht dokumentiert hat und mangels Doku auch nicht ernsthaft testen konnte. Der Code sei die Doku, hieß es. Da möchte ich nicht wieder hin.
Peter D. schrieb: Automatisierte Tests testen immer genau in der > gleichen verhersehbaren Reihenfolge und das macht es schwer, Deadlocks, > Race Conditions usw. zu finden. Ein Ergebnis kann zwar richtig sein, das > Programm reagiert aber falsch, wenn es zu spät vorliegt. Das stimmt so zunächst natürlich. Hierbei handelt es sich um eine allgemeine Schwierigkeit von SW-Tests. > Insbesondere äußere Ereignisse von Sensoren, gestörte Daten oder > enschliche Eingaben > lassen sich schwer automatisieren. > Dadurch werden Tests für Embedded Systeme sehr komplex. Hier kann ich jedoch nur bedingt zustimmen. Durch das auflösen der Abhängigkeit eines verarbeiten Modules zu z.B. der Hardware, ist es möglich verschiedene Szenarien zu Testen. Wird z.B. der HAL durch Stubs oder Mocks ersetzt „denkt“ das getestete Modul, dass es mit Realer Hardware interagieren würde. Auf diese kann bereits mit Unit und Integrationstests viele Probleme aufgezeigt werden. So können zum Beispiel gestörte Daten oder Interne Fehler der HAL simuliert und getestet werden. Ist es nun nicht möglich mit herkömmlichen Methoden diese Abhängigkeit aufzulösen, kann mein System verwendet werden. Stefan ⛄ F. schrieb: > Für das Testen und die Dokumentation gibt man uns (zusammen gerechnet) > typischerweise 30% bis 50% der gesamten Entwicklungszeit. Was dabei > heraus kommt, kannst du dir denken. "Notlösung" wäre dazu ein passender > Begriff, oder "geht so gerade noch". Aber immerhin besser als gar > nichts. Testen ist natürlich ein Investment welches man nicht sieht, wenn man es tätigt. Im Rahmen meiner Arbeit habe ich mir die Kosten angeschaut, die ein Bug verursacht. Hier steigt der Faktor signifikant, je später der Bug gefunden wird. Meiner Meinung nach kann hier bereits viel Zeit und Frust gespart werden, wenn bereits direkt beim erstellen einer Funktion die entsprechenden Unit-Tests erstellt werden. Ich sage das so, weil das für mich nicht ganz intuitiv war. Aus eig Erfahrung aber weiß ich, dass man beim erstellen/bearbeiten einer Funktion/Modul manchmal nicht alle Randbedingungen so wie gewünscht umgesetzt werden. Ein Test ist hier eine einfach Verifikation. Grüße
Basti B. schrieb: > Testen ist natürlich ein Investment welches man nicht sieht Weswegen unsere Kunden nur wenig Geld für's Testen ausgeben. Sie sind eher bereit, viel Geld für schnelle Problemlösungen auszugeben. Nun liegt es also an uns, so viel Automatisierung wie möglich im Rahmen der gegebenen Zeit einzubauen, damit wir es später bei der Produktpflege einfacher haben. Lohnen tut sich das ganze aber nur, wenn es tatsächlich zu einer langen Produktpflege kommt. Ob es dazu kommt, weis man wiederum anfangs noch nicht, was wiederum die Investitionsbereitschaft meiner Entwicklungsfirma beeinflusst. > manchmal nicht alle Randbedingungen so wie gewünscht > umgesetzt werden. Ein Test ist hier eine einfach Verifikation. Das interpretieren der Anforderungen verschiebst du damit vom Entwickler der Anwendung auf den Entwickler der Tests, was in meinen Fällen stets die gleiche Person war. Jetzt darfst du mal raten, wer die technische Umsetzung für die Zukunft detailliert dokumentiert - die selbe Person. Vernünftig testen kann man meiner Meinung nach nur, wenn die Testkriterien vom Auftraggeber selbst geschrieben werden. Habe ich so aber in 30 Jahren noch kein einziges mal erlebt.
Was auch gerne beim Testen vergessen wird ist das Profiling. Programme wachsen und wachsen. Ob aber genügend CPU-Leistung verfügbar ist, alle kritischen Tasks rechtzeitig auszuführen, wird dem Zufall überlassen. Zum Programmieren gehört daher auch, Engpässe zu erkennen und zu lösen. Z.B. ein Steppermotor darf nicht ruckeln, eine Grafikanzeige kann ruckeln.
Stefan ⛄ F. schrieb: > Vernünftig testen kann man meiner Meinung nach nur, wenn die > Testkriterien vom Auftraggeber selbst geschrieben werden. Habe ich so > aber in 30 Jahren noch kein einziges mal erlebt. Kommt drauf an von "welchen" Tests wir sprechen. Annahme: Ich erhalte den Auftrag ein Modul zu entwerfen. Hier muss u.a. spezifiziert sein: * welche Schnittellen gibt es * verhalten eines Moduls bei Parameter x,y und Randbedingung z Der Auftraggeber sollte nun die Anforderungen in der Abnahme überprüfen (z.B. durch Systemtests). Der Entwickler selber kann jedoch mit Unittests einzelne Funktionen und Module testen über die er die Kontrolle hat. Hier ist vor allem das überprüfen von Äquivalenzklassen wichtig (welcher Parameter hat welches gleiche verhalten). Hier kann zum Beispiel die Funktion zum schalten eines Pins mit dem Parameter int8_t drei solcher Äquivalenzklassen haben. An(>0), Aus(==0) und NichtDefiniert(<0) Für jeder dieser Klassen können nun bis zu 2 Tests erstellt werden. Jeweils einer für die Grenzen der Äquivalenzklasse. D.h mit folgenden Parametern 127,1,0,-1,-128. So lassen sich schonnmal das verhalten einer Funktion Testen. Die Interaktion von Modulen (Integrationstests) ist hier komplizierter. Hier kann es tatsächlich sein, dass unterschiedliche Interpretationen einer Anforderung zu unterschiedlichen verhalten führen kann. Was jedoch gemacht werden kann, gegen die vorhandene Spezifikation zu Testen. Hier hat zum Beispiel ein Modul zum Ansteuern einer Tür eine initDoor, setState und deInitDoor Funktion. Auch wenn in der Anforderung z.B. nicht spezifiziert ist was passiert wenn initDoor Fehlschlägt und dann setState aufgerufen wird kann hier die Interaktion, sowie die "klar/eindeutig" Definierte Schnittelle Überprüft werden (setState schreibt das erwartete Ergebnis auf den Pin). System Tests sind hier nochmal deutlich komplizierter. Hier ist es ja das Ziel das System als Ganzes zu testen. Hier sollten Nachbarsysteme wie z.B. die Türansteuerungs-Elektronik durch Stubs ersetzt werden (was zum teil sehr viel Aufwand ist und wirklich Teuer werden kann, weshalb die oft Manuell durchgeführt werden). Hinzu kommt das hier die Anforderung oft noch schwammiger sind als auf Modul/Komponenten Ebene. Zum Aufwand er einzelnen Test lässt sich sagen: Unit << Integration << Systemtest So kann das erstellen eines Unittests in wenigen Minuten erledigt sein. Integrations- und System -Tests sind m.m.n. zwischen 30min und vielen Stunden. Je nachdem wie hier die Testumgebung ist. Natürlich kann ich hier nur aus der theoretischen Sicht sprechen, da ich noch nie in einem wirklich großen Projekt gearbeitet hab.
Gut zu Testen ist auf jeden Fall um ein vielfaches komplexer, als gut zu programmieren.
Peter D. schrieb: > Automatisierte Tests testen immer genau in der > gleichen verhersehbaren Reihenfolge Merkwürdige Behauptung. https://de.wikipedia.org/wiki/Fuzzing
Michael Gugelhupf schrieb: > Merkwürdige Behauptung. https://de.wikipedia.org/wiki/Fuzzing Wichtig ist besonders, daß die Daten zu zufälligen Zeiten kommen und auch asynchron zum CPU-Takt. Wenn die CPU die Daten selber erzeugt, sind sie zwangsläufig schön regelmäßig und synchron. Wenn z.B. 2 Signale immer nacheinander kommen müssen, können diese durch die Interrupthandler zu unterschiedlichen Zeiten eingelesen werden. Die CPU stellt also scheinbar einen verbotenen Zwischenzustand fest und meldet einen Fehler, obwohl alles korrekt ist.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.