Confidence-from-Use bei Medizinprodukten
Anbieter zum Thema
Das Testen wird heute nicht nur als Demonstration der korrekten Funktion eines Systems gesehen. Es dient auch zur Ermittlung des auf Erfahrungswerten aus der Anwendung beruhenden Vertrauensniveaus.

Testen spielt für softwarebasierte Medizingeräte heute eine ganz andere Rolle als noch vor zehn Jahren. Der risikobasierte Ansatz aus der IEC 29119 „Software Testing“ (2013) spiegelt eine Veränderung wider, die explizit oder implizit bereits von den meisten Testgruppen übernommen wurde. Heutzutage sieht man das Testen nicht mehr nur als Demonstration der korrekten Funktion des Systems, sondern als Mittel zur Erzeugung von Nachweisen für die sogenannte Confidence-from-Use – das auf Erfahrungswerten aus der Anwendung beruhende Konfidenzniveau.
Beim Verifizieren eines medizinischen Embedded-Geräts, in dem Software eingesetzt wird, steht man vor einer zentralen Herausforderung: Der Zustandsraum eines laufenden Programms ist so groß, dass eine hundertprozentige Testabdeckung schlechterdings unmöglich ist. Jeder Versuch, das Programm testen zu wollen, kann daher nicht mehr als eine sehr kleine statistische Stichprobe sein.
Einer der Fallstricke, der explizit in der IEC TIR80002-1 (Medizingerätesoftware – Leitfaden zur Anwendung der ISO 14971 auf Medizingerätesoftware) erwähnt wird, besteht gerade darin, sich auf „Testen als Mittel zur Risikokontrolle“ zu verlassen, obwohl eine hundertprozentige Testabdeckung unmöglich ist.
Der Zustandsraum der Software
Es lässt sich relativ einfach zeigen, dass ein modernes Embedded-Betriebssystem (zum Beispiel das QNX Neutrino OS oder Embedded Linux) mehr als 10300 mögliche interne Zustände aufweist. Um dies in Relation zu setzen: Die Eddington-Zahl (die Anzahl der Protonen im beobachtbaren Universum) beträgt rund 1080. Zudem läuft das OS auf einem Prozessorchip mit internen Daten- und Befehlscaches, die sich zu jedem Zeitpunkt in vielen verschiedenen Zuständen befinden können, die allesamt für den Benutzer unsichtbar sind und vom Tester nicht reproduziert werden können.
Und dann ist da noch das eigentliche Anwendungsprogramm. Betrachten wir nun das folgende Programm, das die durchaus überschaubare Aufgabe hat, die Summe aus zwei und zwei zu berechnen und die Antwort – etwa eine einem Patienten zu verabreichende Dosis – auszugeben:
#include <stdio.h>
int main()
{
char x;
x = 2 + 2;
printf("%d\n", x);
return 0;
}
Als Entwickler mag man geneigt sein, dieses Programm als reichlich trivial einzustufen. Das ist aber gar nicht so. Das Programm wird mit der Bibliothek libc verlinkt, welche die printf-Funktion bereitstellt, und es wird auf dem besagten OS ausgeführt, welches selbst schon mindestens 10300 mögliche Zustände aufweist. Um zu beweisen, dass das Ergebnis von 2 + 2 unter allen Umständen korrekt berechnet wird, müssten wir das Programm in jedem einzelnen dieser Zustände testen, was offenkundig unmöglich ist.
Nun habe ich dieses Programm gerade 1000 Mal auf meinem Linux-Laptop getestet, und die Antwort lautete jedes Mal „4“. Vom Standpunkt der Testabdeckung ist dies ohne Bedeutung. So können wir keine Aussage darüber treffen, ob gegebenenfalls während eines dieser Tests der Timer-Interrupt des Computers mit der Anweisung _Lockfileatomic(stdout); in printf zusammenfiel, oder ob noch ein weiterer Thread versuchte, stdout zur gleichen Zeit zu blockieren wie unser Programm – all das würde das Programm sicherlich in unterschiedliche Zustände versetzen. Was, wenn ein anderer Prozess stdout blockiert hat und in diesem Prozess ein Fehler auftritt, bevor er seine Verarbeitung vollendet? Würde unsere Berechnung nun für immer auf die Freigabe von stdout warten? Dies wäre eine Bedingung, die während des Testens nur sehr schwierig herzustellen ist, die aber eine der Testbedingungen sein sollte.
Warum testen wir eigentlich Software?
Egal, wie wir dieses mehr oder weniger Programm, das die Dosis 2 + 2 berechnet, testen: Angesichts der hohen Anzahl möglicher Zustände kratzen wir lediglich an der Oberfläche seines Zustandsraums. Warum testen Firmen ihre Software dann überhaupt?
Eine Firma, die Software testet, setzt ja quasi teures Personal dafür ein, weit weniger als 10 bis 100 Prozent der möglichen Zustände des Systems zu untersuchen. Ist das ein effektiver Einsatz der Firmenressourcen?
Die Norm ISO 13849 geht das Problem aus einer anderen Richtung an: „Wenn eine Validierung auf analytischem Wege nicht zum Abschluss gebracht werden kann, müssen Tests vorgenommen werden, um die Validierung zu komplettieren. Testen stellt immer eine Ergänzung zur analytischen Untersuchung dar, und oft ist es eine notwendige Ergänzung.“
Mit anderen Worten: Testen ist das, was wir tun, wenn andere Methoden der Validierung versagen.
Dennoch hat sich Testen als wirksames Mittel erwiesen, und Medizintechniknormen wie die IEC 62304 schreiben vor, dass getestet werden muss: „Integrierte Softwareelemente sind vom Hersteller gemäß dem Integrationsplan zu testen, und die Ergebnisse sind zu dokumentieren.“
Woher kommt diese Dichotomie zwischen dem Standpunkt „Testen ist wegen der Größe des Zustandsraums nutzlos“ und der gegenteiligen Position „Testen ist nützlich und kann Fehler aufdecken“? Weil das, was wir herkömmlich als Testen bezeichnen, in Wirklichkeit das Erlangen von Confidence-from-Use (Vertrauen in Erfahrungswerte aus der Anwendung) ist. Welche Antworten würden wir lieber von einem Mitglied einer Testgruppe auf die Frage nach seiner Arbeit hören?
„Ich betreibe eine Art von digitaler Homöopathie: Ich stelle die Bedingungen her, um 0,00000000000000000000000000000000000000001 Prozent der möglichen Zustände des Systems durchzuspielen.“
Oder:
„Ich nutze meine Erfahrung, um realistische Bedingungen zu ermitteln, die das System unter Stress setzen, und stelle dann diese Situationen her, um auf diesem Wege unsere Confidence-from-Use zu erhöhen. Kürzlich legte man mir zum Beispiel ein Programm vor, das 2 + 2 berechnet und das Ergebnis als Dosis anzeigt. Ich schaute mir das Programm an und sah sofort, dass es über eine enorme Anzahl möglicher Zustände verfügt. Ich verließ mich auf mein Urteilsvermögen als Ingenieur und wählte gezielt Test-Cases aus. Zum Beispiel führte ich mehrere Instanzen des Programms parallel aus, um einen möglichen stdout-Deadlock abzuprüfen. Dadurch konnte ich die Confidence-from-Use ganz wesentlich erhöhen, ohne in den enorm großen Zustandsraum abtauchen zu müssen.“
Der letztgenannte Ansatz entspricht dem Gedanken eines risikobasierten Testens aus der Norm ISO/IEC 29119 für Software-Tests aus dem Jahre 2013:
„Es ist unmöglich, ein Softwaresystem erschöpfend zu testen. Das Testen ist daher eine stichprobenartige Aktivität. Es gibt zahlreiche Testkonzepte (...), die bei der Wahl einer geeigneten Stichprobe für den Test helfen. Diese werden (...) in dieser Norm behandelt. Eine wichtige Grundannahme dieser Norm ist der Gedanke, unter den gegebenen Einschränkungen und im gegebenen Kontext mit einem risikobasierten Ansatz den bestmöglichen Test durchzuführen.“
Änderungen und ihre Auswirkungen
Angesichts des enorm großen Zustandsraums unseres 2 + 2-Programms überrascht es nicht, dass jede Modifikation sein Verhalten komplett verändern kann.
Angenommen, ein neuer Kunde muss den Wert von 2 + 3 kennen. Können wir eine äußerlich einfache Änderung an dem Programm vornehmen und uns weiterhin auf unsere Erfahrungswerte verlassen, die wir mit der 2 + 2-Version gesammelt haben? Sicherlich gibt das Programm beim Testen erst einmal durchgängig an, dass 2 + 3 = 5 ist. Aber das könnte auch nur Zufall sein.
Schließlich liefern wir die 2 + 3-Version aus, und nach einigen Jahren steigt unser Konfidenzniveau. Wenn nun ein Kunde die Summe 2 + 127 berechnen möchte, dann wissen wir schon, was wir zu tun haben. Oder etwa nicht?
Das Ergebnis 2 + 127 = -127 (statt 129) sollte uns daran erinnern, dass jede Änderung, egal wie trivial sie auch sein mag, den Ablauf des Programms grundsätzlich beeinflussen und dadurch alle in der Vergangenheit gesammelten Erfahrungswerte ungültig machen kann.
Angesichts der Anzahl möglicher Zustände von Softwaresystemen liegt die Frage auf der Hand: „Warum funktioniert eigentlich überhaupt jemals irgendetwas?“ Wir hören zwar oft von softwarebasierten Systemen, die ausfallen. Dennoch funktionieren die meisten solchen Systeme völlig korrekt.
Eine Erklärung liefert möglicherweise eine Erkenntnis aus dem Gebiet des kombinatorischen Testens (siehe Introduction to Combinatorial Testing, Kuhn, Kacker und Lei [ISBN 978-1-4665-5229-6]): Die meisten Systeme hängen von einer großen Anzahl N von Parametern ab. Jeder dieser Parameter hat eine Anzahl v möglicher Zustände. In der Praxis sind Tests mit allen Kombinationen einer wesentlich kleineren Anzahl von Parametern M<<N ein effektives Mittel zum Aufdecken von Problemen. Mehr noch, es gibt zwar keinen geschlossenen Ausdruck für die Anzahl der benötigten Parameter, aber es ist bekannt, dass diese Anzahl mit vM log(N) ansteigt. Ein logarithmisches Wachstum mit log(N) also – das macht Mut.
Es ist nicht klar, ob dieser Zusammenhang eine rein empirische Beobachtung ist, oder ob er in den grundlegenden Eigenschaften von Softwaresystemen begründet ist. So oder so lässt sich folgern, dass ein großer Teil des Verhaltens von Software mit einer relativ kleinen Anzahl von Interaktionen zwischen den Umgebungsbedingungen verknüpft ist. Das bedeutet, dass mit „angemessener Umsicht“ die Confidence-from-Use eines im Einsatz erprobten Systems auf ein modifiziertes System übertragen werden kann.
Das Problem an dieser Stelle ist das Fehlen einer theoretischen Erläuterung des Begriffs „angemessene Umsicht“. Um den signifikanten Unterschied zwischen einer Änderung von char x = 2 + 2 in char x = 2 + 3 und einer Änderung von char x = 2 + 2 in char x = 2 + 127 zu erkennen, ist menschliches Wissen und Erfahrung erforderlich.
Zusammenfassung und Ausblick
Wir können nie beanspruchen, unsere softwarebasierten Medizingeräte vollständig getestet zu haben. Auch dürfen wir Erfahrungswerte bezüglich der Confidence-from-Use, die wir mit einer Version eines Systems gesammelt haben, nicht ungeprüft auf eine andere Version übertragen, auch wenn diese nur geringfügig verändert wurde.
Andererseits ist Testen angesichts des Zustandsraums eines Softwaresystems keine wissenschaftliche Disziplin mehr – es ist einfach ein Weg, ein Maß für die Confidence-from-Use zu erhalten. Das heißt, dass wir Confidence-from-Use-Ergebnisse nicht außen vor lassen müssen, sondern vielmehr zu definieren haben, auf welcher Basis wir Confidence-from-Use-Werte unterschiedlicher Systeme statistisch so kombinieren können, dass etwas Vertretbares dabei herauskommt.
* Chris Hobbs ist Senior Developer für Safe Systems bei QNX Software.
(ID:46495749)