komponententests und testabdeckung

49
Komponententests und Testabdeckung Christian Baranowski 1

Upload: christian-baranowski

Post on 24-Dec-2014

209 views

Category:

Technology


0 download

DESCRIPTION

Komponententests und Testabdeckung

TRANSCRIPT

Page 1: Komponententests und Testabdeckung

Komponententests und Testabdeckung

Christian Baranowski���1

Page 2: Komponententests und Testabdeckung

Komponenten Test

• Testbasis (Was ist die Grundlage für die Testfälle) • Anforderungen an die Komponente • detaillierter Entwurf • Code

• Testobjekte (SUT = System Under Test): • Komponenten • Programme • Datenumwandlung/Migrationsprogramme • Datenbankmodule

���2

Page 3: Komponententests und Testabdeckung

Vier Phasen Test (Four-Phase Test)

Setup

Verify

Teardown

Exercise

SUT

Fixture1

2

3

4

���3

Quelle: XUnit Test Patterns - Gerard Meszaros

Page 4: Komponententests und Testabdeckung

JUnit 3.X Design

+ run(TestResult)

«interface»Test

+ run(TestResult)+ runTest()+ setUp()+ tearDown()

TestCase+ run(TestResult)+ addTest(Test)

TestSuite

+ setUp()+ testMyTest()+ tearDown()

MyTest

TestResult

Assert

���4

Page 5: Komponententests und Testabdeckung

JUnit 3 Examplepublic class CalcTest extends TestCase { ! Calc calc; protected void setUp() throws Exception { calc = new Calc(); } ! protected void tearDown() throws Exception { calc = null; } ! public void testSum() { int sum = calc.sum(); assertEquals(0, sum); } !}

���5

Page 6: Komponententests und Testabdeckung

JUnit 4.X Design+ getDescription()

«interface»Describable

Description

+ getDescription()+ run(RunNotifier)

Runner

+ getDescription()+ run(RunNotifier)

ParentRunner

+ filter(Filter)

«interface»Filterable

+ sort(Sorter)

«interface»Sortable

TestClass

BlockJUnit4ClassRunner

+ setup()+ myTest()+ teardown()

MyTest

Assert

«interface»@Before

«interface»@Test

«interface»@After

«run»

«static import» «use»

���6

Page 7: Komponententests und Testabdeckung

JUnit 4 Exampleimport static org.junit.Assert.*; import org.junit.*; !public class CalcTest { Calc calc; @Before public void setup() { calc = new Calc(); } @Test public void sum() { assertEquals(0, calc.sum()); } @After public void teardown() { calc = null; } }

���7

Page 8: Komponententests und Testabdeckung

JUnit3 Test Exceptions

try { sut.sort(null); fail("NPE was expected!"); } catch(NullPointerException exp){ assertTrue(true); }

���8

Page 9: Komponententests und Testabdeckung

JUnit4 Test Exceptions

@Test(expected = NullPointerException.class) public void sort_NullPointerException() { sut.sort(null); }

���9

Page 10: Komponententests und Testabdeckung

JUnit4 Test Exceptions

@Rule public ExpectedException thrown= ExpectedException.none(); @Test public void testSort_NullPointerException() { thrown.expect(NullPointerException.class); thrown.expectMessage("The values should not be null."); sut.sort(null); }

���10

Page 11: Komponententests und Testabdeckung

JUnit4 Rulespublic class IgnoreRule implements MethodRule {! @Retention(RetentionPolicy.RUNTIME) public static @interface IgnoreTest {}! @Override public Statement apply(final Statement base,

final FrameworkMethod method, Object target) { return new Statement() { @Override public void evaluate() throws Throwable { if (method.getAnnotation(IgnoreTest.class) == null) { base.evaluate(); } } }; }}

���11

Page 12: Komponententests und Testabdeckung

JUnit4 Ignore Rule Test

@Rule public IgnoreRule ignoreRule = new IgnoreRule(); @Test @IgnoreTest public void failingTest() { throw new RuntimeException("Not Implement"); }

���12

Page 13: Komponententests und Testabdeckung

JUnit4 Runner (Parametrisierter Test)@RunWith(Parameterized.class) public class SorterTest { ! @Parameters public static Iterable<Object[]> data() { return Arrays.asList(new Object[][] {{ new Integer[] { 5, 4, 3 }, new Integer[] { 3, 4, 5 } }}); } ! public SorterTest(Integer[] values, Integer[] expected) { this.values = values; this.expectedValues = expected; }

���13

Page 14: Komponententests und Testabdeckung

Strukturorientierter Test

���14

Page 15: Komponententests und Testabdeckung

Strukturorientierter Test (White-Box Verfahren)

Komponentenebene • Struktur der Softwarekomponente • Anweisungen • Entscheidungen • Zweige oder einzelne Pfade

Integrationsebene • Aufrufgraph oder Sequenzdiagramm

���15

Page 16: Komponententests und Testabdeckung

„Als Testabdeckung bezeichnet man das Verhältnis an tatsächlich getroffenen Aussagen eines Tests gegenüber den theoretisch möglich treffbaren Aussagen bzw. der Menge der gewünschten treffbaren Aussagen.“ - Wikipedia

Testabdeckung

���16

Page 17: Komponententests und Testabdeckung

Testabdeckungboolean  aAndbOrC(boolean  a,  boolean  b,  boolean  c)  {            return(a  &&  b)  ||  c;}

Erwartet a b c

false false false false

true false false true

false false true false

true false true true

false true false false

true true false true

true true true false

true true true true

���17

Page 18: Komponententests und Testabdeckung

Vollständige Testabdeckung

„Eine vollständige Testabdeckung stellt eine Ausnahme dar, weil die Anzahl möglicher Testfälle sehr schnell ungeheuer groß wird (durch kombinatorische Explosion). Ein vollständiger Funktionstest für eine einfache Funktion, die zwei 16-Bit-Werte als Argument erhält, würde schon 2^(16+16), also ca. 4 Milliarden Testfälle bedeuten, um die Spezifikation vollständig zu testen.“ - Wikipedia

���18

Page 19: Komponententests und Testabdeckung

Flussdiagramm (flowchart)

     boolean  aAndbOrC(      boolean  a,  boolean  b,        boolean  c)  {        boolean  result  =  false;            if(A  &&  B)  {            result  =  true;        }        else  if(C)  {            result  =  true;        }      else  {            result  =  false;        }        return  result;  }  

result = false

Start

return result

A & B result = true

C result = true

result = false

���19

Page 20: Komponententests und Testabdeckung

Vereinfachtes Flussdiagramm

boolean  aAndbOrC(      boolean  a,  boolean  b,        boolean  c)  {        boolean  result  =  false;            if(a  &&  b)  {            result  =  true;        }        else  if(c)  {            result  =  true;        }      else  {            result  =  false;        }        return  result;}

a && b

c

false

true

true

���20

Page 21: Komponententests und Testabdeckung

Anweisungsüberdeckung (Statement Coverage)

a && b

c

false

true

true Erwartet a b c

true true true false

���21

Page 22: Komponententests und Testabdeckung

Anweisungsüberdeckung (Statement Coverage)

a && b

c

false

true

true Erwartet a b c

true true true false

true false false true

���22

Page 23: Komponententests und Testabdeckung

Anweisungsüberdeckung (Statement Coverage)

a && b

c

false

true

true Erwartet a b c

true true true false

true false false true

false false true false

100 % Anweisungsüberdeckung

���23

Page 24: Komponententests und Testabdeckung

Testabdeckung

int  sum(int  values[],  int  offset){            int  result  =  0;            for  (int  value  :  values)  {                  if(offset  >  0){                      if(offset  <  value)                            result  +=  offset;                  }                  result  +=  value;            }            return  result;  }

���24

Page 25: Komponententests und Testabdeckung

Testabdeckung

result = 0

for(value : values)

offset > 0 offset < value

result += offset

result += value

return result

Erwartet values offset

3 [2] 1

100 %Anweisungs- überdeckung

���25

Page 26: Komponententests und Testabdeckung

Zweigabdeckung (Branch Coverage)

result = 0

for(value : values)

offset > 0 offset < value

result += offset

result += value

return result

Erwartet values offset

3 [2] 1

���26

Page 27: Komponententests und Testabdeckung

Zweigabdeckung (Branch Coverage)

result = 0

for(value : values)

offset > 0 offset < value

result += offset

result += value

return result

Erwartet values offset

3 [2] 1

2 [2] 0

���27

Page 28: Komponententests und Testabdeckung

Zweigabdeckung (Branch Coverage)

result = 0

for(value : values)

offset > 0 offset < value

result += offset

result += value

return result

Erwartet values offset

3 [2] 1

2 [2] 0

2 [2] 2

Merke: 100% Zweigabdeckung schließt 100% Anweisungsüberdeckung ein!!!

���28

Page 29: Komponententests und Testabdeckung

Entscheidungsüberdeckung (Term Coverage)boolean  aAndbOrC(      boolean  a,        boolean  b,        boolean  c)  {            if((a  &&  b)  ||  c)  {                return  true;        }  else  {                return  false;        }}

Erwartet a b c

true true true false

true false false true

false false true false

Merke: 100% Entscheidungsüberdeckung schließt 100% Zweigabdeckung ein!!!

���29

Page 30: Komponententests und Testabdeckung

Überblick kontrollflussorientierten Testverfahren (Überdeckungstests)

���30

Page 31: Komponententests und Testabdeckung

Anweisungsüberdeckung

int result = 0

return result

each(values)

result += offset

offset > 0

result += value

offset < value

���31

Page 32: Komponententests und Testabdeckung

Zweigabdeckung

int result = 0

return result

each(values)

result += offset

offset > 0

result += value

offset < value

���32

Page 33: Komponententests und Testabdeckung

Entscheidungsüberdeckungint result = 0

return result

each(values)

result += offset

offset > 0

result += value

offset < value

���33

Page 34: Komponententests und Testabdeckung

Schleifenüberdeckung (Loop Coverage)

int result = 0

return result

each(values)

result += offset

offset > 0

result += value

offset < value

Schleife wird:- keinmal- genau einmal- mehr als einmaldurchlaufen

���34

Page 35: Komponententests und Testabdeckung

Pfadüberdeckungstest (Path Coverage)

Pfadüberdeckungstest werden alle möglichen Pfade betrachtet. !Pfade in Schleifen: n = Anzahl Schleifendurchläufe m = Anzahl der Pfade in der Schleife P = m(n)+ m(n-1)+ m(n-2) + … + m0 !Beispiel: max(values) = 5 P = 35 + 34 + 33 + 32 + 31 + 1 = 364 243 + 81 + 27 + 9 + 3 + 1 = 364 !Bei Schleifen ergeben sich sehr viele Pfade ⇒ kombinatorische Explosion.

A

for(values)

B D

EC

F

���35

Page 36: Komponententests und Testabdeckung

Pfadüberdeckungstest

A

for(values)

B

C

F

A

for(values)

B D

C

F

A

for(values)

B D

EC

F

max(values) = 5 max(values) = 4 max(values) = 6

���36

P = 15+14+13+12+11+10

P = 6

m = 1

P = 24+23+22+21+20

P = 31

m = 2

P = 36+35+34+33+32+31+30

P =1093

m = 3

Page 37: Komponententests und Testabdeckung

Pfadüberdeckungstest

def n = 5 def loopPaths = ['BC', 'BDC', ‚BDEC'] !def pathCount = 1 def continuous = [] def pathTestCases = [] (1..n).each { continuous.add(Collections.nCopies( it, loopPaths )) } continuous.each { def combinations = it.combinations() def paths = combinations.size() pathCount += paths pathTestCases.addAll(combinations) } pathTestCases.eachWithIndex { test, nr -> println "${nr + 1} \t ${test}" }

Algorithmus Loop Paths (Groovy):

���37

Page 38: Komponententests und Testabdeckung

Komponententests für echte Klassen

���38

Page 39: Komponententests und Testabdeckung

Testen ohne Abhängigkeiten

«component»SUT

«component»DOC

depended-on component

*

Test

*

���39

Page 40: Komponententests und Testabdeckung

Testen ohne Abhängigkeitenpublic class Calc { ! private int result = 0; ! private Cache cache = new Cache(); ! public void add(int a) { if (a < 0) throw new IllegalStateException(); String stmt = String.format("%d + %d", result, a); Integer cachedResult = cache.get(stmt); if (cachedResult != null) result = cachedResult; else cache.put(stmt, result += a); } ! public int sum() { return result; } }

���40

Page 41: Komponententests und Testabdeckung

Testability (Prüfbarkeit)

public class Calc { ! private int result = 0; ! // DOC Cache cache = new Cache(); …

// DOC private Cache cache = new Cache(); public void setCache(Cache cache) { this.cache = cache; }

Package Visible Dependencies

Setters for Dependencies

���41

Page 42: Komponententests und Testabdeckung

Test Doubles

���42

Page 43: Komponententests und Testabdeckung

Test Doubles

Test Double

Fake Object

Test Stub

Mock Object

Test Spy

DummyObject

���43

Quelle: XUnit Test Patterns - Gerard Meszaros

Page 44: Komponententests und Testabdeckung

Test Stub

Setup

Verify

Teardown

Exercise

Stub !

!

Create

Install

Return Values

Indirect Inputs

SUT

���44

Quelle: XUnit Test Patterns - Gerard Meszaros

Page 45: Komponententests und Testabdeckung

Stubbing with Mockitoclass Calc { Cache cache; int plus(int a, int b) { Object cachedValue = cache.get(a + "+" + b); if(cachedValue != null) return (Integer) cachedValue; return a + b; } }!@Testpublic void plus() { when(stubCache.get("1+1")).thenReturn(3); int result = calc.plus(1, 1); assertEquals(3, result);}

���45

Page 46: Komponententests und Testabdeckung

Setup

Verify

Teardown

Exercise

Mock Object

!

!

!

Create

Install

ExpectionsIndirect InputsSUT

RecordVerify

Mock Object

���46

Quelle: XUnit Test Patterns - Gerard Meszaros

Page 47: Komponententests und Testabdeckung

Mocking with Mockitoclass EventAdmin { List<EventListener> listeners = new ArrayList<>(); public void subscribe(EventListener listener) { listeners.add(listener); } public void send(String event, Map<?, ?> properties) { for (EventListener listener : listeners) listener.onEvent(event, properties); }}!@Test public void send() { EventListener mockListener = mock(EventListener.class); eventAdmin.subscribe(mockListener); eventAdmin.send("ups", null); verify(mockListener).onEvent("ups", null);}

���47

Page 48: Komponententests und Testabdeckung

Test Spy

Setup

Verify

Teardown

Exercise

Test Spy !

!

!

Create

Install

Indirect InputsSUT

Record

Verify

���48

Quelle: XUnit Test Patterns - Gerard Meszaros

Page 49: Komponententests und Testabdeckung

Spy Objects with Mockito

@Test public void send() { EventListener listener = new EventListener() { @Override public void onEvent(String e, Map<?, ?> p) {} }; EventListener mockListener = spy(listener); eventAdmin.subscribe(mockListener); eventAdmin.send("ups", null); verify(mockListener).onEvent("ups", null); }

���49