Software engineering ii
This presentation is the property of its rightful owner.
Sponsored Links
1 / 41

Software-Engineering II PowerPoint PPT Presentation


  • 60 Views
  • Uploaded on
  • Presentation posted in: General

Software-Engineering II. Objektorientiertes Testen. Themenübersicht. Objektorientierung Aspektorientierung Vorgehensmodelle UML Analyse- & Entwurfsmuster Objektorientiertes Testen Versionsverwaltung Refactoring Labor (Praktischer Teil). Unit-Testing mit JUnit.

Download Presentation

Software-Engineering II

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Software engineering ii

Software-Engineering II

Objektorientiertes Testen


Themen bersicht

Themenübersicht

Objektorientierung

Aspektorientierung

Vorgehensmodelle

UML

Analyse- & Entwurfsmuster

Objektorientiertes Testen

Versionsverwaltung

Refactoring

Labor (Praktischer Teil)


Unit testing mit junit

Unit-Testing mit JUnit

Pragmatic Unit Testing in Java with JUnit

Andrew Hunt,

David Thomas

176 Seiten

ISBN: 0-974-5140-12 (Englisch)


Objektorientiertes testen

Testen ist ein wichtiger Bestandteil des Software-Lifecycles

Testen objektorienter Software bringt verglichen mit funktionaler Programmierung einige Erschwernisse mit sich

Objektorientiertes Testen


Probleme bei der objektorientierung i

Probleme bei der Objektorientierung I

  • Nachdem die objektorientierte Software-Entwicklung begann, sich durchzusetzen, blieb objektorientiertes Testen zunächst unbeachtet

  • Es gab sogar Meinungen, dass Objektorientierung das Testen von Software vereinfacht:

„... the use of object-oriented design doesn’t change any basic testing principles; what does change is the granularity of the units tested.“ (Grady Booch)

„Both testing and maintenance are simplified by an object-oriented approach...“ (James Rumbaugh)


Probleme bei der objektorientierung ii

Im Allgemeinen die selben Anforderungen wie bei funktionaler Programmierung

Generierung von authentischen Testdaten

Validierung der Testergebnisse

Das Programm gilt als korrekt, wenn der Ist-Zustand dem spezifizierten Soll-Zustand entspricht

Probleme bei der Objektorientierung II


Unz hlige zust nde

Methoden können in objektorientierten Programmen abhängig vom Zustand der Klasse sein, welcher durch ihre Attribute geprägt wird

Ein Aufruf einer Methode kann je nach Vorgeschichte der Klasse ein beliebig differenziertes Ergebnis liefern

Eine Klasse zu 100% zu testen führt zu einer exponentiellen Steigerung der Testfälle

Es würde bei den meisten komplexen Programm-Strukturen den finanziellen Rahmen des Projekts sprengen

Unzählige Zustände


Generik und vererbung

Klassen sollten generisch und für eine große Anzahl von Anwendungsfällen geschrieben sein

Beim Testen nicht vorhersehbar, wie eine Klasse benutzt wird

Prognose der Fälle erforderlich

Durch Vererbung entstehen neue Abhängigkeiten die wiederum getestet werden müssen

Werden Fehler in Basisklassen nicht erkennt, erben alle Subklassen die Fehler von der Basisklasse

Generik und Vererbung


Automatisierte tests

Nach dem Definieren von Testfällen kann automatisiert die ganze Testsuite getestet werden

Vorteile:

Fehler, die durch Abhängigkeiten unbemerkt entstanden sind, können einfach gefunden werden

Schnelle Möglichkeit um ein System komplett auf Funktionalität zu prüfen

Verringert die Zeit für das Debuggen

Gibt Vertrauen in den Quellcode

Verbessert das Design, da schon zu Beginn Gedanken über die Verwendung (Testbarkeit) des Codes gemacht werden müssen

Voraussetzung:

Gute Code-Abdeckung der Tests

Automatisierte Tests


Generelle grunds tze

Teste alles, was schief gehen kann

Teste alles, was schief ging (Bugs)

Neuer Quellcode ist solange fehlerhaft bis man das Gegenteil bewiesen hat

Schreibe mindestens so viel Testcode wie Programmcode

Führe Tests lokal bei jedem Compilieren aus

Führe alle Tests vor dem Check-In in das Repository aus

Generelle Grundsätze


Was soll getestet werden

Regel: „Use your Right-Bicep“

R ight

B oundary

I nverse

C ross-Check

E rror-Conditions

P erformance

Was soll getestet werden?


R bicep right

Die einfachste Kondition

Teste, ob das Ergebnis richtig ist

R-BICEP - Right

int[] numbers = { 3, 1, 4, 2 };

Assert.assertEquals( 4, MaxValue( numbers ) );


R b icep b oundary

Mit Grenzwerten testen

Sonderzeichen, Umlaute

Leere oder fehlende Werte, bspw. null, Leerstring, 0

Unerwartete Werte, bspw. 10,000 als Alter

Duplikate in Listen, die keine haben dürften

Sortierte und unsortierte Werte, bpsw. für Sortieralgorithmen

Befehle nicht in erwarteter Reihenfolge ausführen

R-BICEP - Boundary


R b i cep i nverse relationship

Einige Methoden können durch die Invers-Methode verifiziert werden

Definitionsbereiche beachten

R-BICEP – Inverse Relationship

double x = MyMath.Sqrt( 4.0 );Assert.assertTrue( Math.abs( 4.0 - x*x ) < 0.0001 );


R bi c ep c ross check

Manche Ergebnisse können mit alternativen Implementierungen geprüft werden

R-BICEP - Cross-Check

double x = MyMath.Sqrt( 100 );double y = Math.Sqrt( 100 );

Assert.assertTrue( Math.abs( x – y ) < 0.0001);


R bic e p e rror conditions

Mit ungültigen Eingaben testen

Exceptions provizieren und erwarten

Umgebungsprobleme testen

Speicherüberlauf

Festplatte voll

Systemuhrzeit inkonsistent (manipuliert)

Dauerhafter oder temporärer Netzwerk-Abbruch

Unzureichende Benutzer-Rechte

Systemauslastung

Eingeschränkte oder sehr hohe Bildschirmauflösung

R-BICEP – Error-Conditions


R bice p p erformance

Bei manchen Methoden sind Performance-Analysen möglich

R-BICEP- Performance

long start = System.currentTimeMillis();

this.sortList();

long end = System.currentTimeMillis();

Assert.assertTrue( ( end - start ) < 1.0 );


Gute tests

A utomatic

T horough

R epeatable

I ndependant

P rofessional

Gute Tests


A trip a utomatic

Unit-Tests müssen automatisch ablaufen können

Starten der Tests

Prüfen der Ergebnisse

Es darf kein manueller Schritt notwendig sein

Datenbank-Zeilen einfügen

Dateien erstellen

A TRIP - Automatic


A t rip t horough

Teste alles, bei dem es wahrscheinlich ist, dass es schief geht

Teste zumindest die wichtigsten Eigenschaften

Grenzwerte

Fehlende und ungültige Werte

Die Konsequenz, mit der getestet wird, muss für jedes Projekt neu entschieden werden

A TRIP - Thorough


A t r ip r epeatable

Tests sollten

immer wieder ausführbar sein

in jeder Reihenfolge ausführbar sein

immer die gleichen Ergebnisse liefern

A TRIP - Repeatable


A tr i p i ndependant

Tests sollten

Klein und sauber sein

Unabhängig von der Umgebung sein

Unabhängig von einander sein

Teste immer nur eine Sache zu einer Zeit

A TRIP - Independant


A tri p p rofessional

Tests sind richtiger Quellcode

Sie müssen deshalb nach den selben professionellen Standards wie der Programmcode

geschrieben sein

gewartet werden

A TRIP - Professional


Dependency injection 1

Dependency Injection 1

  • Klassen mit direkten Abhängigkeiten sind schwer testbar

  • Sie können nicht einzeln, sondern nur als System getestet werden

Zu testende Klasse


Dependency injection 2

Dependency Injection 2

  • Die abhängige Klasse bekommt eine Referenz auf ihre Delegate-Klasse gesetzt

  • Der Typ der Referenz ist dabei nicht die Klasse selbst sondern ein Interface*

Zu testende Klasse


Dependency injection 3

Dependency Injection 3

  • Im Test-Code kann nun der Klasse ein Delegate gesetzt werden, welches dasselbe Interface implementiert, sich jedoch nach von der Test-Klasse vorgegebenen Regeln verhält

  • Diese Alternativ-Klassen nennt man Mock-Klassen (Mock = Attrappe)


Frameworks mockito

[Frameworks] Mockito

  • Mocking-Framework

  • Stellt Mocks zur Verfügung

Class2 delegate = Mockito.mock(Class2.class);

Mockito.when(delegate.foo(10)).thenReturn(“String“);new Class1().setDependancy(delegate);

Mit verify kann später geprüft werden, ob ein Aufruf stattfand:

Mockito.verify(delegate).foo(10);


Frameworks spring i

[Frameworks] Spring (I)

  • Dependancy Injection Framework

    @Resource-Annotation

class Class1{

@Resource

private iClass2 dependancy;

}

  • Dependancies sind konfigurierbar

...

<bean id="dependancy" class="Class2“ />

...


Frameworks spring ii

[Frameworks] Spring (II)

  • Komplexe Instanziierungen möglich

...

<bean id="class1" class="Class1">

<property name="dependancy" ref=“iClass2" />

</bean>

<bean id=“iClass2" class="Class2">

<constructor-arg value="Hallo Welt" />

</bean>

...

Entspricht:

iClass2 class2 = new Class2("Hallo Welt");

Class1 class1 = new Class1();

Class1.setDependancy(class2);

Vorteil:

Variable Parameter und Abhängigkeiten sind konfigurierbar!

(=austauschbar)


Dependency injection 4

Dependency Injection 4

  • OOP Design Pattern

  • Einsatzgebiete nicht nur auf OOP Testing beschränkt

  • Immer dann ideal, wenn direkte Abhängigkeiten vermieden werden sollen


Werkzeug junit

In Eclipse und NetBeans

Ohne Eclipse:

http://www.junit.org/

In Eclipse das JUnit-Library einbinden

Projekt-Properties

Java Build Path

Libraries

Werkzeug JUnit


Testfall erstellen

Neue (Test-)Klasse erstellen

vorzugsweise in einem separaten Package für unit-tests

Neue Methode erstellen, die einen Test durchführt

Methode mit der Annotation @org.junit.Test versehen

Package Explorer:

Rechtsklick auf Klasse

Run as

JUnit test

Testfall erstellen


Aufbau eines tests

Aufbau eines Tests

package unittest.test;

publicclass SimpleTest

{

@org.junit.Test publicvoid testcase()

{

// …

}

}

Testklasse

Test-Methode

Test-Code


Assertions

Die Klasse org.junit.Assert bietet statische Funktionen, um Tests durchzuführen

Assert.assertTrue( boolean )

Test bestanden, wenn der übergebene Wert true ist

Assert.assertFalse( boolean )

Test bestanden, wenn der übergebene Wert false ist

Assert.assertEquals( Object, Object )

Test bestanden, wenn beide übergebene Objekte „gleich“ sind (Bsp.: Strings mit gleichem Inhalt)

Assert.assertSame( Object, Object )

Test bestanden, wenn es sich bei den übergebenen Objekten und die selbe Instanz handelt

Assert.assertNotNull( Object )

Test bestanden, wenn das übergebene Objekt nicht null ist

Assertions


Beispiel testfall

Beispiel-Testfall

package unittest.test;

import org.junit.Assert;

publicclass SimpleTest {

@org.junit.Test publicvoid testcase()

{

Assert.assertTrue( Math.PI > 3 ); // will succeed

}

@org.junit.Test publicvoid badTestcase()

{

Assert.assertTrue( Math.PI < 3 ); // bound to fail

}

}


Ausf hren des tests

Ausführen des Tests

Start des Testvorgangs


Test ergebnisse

Test-Ergebnisse

Indiziert, dass alle Testfälle erfolgreich waren

Ein Testfall ist fehlgeschlagen


Setup teardown

Benötigen alle Tests einer Testklasse gemeinsame Ressourcen, können diese in einer setUp-Methode alloziert werden

Dazu wird die Methode mit der Annotation @org.junit.Before versehen

Ressourcen, die in der setUp-Methode alloziert werden, können in der tearDown-Methode wieder freigegeben werden

Die Methode wird mit der Annotation @org.junit.After versehen

Die beiden Methoden werden vor und nach jedem Test ausgeführt

setUp & tearDown

@org.junit.Before public void setUp(){

this.dbconnection.open();

}

@org.junit.After public void tearDown() {

this.dbconnection.close();

}

@org.junit.Test public void testcase1()

{ this.dbconnection.…; }

@org.junit.Test public void testcase2()

{ this.dbconnection.…; }


Einfachere annotations

Einfachere Annotations

  • Durch den Import von org.junit.* bzw. den benötigten Elementen kann man auf die Paketnamen verzichten

import org.junit.*;

class MyTest

{

@Before public void setUp(){

}

@Test public void testcase1()

{ … }

}


Exceptions

Exceptions, die während des Tests auftreten werden von JUnit abgefangen und bei der Auswertung als Fehler ausgewiesen

Möchte man explizit testen, ob eine spezielle Exception geworfen wird, kann man das durch die Erweiterung der Annotation erreichen:

Exceptions

@Test(expected= [Exception-Name].class)

Beispiel:

@Test(expected= IndexOutOfBoundsException.class) publicvoid testException()

{

new ArrayList<Object>().get(0); // wirft Exception

}


Tools code coverage

Analysieren, welche Code-Stellen durch Unit-Tests bereits abgedeckt sind

Einfaches Auffinden von ungetestetem Code

„Nur getesteter Code kann als funktionsfähig angesehen werden!“

Beispiel: Clover

[Tools] Code-Coverage


  • Login