Zum Inhalt springen

Testen und Beheben von sporadisch auftretenden Bugs

Ich vermute, so ziemlich jeder Software-Entwickler unter uns hatte bereits mit ihnen zu tun. Diesen ärgerlichen und gleichermaßen nervigen Fehlern und Bugs in einer App, die nicht explizit nachvollziehbar immer an derselben Stelle oder immer nach einer bestimmten Aktion auftreten, sondern sporadisch. Es braucht eine Verkettung verschiedenster Umstände, um einen solchen Bug ab und an einmal zu provozieren. Murphy’s Gesetz folgend, kommt der Bug bei einem Test beim Kunden (ohne aktive Debugging-Werkzeuge) darüber hinaus natürlich häufiger vor als bei den eigenen Tests.

Da ich selbst in einem aktuellen Projekt dieser Tage mit genau solch einem Problem konfrontiert war, machte ich mir konkrete Gedanken darüber, wie ich derartige Bugs nicht nur erfolgreich fixen, sondern auch möglichst sicher und realistisch nachvollziehen kann, dass der Fehler tatsächlich behoben ist.

Die Krux

Habe ich es mit einem solch beschriebenen sporadischen Bug zu tun, greife ich zunächst einmal auf verfügbare Log-Files und/oder Crash Reports zurück, um die Ursache des Problems weitestgehend einzugrenzen. Darüber lässt sich dann zumindest schon einmal grob erahnen, von welcher Stelle im Code der Fehler ausgeht und mit welchen Funktionen und Abläufen er im Zusammenhang steht.

Dann wird es schwieriger.

Letzten Endes könnte ich nun hergehen und besagte Stelle untersuchen. Womöglich sticht mir direkt ein Problem ins Auge, das ich beheben kann oder ich sehe Optimierungsmöglichkeiten, um den Code effizienter und (hoffentlich) weniger fehleranfällig zu gestalten.

Doch wenn ich genau so vorgehe, sagen mir anschließende Tests der App nicht eindeutig, ob ich tatsächlich den Bug gefixt oder einfach nur den Code hier und da geändert habe. Denn das ist ja das Problem, wenn etwas nur sporadisch auftritt: Womöglich haben meine Änderungen in Bezug auf das eigentliche Problem rein gar nichts bewirkt. Ein erfolgreiches Durchlaufen meiner Tests besitzt damit keinerlei Aussagekraft. Selbst wenn die App nach meinen Änderungen nicht mehr den ursprünglichen Fehler auslöst, kann es dennoch sein, dass er noch immer vorhanden ist und ich daher der falschen Annahme erliege, ich hätte den Bug gefixt. Getreu Murphy’s Gesetzt wird der als behoben gedachte Fehler dann umgehend beim Kunden auftreten, kaum das man diesem das „Bugfix-Update“ zur Verfügung stellt. Das frustriert dann sowohl den Kunden und ist gleichermaßen peinlich und unangenehm für mich als App-Entwickler.

Was tun?

Jeder Fehler hat eine Ursache, nur ist die eben – wie schon beschrieben – nicht immer so offensichtlich. Bevor ich aber auch nur eine einzige Zeile Code zur Behebung eines Bugs schreibe, möchte ich einen oder mehrere potentielle Test-Cases entwickeln, deren Durchführung wenigstens mit einer gewissen Wahrscheinlichkeit jenen Fehler auslösen, den ich beseitigen möchte.

Ein Beispiel: Eine App stürzt in einer Optionsauswahl unregelmäßig ab. Ich teste das und wechsle zwischen verschiedenen Optionen. In einem von zehn Fällen kommt es zum Crash. Das ist zwar jetzt nicht besonders häufig, doch wenn ich reproduzierbar im Schnitt wenigstens einen Crash pro zehn Versuche bei diesem Test verursache, habe ich tatsächlich einen brauchbaren Test-Case geschaffen. Denn wenn ich nach vermeintlichem Fix des Fehlers diesen Test-Case erneut ausführe und beispielsweise nach hundert Optionswechseln keinen einzigen Crash verursacht habe, ist die Wahrscheinlichkeit sehr hoch, dem Problem auf die Schliche gekommen zu sein.

Dieses Beispiel ist sehr einfach illustriert, lässt sich aber auch auf komplexere Probleme übertragen. Es gilt schlicht und ergreifend, ein Szenario auszumachen, in dem es wenigstens zu einem gewissen Prozentsatz nachvollziehbar zu dem zu lösenden Fehler kommt. Ist das Szenario aufwendig und komplex, empfiehlt es sich, eine Art Schritt-für-Schritt-Anleitung niederzuschreiben, die in Stichpunkten ganz genau beschreibt, was zu tun ist, um den Fehler wenigstens in manchen Fällen zu verursachen. Das mag nicht perfekt sein, ist aber in jedem Fall deutlich hilfreicher und besser testbar, als ins Blaue hinein einfach los zu programmieren.

Unregelmäßigkeit eindämmen

Ziel dieses Verfahrens ist es, die Unregelmäßigkeit eines Fehlers zu eliminieren oder wenigstens einzudämmen. Ich selbst bin bei derartigen Problemen in der letzten Zeit immer so vorgegangen und bin damit sehr erfolgreich gefahren. Womöglich erschlägt man so nicht alle Probleme auf einmal, kann aber nachvollziehen, sich in die richtige Richtung zu bewegen.

Darüber hinaus helfen solche Test-Cases in jedem Fall dabei, dem eigentlichen Bug auf die Spur zu kommen. Durch die vielen sich wiederholenden Tests kann man das Problem systematisch eingrenzen und am Ende sehr explizit jene Stelle im Code und die das Problem verursachende Situation ausmachen, um anschließend einen entsprechenden Fix durchzuführen.

Wie seht ihr das? Wie geht ihr bei solch unliebsamen unregelmäßig auftretenden Bugs vor? Ich freue mich wie immer auf jeden Austausch. 🙂

Euer Thomas

Published inDevelopment

Sei der Erste der einen Kommentar abgibt

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.