Holen Sie sich die UMFANGREICHSTE Abdeckung für die Einhaltung von MISRA C! Erfahren Sie mehr >>

Wann sollte man C/C++-Code für Unit-Tests nachahmen?

Von Miroslaw Zielinski

26. Juli 2018

6  min lesen

Beim Unit-Test geht es darum, die isolierten Einheiten zu testen. In diesem Beitrag sehen wir uns 7 Mal zum Verspotten an, einschließlich einiger nützlicher Fragen, damit Sie sich durch C- und C ++ - Komponententests führen können.

Wie viel Isolation für Unit-Tests benötigen wir? Dies ist eine wiederkehrende und wichtige Frage, die häufig bei der Entwicklung von Komponententests für C und C ++ diskutiert wird. Und ich spreche hier nicht von der Isolation vom Entwicklerkollegen, der neben uns im Freien sitzt und den Rhythmus der Musik aus seinen Kopfhörern trommelt (was übrigens auch sehr wichtig ist, wenn wir Gutes schaffen wollen Qualitätscode). Ich spreche von der Isolation des getesteten Codes von seiner Umgebung - seinen sogenannten Kollaborateuren.

Bevor ich fortfahre, möchte ich nur eines klarstellen: Wenn ich über das Stubben und Verspotten von C- und C ++ - Sprachen spreche, wird normalerweise eine Grenze zwischen C und C ++ gezogen, da sich die Unterschiede in der Sprachschicht in der Komplexität, den Fähigkeiten und den Erwartungen widerspiegeln in Bezug auf typische Spott-Frameworks. Mit Parasoft C / C ++ testDie Situation ist etwas anders, da die meisten Framework-Funktionen für beide Sprachen verfügbar sind. Wenn ich dieses Thema diskutiere, werde ich entweder ein C- oder C ++ - Unit-Testbeispiel geben. Wenn ich nicht ausdrücklich etwas als nur für C oder C ++ unterstützt markiere, sollten Sie immer davon ausgehen, dass für beide Sprachen bestimmte Funktionen bereitgestellt werden.

Holen Sie sich alles, was Sie zum Erstellen, Ausführen und Verwalten von Komponententests benötigen. Siehe Parasoft C / C ++ - Test in Aktion.
Sehen Sie sich eine Demo an

Isolieren oder nicht isolieren?

Einerseits schreibt der gesunde Menschenverstand vor, dass wir nicht isolieren sollten, es sei denn, wir haben einen guten Grund dafür. Am Ende erhöht das Testen der echten Mitarbeiter nur unsere Durchdringung der Codebasis. Warum sollten wir auf zusätzliche Codeabdeckung und die Möglichkeit verzichten, einen Fehler zu finden? Nun, es scheint, dass es einige gute Gründe dafür gibt - wir werden es bald diskutieren.

Auf der anderen Seite wird ein orthodoxer Unit-Tester das argumentieren Beim Unit-Test geht es darum, die isolierten Units zu testen und es soll bleiben was es ist. Das Testen mit echten Mitarbeitern ist die Domäne der Integrationsphase. Es ist eine bekannte Tatsache, dass wir unsere Tests lauter machen, wenn wir die echten Mitarbeiter in den Testumfang einbeziehen. Tests, die sich auf echte Mitarbeiter verlassen, reagieren nicht nur auf Änderungen im getesteten Code, sondern auch auf Änderungen in abhängigen Komponenten. Lautere Tests verteuern den Wartungsprozess und erzeugen viel Ablenkung. Langfristig wird diese Ablenkung normalerweise zum Hauptgrund, Ihre Unit-Testing-Praxis aufzugeben.

Wie sieht die Strategie zum Isolieren des getesteten Codes aus? In Anbetracht des Vorstehenden ist es schwierig, eine gute Regel zu formulieren, um zu bestimmen, welche Mitarbeiter verspottet werden müssen, um eine geeignete Isolierung des getesteten Codes zu gewährleisten. Unter dem Gesichtspunkt der Effizienz und Effektivität des Testens haben sowohl die Ansätze „So viel wie möglich isolieren“ als auch „Die Isolation von Komponententests nach Möglichkeit vermeiden“ Vor- und Nachteile.

3 einfache Gründe zum Verspotten

Hier sind einige offensichtlichere Situationen:

1. Collaborator noch nicht implementiert oder noch in der Entwicklung

Dies ist eine einfache. Wir haben keine Wahl und brauchen eine Scheinimplementierung. Das folgende Diagramm zeigt diese typische Unit-Test-Umgebung (SUT - Testsystem, DOC - abhängige Komponente / Mitarbeiter):

2. Hardwareunabhängigkeit

Für Entwickler, die Desktop-Anwendungen schreiben, mag diese Klasse von Problemen weit entfernt erscheinen, aber für eingebettete Entwickler ist die Hardwareunabhängigkeit von Komponententests ein wichtiger Aspekt, der ein hohes Maß an Testautomatisierung und -ausführung ohne Hardware erfordert. Ein gutes Beispiel hierfür wäre eine zu testende Einheit, die mit GPS-Hardware interagiert und erwartet, dass eine bestimmte Folge von Lokalisierungskoordinaten zur Berechnung der Geschwindigkeit bereitgestellt wird. Obwohl es eine gute Idee ist, mehr zu trainieren, kann ich mir nicht vorstellen, dass Tester mit einem Gerät herumlaufen, um Bewegungen zu simulieren, nur um die erforderlichen Testeingaben zu generieren, wenn eine Unit-Testsitzung erforderlich ist. Zu diesem Zweck zeigt dieses Beispiel, wie spät der GPS-Test eines Geräts im Entwicklungslebenszyklus wäre, wenn während der Entwicklung keine Hardwareunabhängigkeit möglich wäre.

3. Fehlerinjektion

Das absichtliche Injizieren von Fehlern ist ein häufiges Szenario beim Testen. Dies kann beispielsweise verwendet werden, um zu testen, ob die Speicherzuordnung fehlgeschlagen ist, oder um festzustellen, ob eine Hardwarekomponente ausgefallen ist. Einige Entwickler versuchen, den echten Mitarbeiter in der Testinitialisierungsphase zu stimulieren, sodass er beim Aufrufen aus dem getesteten Code mit einem Fehler reagiert. Für mich ist das nicht praktikabel und normalerweise zu viel Aufwand. Eine testspezifische, gefälschte Implementierung, die einen Fehler simuliert, ist normalerweise die bessere Wahl.

4 weniger einfache Gründe zum Verspotten

Neben diesen offensichtlichen Fällen, in denen ein verspotteter Mitarbeiter immer erwünscht ist, gibt es einige andere, subtilere Situationen, in denen gefälschte Mitarbeiter eine gute Wahl sind. Wenn unser Testprozess unter einem der unten aufgeführten Probleme leidet, ist dies ein Hinweis darauf, dass eine bessere Isolierung des getesteten Codes erforderlich ist.

1. Unit-Tests sind nicht wiederholbar

Es ist schwierig, stabile Tests zu implementieren, die von einer flüchtigen Abhängigkeit abhängen. In solchen Fällen erhalten wir normalerweise unterschiedliche Testergebnisse, ohne den getesteten Code oder den Testcode zu ändern. Vergänglichkeit kann ein Effekt sein, wenn man sich auf Systemaufrufe verlässt oder von einem externen Signal abhängt, das nicht innerhalb des Tests gesteuert werden kann. Ein klassisches Beispiel ist die Systemuhr. Wenn ein Testszenario zu bestimmten Zeitpunkten reagieren muss, ist eine Automatisierung ohne verspottete Mitarbeiter, die die volle Kontrolle über die indirekten Eingaben in den getesteten Code haben, nur schwer zu erreichen.

2. Testumgebungen sind schwer zu initialisieren

Das Initialisieren der Testumgebung kann sehr komplex sein. Es kann eine entmutigende, wenn nicht sogar unmögliche Aufgabe sein, die tatsächlichen Mitarbeiter so zu simulieren, dass sie zuverlässige Eingaben in den getesteten Code liefern.

Komponenten hängen oft miteinander zusammen, und wenn wir versuchen, ein bestimmtes Modul zu initialisieren, wird möglicherweise die Hälfte des Systems initialisiert. Ersetzen der echten Mitarbeiter durch Eine gefälschte Implementierung reduziert die Komplexität der Initialisierung der Testumgebung.

3. Der Teststatus ist schwer zu bestimmen

In vielen Fällen muss zur Bestimmung des Testurteils der Status des Mitarbeiters überprüft werden, nachdem der Test ausgeführt wurde. Bei echten Kollaborateuren ist es oft unmöglich, da es in der Schnittstelle für echte Kollaborateure keine geeignete Zugriffsmethode gibt, um den Status nach dem Test abzufragen.

Das Ersetzen eines echten Mitarbeiters durch ein Modell behebt normalerweise das Problem, und wir können die gefälschte Implementierung mit allen Arten von Zugriffsmethoden erweitern, um das Testergebnis zu ermitteln.

4. Tests sind langsam

Es gibt Fälle, in denen eine Antwort des tatsächlichen Mitarbeiters viel Zeit in Anspruch nehmen kann. Es ist nicht immer klar, wann die Verzögerung inakzeptabel wird und wann eine Isolierung erforderlich ist. Ist eine Verzögerung von 2 Minuten in einem Testlauf akzeptabel oder nicht? Es ist oft wünschenswert, Testsuiten so schnell wie möglich ausführen zu können, möglicherweise nach jeder Codeänderung. Große Verzögerungen aufgrund von Interaktionen mit echten Mitarbeitern können dazu führen, dass Testsuiten zu langsam sind, um praktisch zu sein. Verspottungen dieser echten Mitarbeiter können um mehrere Größenordnungen schneller sein und die Ausführungszeit der Tests auf ein akzeptables Niveau bringen.

Nützliche Fragen, um festzustellen, ob verspottet werden soll oder nicht

Berücksichtigen Sie beim Schreiben eines neuen C- oder C ++ - Komponententests und bei der Entscheidung über die Verwendung von Originalmitarbeitern oder verspotteten Implementierungen die folgenden vier Fragen:

  1. Ist der echte Mitarbeiter eine Risikoquelle für die Stabilität meiner Tests?
  2. Ist es schwierig, den echten Mitarbeiter zu initialisieren?
  3. Ist es möglich, den Status des Mitarbeiters nach dem Test zu überprüfen, um den Teststatus zu bestimmen?
  4. Wie lange dauert es, bis der Mitarbeiter antwortet?

Wenn wir den Mitarbeiter gut genug kennen, um all diese Fragen zu beantworten, ist es auf die eine oder andere Weise eine einfache Entscheidung. Wenn nicht, würde ich vorschlagen, mit dem echten Mitarbeiter zu beginnen und zu versuchen, diese vier Fragen zu beantworten, während Sie gehen. In der Praxis ist dies der Ansatz, den die meisten Praktiker der testgetriebenen Entwicklung (TDD) in ihrer täglichen Arbeit anwenden. Dies bedeutet, dass Sie Ihre Testfälle sorgfältig behandeln und sorgfältig prüfen müssen, bis sie stabil sind.

Am häufigsten wird die Isolierung von Komponententests durch die Abhängigkeiten der zu testenden Einheit erschwert. Es gibt eindeutig wünschenswerte Fälle, in denen das Verspotten einer abhängigen Komponente erforderlich ist, aber auch subtilere Situationen. In einigen Fällen ist dies nicht eindeutig und hängt vom Risiko und der Unsicherheit ab, die eine Abhängigkeit in der Testumgebung aufweist.

Holen Sie sich alles, was Sie zum Erstellen, Ausführen und Verwalten von Komponententests benötigen. Siehe Parasoft C / C ++ - Test in Aktion.
Sehen Sie sich eine Demo an

Von Miroslaw Zielinski

Zu den Spezialitäten von Miroslaw, dem Produktmanager für die eingebetteten Testlösungen von Parasoft, gehören C / C ++, RTOS, statische Code-Analyse, Komponententests, Verwaltung der Softwarequalität für sicherheitskritische Anwendungen und Einhaltung der Sicherheitsstandards durch die Software.

Erhalten Sie die neuesten Nachrichten und Ressourcen zum Testen von Software sofort.