Download - Komponententests und Testabdeckung
![Page 1: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/1.jpg)
Komponententests und Testabdeckung
Christian Baranowski���1
![Page 2: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/2.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/3.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/4.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/5.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/6.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/7.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/8.jpg)
JUnit3 Test Exceptions
try { sut.sort(null); fail("NPE was expected!"); } catch(NullPointerException exp){ assertTrue(true); }
���8
![Page 9: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/9.jpg)
JUnit4 Test Exceptions
@Test(expected = NullPointerException.class) public void sort_NullPointerException() { sut.sort(null); }
���9
![Page 10: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/10.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/11.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/12.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/13.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/14.jpg)
Strukturorientierter Test
���14
![Page 15: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/15.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/16.jpg)
„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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/17.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/18.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/19.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/20.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/21.jpg)
Anweisungsüberdeckung (Statement Coverage)
a && b
c
false
true
true Erwartet a b c
true true true false
���21
![Page 22: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/22.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/23.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/24.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/25.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/26.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/27.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/28.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/29.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/30.jpg)
Überblick kontrollflussorientierten Testverfahren (Überdeckungstests)
���30
![Page 31: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/31.jpg)
Anweisungsüberdeckung
int result = 0
return result
each(values)
result += offset
offset > 0
result += value
offset < value
���31
![Page 32: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/32.jpg)
Zweigabdeckung
int result = 0
return result
each(values)
result += offset
offset > 0
result += value
offset < value
���32
![Page 33: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/33.jpg)
Entscheidungsüberdeckungint result = 0
return result
each(values)
result += offset
offset > 0
result += value
offset < value
���33
![Page 34: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/34.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/35.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/36.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/37.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/38.jpg)
Komponententests für echte Klassen
���38
![Page 39: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/39.jpg)
Testen ohne Abhängigkeiten
«component»SUT
«component»DOC
depended-on component
*
Test
*
���39
![Page 40: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/40.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/41.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/42.jpg)
Test Doubles
���42
![Page 43: Komponententests und Testabdeckung](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/43.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/44.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/45.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/46.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/47.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/48.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022051818/549b0cbeb479591a098b466d/html5/thumbnails/49.jpg)
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