Agile Modellierung mit
UML
Loading

7.5 Statecharts

Die in Kapitel 5, Band 1 definierten Statecharts haben folgende grundsätzlichen Anwendungsgebiete:

  1. Ausführbare Statecharts werden konstruktiv in Code übersetzt und finden im Produktionssystem oder als Orakelfunktion Verwendung.
  2. Für Tests einsetzbare Statecharts werden zur Überprüfung des korrekten Ablaufs eines Tests genutzt.
  3. Statecharts dienen als allgemein gültige Verhaltensspezifikationen und werden zur manuellen oder automatisierten Ableitung von Testfällen eingesetzt.
  4. Abstrakte Statecharts dienen als Dokumentation, sind aber für Tests und Codegenerierung zu abstrakt oder zu informell.2

Ein abstraktes, informelles Statechart kann durch Detaillierung und Präzisierung der darin enthaltenen Information zu einem für Tests geeigneten oder ausführbaren Statechart transformiert werden. Da in einem Statechart gleichzeitig konstruktive Elemente wie Aktionen und deskriptive Elemente wie OCL-Nachbedingungen verwendet werden können, ist auch ein kombinierter Einsatz sinnvoll. So kann ein konstruktiver Anteil eines Statecharts zur Generierung von Methoden eingesetzt werden, während zum Beispiel Zustands- und Nachbedingungen parallel dazu verwendet werden, Tests zu unterstützen und Invarianten zu generieren.

7.5.1 Ausführbare Statecharts

Ein ausführbares Statechart wird als konstruktives Modell genutzt und, wie in Abschnitt 5.4 beschrieben, direkt in Code umgesetzt. Ausführbare Statecharts besitzen typischerweise prozedurale Aktionen in Form von Java-Code. Der bei der Umsetzung entstehende Java-Code kann durch im Statechart eingetragene Zustandsinvarianten erweitert sein, die während der Testphase des Systems im Code zur Laufzeit geprüft werden. Konstruktive Statecharts eignen sich jedoch nicht als Testbeschreibung, da der Effekt einer prozeduralen Aktion nicht getestet, sondern die Aktion nur ausgeführt werden kann.

Im Prinzip können Statecharts auch als Testtreiber eingesetzt werden. Es ist jedoch ein Prinzip bei der Definition von Testtreibern, diese möglichst einfach und damit im Wesentlichen ohne verzweigte Kontrollstruktur zu entwickeln. Die lineare Struktur eines Testtreibers aber lässt ein Statechart zu einer linearen Form entarten, die auch durch ein Sequenzdiagramm dargestellt werden kann.

Interessant ist der Einsatz eines konstruktiven Statecharts als Orakelfunktion für das Testergebnis. Dies empfiehlt sich zum Beispiel, wenn der durch ein Statechart generierbare Code g für das Produktionssystem zu langsam ist und deshalb eine alternative Implementierung f realisiert wurde. Im Test wird der Testdatensatz x kopiert, auf beiden Testdatensätzen die jeweilige Funktion angewandt und das Ergebnis passend verglichen. Die Vergleichsform kann, wie in Abbildung 6.6 gezeigt, durch die Angabe eines comparator-Eintrags auch explizit definiert werden, da es eine ganze Reihe von Vergleichsmöglichkeiten gibt, etwa ob Reihenfolgen in Listen eine Rolle spielen.

Ein Black-Box-Vergleich der Ergebnisse f(x)=g(x) hat den Vorteil, dass die interne Realisierung einer Methode wesentlich von der Beschreibung durch das Statechart abweichen und damit einem Refactoring unterworfen werden kann, ohne das Statechart in seiner Funktion als Orakel zu beeinträchtigen. Bei dieser Vorgehensweise werden aber die im Statechart angegebenen OCL-Bedingungen während des Ablaufs nicht geprüft. Um das zu erreichen ist eine gleichzeitige Verwendung der konstruktiven Anteile des Statecharts für die Generierung von Produktionscode und der deskriptiven Anteile für die Generierung von Prüfungen in Tests notwendig.

Sowohl bei der Verwendung eines Statecharts als Testtreiber als auch als Orakel ist Nichtdeterminismus im Statechart kritisch. Nichtdeterministische Statecharts, also solche mit überlappenden Schaltbereichen, sind nur sinnvoll, wenn das Statechart als Ablaufbeschreibung im Test eingesetzt wird. Der Nichtdeterminismus wirkt dann als Unterspezifikation und wird durch die tatsächliche Implementierung aufgelöst.

In Abbildung 7.13 sind drei der Strategien des Auktionssystems skizziert, die gemäß der Beschreibung in Abschnitt D.2, Band 1 bei Gebotsabgabe unterschiedliche Verlängerungen (delta) in Abhängigkeit des Zeitpunkts des jeweils aktuellen Gebots bewirken.


Abbildung 7.13: Verlängerungsstrategien bei Geboten in der Auktion

Die historisch gewachsene Berechnungsstruktur für das Auktionsende nach Abgabe eines Gebots ist durch das Methoden-Statechart in Abbildung 7.14 beschrieben.3


Abbildung 7.14: Statechart berechnet neues Auktionsende

Die Berechnung ist im tatsächlichen Auktionssystem in verschiedene Methoden auf mehrere Unterklassen von TimingPolicy verteilt worden. Die in Abbildung 7.14 gezeigte ursprüngliche Modellierung der Funktionalität ist deshalb als konstruktive Implementierung nicht geeignet, kann aber aufgrund ihrer Ausführbarkeit und der inhaltlichen Korrektheit als Orakelfunktion eingesetzt werden.5

Daher können Tests unter Nutzung der modellierten Funktionalität als Orakel, wie in Abbildung 7.15, formuliert werden.


Abbildung 7.15: Test mit Methoden-Statechart als Orakelfunktion

7.5.2 Statechart als Ablaufbeschreibung

Ein Statechart, das einen Lebenszyklus deskriptiv modelliert, kann ähnlich wie ein Sequenzdiagramm zur Prüfung der Korrektheit eines Systemablaufs eingesetzt werden. Das Statechart wird also als Prädikat für einen Testfall verstanden, der in einem vorgegebenen Zustand beginnt, und dessen Interaktionen durch das Statechart überwacht werden. Damit kann ein Statechart in einem Test zusätzlich als einzuhaltendes Prädikat eingesetzt werden. Das Statechart selbst stellt allerdings keinen kompletten Testfall dar, da sowohl die Testdaten als auch der Testtreiber fehlen.

Ein zugehöriger Testablauf wird typischerweise durch ein Sequenzdiagramm beschrieben. Die beteiligten Objekte werden in der üblichen Form durch eine Objektstruktur modelliert. Einem oder mehreren dieser Objekte kann nun jeweils ein Statechart zugeordnet sein, dessen Gültigkeit zu prüfen ist. Die Objekte müssen sich dabei nicht in einem durch das Statechart vorgegebenen Startzustand befinden oder während des Testablaufs einen Endzustand erreichen. Deshalb werden für jedes Objekt zusätzlich der zu Beginn des Tests relevante Zustand und die am Ende des Tests erlaubten Zustände angegeben. Abhängig von der in Abschnitt 5.4 beschriebenen Umsetzung der Zustände durch ein Aufzählungsattribut oder Prädikate werden diese Zustände eingestellt oder geprüft. Da ein Statechart verschiedene Pfade darstellt ist eine Wiederverwendung eines Statecharts für mehrere Testfälle sinnvoll.

Abbildung 7.16 zeigt ein geegnetes Statechart und einen Testtreiber, der alternativ auch als Sequenzdiagramm dargestellt sein könnte. Weitere Testfälle können in anderen Zuständen starten oder andere Pfade nehmen, indem sie zum Beispiel Gebote (bid-Aufrufe) berücksichtigen.


Abbildung 7.16: Statechart als Lebenszyklusbeschreibung im Test

Für den Vergleich des Testablaufs mit den Transitionen und Zuständen des Statecharts ist eine Instrumentierung des Testlings in ähnlicher Form wie beim Sequenzdiagramm notwendig. Das heißt, zu Beginn und am Ende jeder Methode wird eine geeignete Instrumentierung eingebaut, um unter anderem die Zustände, Zustandsinvarianten und die Schaltbereitschaft prüfen zu können. Nicht alle im Statechart formulierbaren Eigenschaften können allerdings zur Prüfung verwendet werden. Zum Beispiel sind prozedurale Aktionen als Prüfvorgaben ungeeignet und müssen daher (falls angegeben) ignoriert werden.6

Außerdem können bei Methoden-Statecharts beziehungsweise generell die Kontrollzustände (Stereotyp controlstate) eines Statecharts nicht geprüft werden, da deren automatische Zuordnung zu Programmstellen im Code nicht möglich ist. Nur wenn die Implementierung aus dem prozeduralen Teil eines Methoden-Statecharts konstruktiv erzeugt wird, ist es möglich, den deskriptiven Teil gleichzeitig als Zusicherungen in die generierte Methode einzusetzen.

Auch für die in Abschnitt 5.5.2, Band 1 diskutierten, abschnittsweise komponierten Aktionen (Stereotyp action:sequential) ist eine Prüfung der zwischendurch gültigen Bedingungen nur bei einer konstruktiven Umsetzung des Statecharts möglich.

7.5.3 Testverfahren für Statecharts

Da Statecharts nicht einen einzelnen Ablauf, sondern eine unendliche Menge von potentiellen Abläufen für ein Objekt beschreiben, ist ein Statechart eine hervorragende Ausgangsbasis für die Entwicklung von Tests und für die Messung der Überdeckung der im Statechart modellierten Verhaltensteile. Im Gegensatz zu den bisher diskutierten Formen des Einsatzes der UML zur Testfallmodellierung, wird hier also nicht ein Diagramm für einen Testfall eingesetzt, sondern es werden aus einem Diagramm viele Testfälle abgeleitet.

Wird ein Statechart konstruktiv eingesetzt, so können die aus dem prädikativen Anteil (OCL-Bedingungen) generierten Zusicherungen als White-Box-Tests verstanden werden, da das Statechart die Implementierung darstellt. Existiert jedoch eine unabhängig entstandene Implementierung, so wird das Statechart als Spezifikation mit der Implementierung verglichen. Die Tests sind dann also Black-Box-Tests.

Es ist heute Gegenstand der Forschung aus gegebenen Statechart-Spezifikationen möglichst kompakte, aber doch vollständige Sammlungen von Testdatensätzen zu generieren, die eine Überdeckung nach einer vorgegebenen Überdeckungsmetrik erreichen. Für verschiedene Varianten flacher Automaten wurden bereits Verfahren entwickelt [PYvB96RDT95]. In Abschnitt 7.5.6 werden weiterführende Ansätze diskutiert.

Wie bereits beschrieben, ist es im generellen Fall unentscheidbar, ob eine OCL-Bedingung erfüllbar ist. Wurde eine unerfüllbare OCL-Bedingung als Vorbedingung einer Transition eingesetzt, so kann kein Pfad gefunden werden, der die zugehörige Transition beinhaltet. Eine Überdeckung aller Transitionen ist daher unmöglich. Wegen diesen Unentscheidbarkeitsproblemen gibt es für die in der UML/P definierten Statecharts wie für viele andere Varianten von Automaten kein automatisches Verfahren, das für alle Formen eine nach einem bestimmten Kriterium vollständige Testfallsammlung generiert.

Ein weiteres Problem entsteht durch den möglichen Nichtdeterminismus im deskriptiven Statechart zum Beispiel durch überlappende Schaltbereiche. Hat ein Statechart zwei Transitionen mit identischen Schaltbereichen, aber unterschiedlichen Zielzuständen, wie zum Beispiel in Abbildung 3.38(a) dargestellt, so ist es möglich, dass eine Implementierung immer nur eine Alternative auswählt. Die zweite Transition wird daher nicht gewählt und kann durch Tests nicht überdeckt werden. Auch die Überlappung von Schaltbereichen und die Bevorzugung einer Transition in einer Implementierung kann im Allgemeinen nicht automatisiert erkannt werden. Es ist daher bereits eine sinnvolle Unterstützung, wenn ein Werkzeug auf Basis vorhandener Tests misst, zu welchem Grad ein Statechart überdeckt wurde und gegebenenfalls auf Defizite hinweist.

Beiden Formen von Statecharts ist gemeinsam, dass die damit beschriebenen Transitionsfolgen eine gewisse Abstraktion der vollständigen Implementierung darstellen. So kann

  • in einer Aktionen eine komplexe Anweisungsfolge einschließlich Schleifen und Verzweigungen eingebettet sein,
  • ein einzelner Diagrammzustand einer Menge von Objektzuständen entsprechen und
  • eine OCL-Bedingung aus mehreren in eine Disjunktion zusammengefassten alternativ erfüllbaren Klauseln bestehen.

Für detaillierte Tests sollte dies berücksichtigt werden. Dies kann geschehen, indem ähnlich zu [GH99] Überdeckungsmetriken für diese Elemente mit den nachfolgend genannten Verfahren für Statecharts kombiniert werden. Das heißt also, dass nach der Entwicklung der Tests auf Basis der Statechart-Struktur diese so verfeinert werden, dass die einzelnen Bestandteile von Bedingungen und Aktionen im Statechart ebenfalls überdeckt werden. Eine Alternative ist es, die Überdeckung nicht auf Basis des Statecharts, sondern des daraus generierten Codes zu messen.

Ein weiterer Aspekt ist die Einbeziehung der Abläufe in aufgerufenen Methoden desselben oder anderer Objekte. Insbesondere, wenn eine Kompositionsbeziehung zu anderen Objekten besteht, wie im Auktionsbeispiel zwischen dem Auction- und seinen Policy-Objekten, dann wird das Verhalten der abhängigen Objekte in die Tests des Kompositums einbezogen. Dadurch wächst aber die Zahl der notwendigen Tests stark an, da verschiedene Konfigurationen von Objektstrukturen und in jeder Konfiguration jeweils die Zustandsmodelle aller Objekte des Kompositums betrachtet werden können. Eine Abschätzung zeigt schnell, ob ein Versuch einer Überdeckung praktisch durchführbar ist. Die adäquate Wahl des zu testenden Teilsystems, des gewünschten Überdeckungskriteriums und die intelligente, aber dadurch leider manuelle Auswahl von Testfällen wird daher notwendig. Bereits in [Mye79] wird vermerkt, dass erfahrene Tester auch ohne explizit angewandte Systematik durch „Error Guessing“, also dem Erraten von potentiellen Fehlerquellen, gute Ergebnisse erzielen. [PKS02] aber fordern für viele Anwendungen oder zumindest kritische Systemteile, dass „Error Guessing“ vor allem als zusätzliche Technik zu mehr systematischen Vorgehensweisen zu sehen ist.

7.5.4 Überdeckungsmetriken

In Vernachlässigung der diskutierten Komplexitäten bei Aktionen und OCL-Bedingungen lassen sich folgende Metriken für die Überdeckung eines Statecharts durch eine Testsammlung identifizieren. Diese sind als Kontrollfluss-basierte Metriken bereits in [FHNS02Bal98] genannt:

Zustandsüberdeckung
erfordert einen Testfall für jeden erreichbaren Zustand im Diagramm. Ein Testfall legt dabei eine Sequenz von Eingaben fest, die von einem Startzustand in diesen Zustand führt.
Transitionsüberdeckung
erfordert einen Testfall für jede schaltbereite Transition. Die Sequenz von Eingaben beschreibt dabei den Pfad von einem Ausgangszustand bis zur Ausführung der Transition.
Pfadüberdeckung
erfordert einen Test für jeden möglichen Pfad von einem Start- in einen Endzustand. Diese Form der Überdeckung umfasst die beiden vorhergehenden Formen. Wenn Schleifen im Automat existieren, ist die Menge der Pfade jedoch unendlich und damit eine Pfadüberdeckung praktisch undurchführbar.
Minimale Schleifenüberdeckung
ist eine reduzierte Form der Pfadüberdeckung. Dabei wird bei Schleifen darauf verzichtet, diese mehrmals zu durchlaufen. Jede im Statechart vorkommende Schleife muss jedoch mindestens einmal durchlaufen werden.

Nach [Bal98] hat die Pfadüberdeckung keine praktische Relevanz, da sie bei Schleifen sofort zu einer unendlichen und damit nicht mehr durchführbaren Aufgabe wird. Demgegenüber ist die minimale Schleifenüberdeckung ein starkes und dennoch praktikables Kriterium, das für qualitativ hochwertige Software eingesetzt werden sollte. Bei Statecharts ohne Schleifen sind jedoch beide Metriken äquivalent. Ein Problem beider Metriken ist die Frage, ob ein im Statechart erkennbarer Pfad in einer Implementierung tatsächlich durchgeführt werden kann. Wird die Vorbedingung einer Transition durch Invarianten und dem bisherigen Verlauf eines Teilpfades nie erfüllbar, so lässt sich diese Transition nicht ausführen. Dies gilt um so mehr, wenn das durch ein Statechart modellierte Objekt in einen Testling aus mehreren Objekten eingebettet und daher nicht direkt zugänglich ist. Die Umgebung kann dann auch verhindern, dass eine erforderliche Eingabesequenz auftritt. Deshalb ist die Testumgebung jeweils geeignet zu wählen.

Um die Überdeckungsmetriken bezüglich einer Testsammlung zu ermitteln, werden die Abläufe der Tests auf Basis einer Instrumentierung des Codes protokolliert.

Die ursprünglich für flache Automaten entwickelten Überdeckungsmetriken können in dieser Form auch auf Statecharts mit hierarchischem Zustandskonzept angewandt werden. Durch die in Abschnitt 5.6.2, Band 1 diskutierten Transformationen auf Statecharts ist es allerdings auch möglich, die Tests auf Basis der expandierten Hierarchie durchzuführen. Dadurch wird die notwendige Testüberdeckung verfeinert, da zum Beispiel beim Auflösen einer Transition in einen hierarchischen Zustand eine Vervielfachung dieser Transition stattfindet. Die Expansion kann also genutzt werden, um eine feinere Testüberdeckung zu erhalten.

Anhand des Statecharts aus Abbildung 7.14 werden die vier genannten Metriken in Abbildung 7.17 illustriert. Dabei werden strukturell identische, ikonisierte Formen des Ausgangsstatecharts verwendet, die den Durchlauf des Tests durch das Statechart illustrieren. Die drei Pfade der Zustandsüberdeckung reichen für die Transitionsüberdeckung nicht aus: Es muss ein vierter Ablauf hinzu genommen und zwei der vorhandenen Abläufe so modifiziert werden, dass auch die am Ende stattfindenden Transitionen überdeckt sind.


Abbildung 7.17: Testfallpfade zur Erfüllung der Metriken

Die Pfadüberdeckung erfordert 18 Testfälle. Da es sich bei dem zu testenden Statechart um ein Methoden-Statechart handelt, besteht die Eingabe aus nur einem Methodenaufruf. Gegebenenfalls werden weitere Interaktionen mit der Umgebung vorgenommen, indem Methoden der Umgebung aufgerufen werden und durch return-Werte eine weitere Steuerung des Transitionsverlaufs möglich ist. In diesem Beispiel aber hängt der Verlauf des Testfalls ausschließlich von der initialen Eingabe und der Wertebelegung in der initialen Objektstruktur ab. Um eine 100%ige Pfadüberdeckung zu erreichen, sind also 18 verschiedene Belegungen für die im Statechart benutzten Variablen zu finden. Die Invariante

       OCL  
    context Auction a inv:
  MIN_DELTA <= a.extensionTime

fordert zum Beispiel, dass die extensionTime einer Auktion immer über der minimalen Erweiterungszeit von MIN_DELTA (5 Sekunden) liegt. Deshalb sind die markierten drei Pfade nicht durchführbar. Für die anderen 15 Pfade lassen sich geeignete Testdaten finden. Zusätzlich ist es sinnvoll, Randfälle, wie die Ankunft eines Gebots exakt zum Zeitpunkt des Auktionsendes oder minimal danach, zu behandeln. Weitere Randfälle lassen sich durch die Analyse der Schaltbedingungen von Transitionen identifizieren und so weitere Tests ableiten.

Als zweites Beispiel werden die Metriken anhand des in Abbildung 7.16 dargestellen Statecharts demonstriert. Dort ist jede Transition durch einen Methodenaufruf zu steuern, die Eingabe ist also eine mehrteilige Sequenz.


Abbildung 7.18: Testfälle zur Erfüllung der Metriken

Die Möglichkeit, Statecharts durch Verwendung verschiedener Stereotypen eine unterschiedliche Semantik in Bezug auf Vervollständigung und Fehlersituationen zu geben, erfordert bei der Definition von Tests die Berücksichtigung dieser Stereotypen. Folgende Situationen und Strategien sind dabei möglich:

  1. Das Statechart ist vollständig, indem zum Beispiel ein Fehlerzustand eingeführt wurde. Dadurch existieren implizite Transitionen, die in den Fehlerzustand führen und deren Schaltbereiche alles abdecken, was nicht durch explizite Transitionen abgedeckt ist. Diese Transitionen können in die Überdeckung einbezogen werden. Da Statecharts einen zweiten Fehlerzustand für die Behandlung aufgetretener Exceptions besitzen können, ist die hier auftretende Situation analog. Es ist wieder zu entscheiden, ob und wie detailliert die Verarbeitung der Exceptions getestet werden soll.
  2. Das Statechart wurde mit completion:ignore vervollständigt. Dadurch entstehen Transitionsschleifen, die bei Transitions- und Pfadüberdeckung getestet werden können.
  3. Ein mit completion:chaos markiertes Statechart basiert auf der Annahme, dass das Statechart nur einen Teil des Verhaltens festlegt. Es beschreibt das Verhalten des Objekts bis zu dem ersten Auftreten einer Situation, in der das Statechart nicht schaltbereit ist und der Testling beliebiges Verhalten annehmen kann. Derartige Abläufe müssen nicht getestet werden.

Bei einer Vervollständigung mittels completion:ignore wird besonders offensichtlich, dass ein Test dieser zusätzlichen Transitionen für das Verhalten des mit dem Statechart beschriebenen Objekts nicht sehr wesentlich ist, da diese Transitionen in uniformer Weise generiert sind. Wesentlich interessanter ist es daher meistens, Objekte der Umgebung darauf zu testen, ob deren Umgang mit dem beschriebenen Objekt soweit korrekt ist, dass sie auf das Ignorieren eines Methodenaufrufs oder das Betreten eines Fehlerzustands ihrerseits robust reagieren. Bei der Annahme, dass ein Statechart durch die Unvollständigkeit alle erlaubten Abläufe eines Objekts beschreibt, entstehen dadurch sogar wesentliche Einschränkungen an die Umgebung, die zumindest in Form von Tests zu prüfen sind. Das kann zum Beispiel durch eine Vervollständigung mit Fehlerzustand umgesetzt werden, bei der im Fehlerzustand ein Scheitern des Tests gemeldet wird.

7.5.5 Transitionstests statt Testsequenzen

Bei den bisher diskutierten Testsequenzen wird grundsätzlich davon ausgegangen, dass als Testdatensatz das beschriebene Objekt in einem Initialzustand vorliegt. Um daher eine Transition zu testen, ist zunächst ein Pfad zu finden, der zum Quellzustand dieser Transition führt.

Die mit Abbildung 6.7 charakterisierte Grundstruktur von Testfällen zeigt, dass ein Testfall von einem beliebigen Testdatensatz ausgehen kann. Dies bedeutet, dass eine Transition eines Statecharts auch dadurch getestet werden kann, dass ein Testdatensatz gefunden wird, der dem Quellzustand der Transition entspricht und diese schaltbereit macht. Dies geht vor allem bei dem Lebenszyklus eines Objekts, bei dem ein Methodenaufruf einer einzelnen Transition entspricht und somit isoliert ausgeführt werden kann. Statt also eine Testsequenz beginnend mit einem Initialzustand zu erfordern, reicht es für einen Transitionstest aus, einen einfachen Methodenaufruf durchzuführen.

Bei einer Automatisierung der Generierung von Tests wird durch die Definition von Testdaten, die einem Quellzustand einer Transition entsprechen, das bereits in Abschnitt 7.4 diskutierte Problem umgangen, dass eine Testsequenz zu finden ist, die zu einem bestimmten Zustand beziehungsweise einer Transition führt. Stattdessen ist eine Objektstruktur zu finden, in der der Testling einem Statechart-Zustand entspricht. Es ist deshalb notwendig Diagrammzustände mit OCL-Bedingungen ausreichend genau zu charakterisieren. Sonst kann es bei diesem Ansatz vorkommen, dass ein Objektzustand für die Ausgangsdaten festgelegt wird, der im Produktionssystem nicht erreichbar ist. Bei der Suche von Objektzuständen, die einem Diagrammzustand entsprechen, sind außerdem auch die allgemein gültigen Invarianten zu beachten.

Damit ist die Suche nach Testdaten für Transitionen aus Statecharts äquivalent mit der bereits in Abschnitt 7.3.2 diskutierten Suche nach Testdaten, die die Vorbedingung einer OCL-Methodenspezifikation erfüllen. Wird ein Verfahren zur Identifikation von Testdaten, die eine OCL-Vorbedingung erfüllen, verwendet, so kann dieses Verfahren aufgrund der in Abschnitt 5.6.2, Band 1 vorgestellten Transformation von Statecharts in OCL auch für Transitionen in Lebenszyklen-Statecharts verwendet werden.

Ein Vorteil des hier skizzierten transitionsbasierten Ansatzes ist die einfache Prüfbarkeit jeder Transition, die auch in effizienter ablaufenden Tests mündet. Nachteil ist, dass nicht erkannt wird, ob ein Zustand überhaupt erreichbar ist. Von solchen Zuständen ausgehende Transitionen müssen nicht getestet werden, da sie keinen Beitrag zum Systemverhalten leisten.

Der skizzierte Ansatz ist äquivalent zur Transitionsüberdeckung, ignoriert aber die Pfade vom Startzustand bis zum Quellzustand der eigentlich durchzuführenden Transition.

7.5.6 Weiterführende Ansätze

Wie bereits erwähnt, ist es weiterhin ein Forschungsgebiet, aus automatenartigen Beschreibungstechniken mit verschiedenen Verfahren Testfälle zu ermitteln. Exemplarisch werden die folgenden Ansätze kurz skizziert, die den Fortschritt in diesem Bereich demonstrieren.

Für einfachere Varianten von zustandsbasierten Systemen ist zum Beispiel in [GH99] ein Verfahren angegeben, mit dem aus einem ausführbaren Automaten mithilfe von Model-Checking automatisierte Tests generiert werden können. Diese Tests prüfen eine Implementierung gegen den als Orakelfunktion verwendeten Automaten. Diese Automaten haben aber keine Zustandshierarchie, keinen Nichtdeterminismus und eine im Vergleich zu den hier präsentierten Statecharts eingeschränkte Form von Transitionsmarkierungen. In dem Verfahren wird eine Transitionsüberdeckung des Automaten erreicht. Model-Checking wird dabei vor allem verwendet, um Aufrufsequenzen für den Automaten zu finden, die Vorbedingungen der jeweils zu testenden Transition erfüllen. Dieses Verfahren wird außerdem auf zwei Arten verfeinert. Zum einen werden aus Disjunktionen bestehende Vorbedingungen zerlegt und damit implizit die Transitionen geteilt, um so eine Überdeckung aller Klauseln einer Disjunktion zu erreichen. Zum anderen wird eine einfache Grenzwertanalyse gemacht, indem Randvergleiche wie etwa a>=b in zwei Fälle a>b und a==b zerlegt werden.

In [FHNS02] wird ein Ansatz beschrieben, aus einem Zustandsautomaten durch Projektion eine Verringerung des Zustandsraums zu erhalten. Dadurch wird eine Überdeckung des als Projektion erhaltenen Automaten durch Tests nach den Kriterien Zustands- und Transitionsüberdeckung möglich. Allerdings hängt es von der Wahl der Projektion ab, welche Pfade durch das System wirklich getestet werden und welche Fehler nicht entdeckt werden, weil sie über mehrere der projezierten Automaten verteilt sind. Dieses Verfahren ist hilfreich, wenn man ein Objekt mit vielen Zuständen hat. In objektorientierten Systemen ist es in diesem Fall ratsam (wenn auch nicht immer möglich), durch Auslagerung von Teilfunktionalität diese Projektion bereits beim Entwurf vorzunehmen. Als Nebeneffekt entstehen mehrere Objekte, deren Zustandsraum jeweils einer Projektion entsprechen kann. Das Projektionsverfahren aus [FHNS02] bietet aber zusätzliche Flexibilität, da es überlappende Projektionen erlaubt und so überlappende Sichten für Tests zulässt.

Der Ansatz in [CCD02] diskutiert ähnlich wie hier den Einsatz einer restringierten Form der UML-Statecharts für die Gewinnung von Tests. Für die Testdaten werden ebenfalls Objektdiagramme eingesetzt. Jedoch erklären die Autoren der noch in Weiterentwicklung befindlichen Arbeit mehr die Architektur einer auf XML basierenden Werkzeugkopplung, als die Vorgehensweise aus den hierarchischen Statecharts Testfälle zu generieren.


Bernhard Rumpe. Agile Modellierung mit UML. Springer 2012