Last active
December 18, 2015 14:29
-
-
Save floriankrueger/5797536 to your computer and use it in GitHub Desktop.
Just a presentation I did on unit testing in Xcode to wrap up the whole topic and provide a basis for our in-team discussion. It uses the SublimeScreencastDirector plugin by @colinta to be "played". (https://github.com/colinta/SublimeScreencastDirector) Unfortunately, it's in german. But the code examples are kind of international ;)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- clear: 0 # screen 00 : Titel | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [4, 14] | |
- write_lines: | |
- 'Unittesting für iOS & OS X' | |
- goto: [5, 14] | |
- delay: 500 | |
- write_lines: | |
- '==========================' | |
- goto: [7, 14] | |
- delay: 100 | |
- write_lines: | |
- 'Eine kleine Einführung' | |
- clear: 0 # screen 01 : Agenda | |
- goto: [4, 14] | |
- write_lines: | |
- 'Agenda' | |
- '======' | |
- goto: [7, 14] | |
- delay: 500 | |
- write_lines: | |
- '1. Was ist ein Unittest?' | |
- '2. Unittesting in Xcode' | |
- '3. Logic Test vs. Application Test' | |
- '4. TDD (Test Driven Development)' | |
- clear: 0 # screen 02 : Was ist ein Unittest? | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Was ist ein Unittest?' | |
- '=====================' | |
- goto: [3, 2] | |
- write_lines: | |
- '"The goal of unit testing is to isolate each' | |
- 'part of the program and show that the individual' | |
- 'parts are correct."' | |
- goto: [7, 2] | |
- write_lines: | |
- '"A unit test provides a strict, written contract' | |
- 'that the piece of code must satisfy."' | |
- delay: 500 | |
- goto: [10, 2] | |
- write_lines: | |
- '~ Quelle: https://en.wikipedia.org/wiki/Unit_testing' | |
- clear: 0 # screen 03 : Fibonacci Header | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- write: '/* Beispiel A: Eine kleine Beispielklasse */' | |
- nl | |
- nl | |
- delay: 500 | |
- write: | |
- '// in Fibonacci.h' | |
- '' | |
- '@interface Fibonacci : NSObject' | |
- '' | |
- '+ (NSUInteger)fibonacci:(NSUInteger)n;' | |
- '' | |
- '@end' | |
- nl | |
- clear: 0 # screen 04 : Fibonacci Test Suite Teil 1 | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- write: '/* Beispiel B: Ein einfacher Unittest */' | |
- nl | |
- nl | |
- delay: 500 | |
- write: | |
- '// in FibonacciTests.m' | |
- set_mark: fib1_import | |
- '' | |
- '@implementation FibonacciTests' | |
- set_mark: fib1_tests | |
- '' | |
- '@end' | |
- goto_mark: fib1_import | |
- write: | |
- '' | |
- '#import "Fibonacci.h"' | |
- goto_mark: fib1_tests | |
- write: | |
- '' | |
- '- (void)testFibonacci10' | |
- '{' | |
- ' NSInteger f10 = [Fibonacci fibonacci:10];' | |
- ' STAssertEquals(f10, 55, nil);' | |
- '}' | |
- clear: 0 # screen 04 A : execution log | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- write: | |
- 'Execution Log' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- nl | |
- insert: "Test Suite 'All tests' finished at 2013-06-13 13:48:44 +0000. \n" | |
- delay: 100 | |
- insert: "Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.001) seconds \n" | |
- clear: 0 # screen 05 : Erklärung Test Suite Teil 1 | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Struktur eines Unittests' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- goto: [3, 1] | |
- write_lines: | |
- '1. Herstellen aller Voraussetzungen für den Test' | |
- goto: [4, 1] | |
- write_lines: | |
- '2. Aufrufen der getesteten Methode' | |
- goto: [5, 1] | |
- write_lines: | |
- '3. Überprüfen der Resultate' | |
- goto: [6, 1] | |
- write_lines: | |
- '4. Aufräumen' | |
- goto: [8, 1] | |
- write: '- 1. und 4. sind im gezeigten Beispiel nicht enthalten.' | |
- clear: 0 # screen 06 : Arten von Unittests | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Arten von Unittests' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- goto: [3, 1] | |
- write_lines: | |
- '- Verhaltenstests' | |
- delay: 500 | |
- goto: [5, 1] | |
- write_lines: | |
- ' "Tut der Code das, was er soll?"' | |
- delay: 500 | |
- goto: [7, 1] | |
- write_lines: | |
- '- Stichprobenartig (unter Umständen)' | |
- '- Sollte Sonderfälle enthalten' | |
- '- Sollte Randfälle enthalten' | |
- '- Erwartet niemals Fehler' | |
- '- Werden bei TDD zuerst geschrieben' | |
- clear_lines: [5, -1] | |
- goto: [4, 1] | |
- write_lines: | |
- '- Regressiontests' | |
- delay: 500 | |
- goto: [6, 1] | |
- write_lines: | |
- '"Ist ein bug (immernoch) gefixed?"' | |
- delay: 500 | |
- goto: [8, 1] | |
- write_lines: | |
- '- Werden geschrieben, um einen von reporteten Bug nachzustellen.' | |
- '- Verbleiben auch nach dem Fix im Code um auszuschließen, dass das Problem' | |
- ' zu einem späteren Zeitpunkt wieder auftritt.' | |
- clear_lines: [6, -1] | |
- goto: [5, 1] | |
- write_lines: | |
- '- Fehlertests' | |
- delay: 500 | |
- goto: [7, 1] | |
- write_lines: | |
- ' "Was tut der code, wenn er falsch benutzt wird?"' | |
- delay: 500 | |
- goto: [9, 1] | |
- write_lines: | |
- '- falsche/ungültige Eingabewerte oder Ergebnisse' | |
- '- Overflows, ∞, NaN' | |
- '- Nil' | |
- '- Leere Collections' | |
- '- Unerwartete Typen in Collections' | |
- '- NSError' | |
- '- erwartet ggf. Exceptions' | |
- clear_lines: [7, -1] | |
- goto: [7, 1] | |
- write_lines: | |
- 'Alle diese sind wichtig um die Funktionsfähigkeit des zu testenden Codes' | |
- 'sicherzustellen.' | |
- clear: 0 # screen 07 : Erweiterung des Unittests | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- goto: [0, 0] | |
- write: '/* Beispiel C: Erweiterung der Unittests (Sonderfälle) */' | |
- nl | |
- nl | |
- delay: 500 | |
- write_lines: | |
- '// in Fibonacci.h' | |
- '' | |
- '@interface Fibonacci : NSObject' | |
- '' | |
- '+ (NSUInteger)fibonacci:(NSUInteger)n;' | |
- '' | |
- '@end' | |
- nl | |
- delay: 500 | |
- goto: [12, 0] | |
- write: | |
- '// in FibonacciTests.m' | |
- '' | |
- '#import "Fibonacci.h"' | |
- '' | |
- '@implementation FibonacciTests' | |
- set_mark: fib2_comment | |
- '' | |
- '- (void)testFibonacci10' | |
- '{' | |
- ' NSInteger f10 = [Fibonacci fibonacci:10];' | |
- ' STAssertEquals(f10, 55, nil);' | |
- '}' | |
- '' | |
- '@end' | |
- goto_mark: fib2_comment | |
- set_mark: fib2_special_cases | |
- write: | |
- '' | |
- '// Stichprobenartiger Positivtest: fib(10) = 55' | |
- goto_mark: fib2_special_cases | |
- write: | |
- set_mark: fib2_special1_comment | |
- '' | |
- '- (void)testFibonacci1' | |
- '{' | |
- ' NSInteger f1 = [Fibonacci fibonacci:1];' | |
- ' STAssertEquals(f1, 1, nil);' | |
- '}' | |
- set_mark: fib2_special2_comment | |
- '' | |
- '- (void)testFibonacci2' | |
- '{' | |
- ' NSInteger f2 = [Fibonacci fibonacci:2];' | |
- ' STAssertEquals(f2, 1, nil);' | |
- '}' | |
- goto_mark: fib2_special1_comment | |
- write: | |
- '' | |
- '// Sonderfall: fib(1) = 1' | |
- goto_mark: fib2_special2_comment | |
- write: | |
- '' | |
- '// Sonderfall: fib(2) = 1' | |
- clear: 0 # screen 07 A : execution log | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- write: | |
- 'Execution Log' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- nl | |
- insert: "Test Suite 'All tests' finished at 2013-06-13 13:25:59 +0000. \n" | |
- delay: 100 | |
- insert: "Executed 3 tests, with 0 failures (0 unexpected) in 0.000 (0.001) seconds \n" | |
- clear: 0 # screen 08 : Randfälle | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- goto: [0, 0] | |
- write: '/* Beispiel D: Erweiterung der Unittests (Randfälle) */' | |
- nl | |
- nl | |
- delay: 500 | |
- write_lines: | |
- '// in Fibonacci.h' | |
- '' | |
- '@interface Fibonacci : NSObject' | |
- '' | |
- '+ (NSUInteger)fibonacci:(NSUInteger)n;' | |
- '' | |
- '@end' | |
- nl | |
- delay: 500 | |
- goto: [12, 0] | |
- write: | |
- '// in FibonacciTests.m' | |
- '' | |
- '#import "Fibonacci.h"' | |
- '' | |
- '@implementation FibonacciTests' | |
- set_mark: fib3_special0 | |
- '' | |
- '/* others */' | |
- '' | |
- '@end' | |
- goto_mark: fib3_special0 | |
- write: | |
- '' | |
- '// Sonderfall: fib(<=0) = 0' | |
- '- (void)testFibonacci0' | |
- '{' | |
- ' NSInteger f0 = [Fibonacci fibonacci:0];' | |
- ' STAssertEquals(f0, 0, nil);' | |
- '' | |
- ' NSInteger flt0 = [Fibonacci fibonacci:-1];' | |
- ' STAssertEquals(flt0, 0, nil);' | |
- '}' | |
- clear: 0 # screen 08 A : execution log | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- write: | |
- 'Execution Log' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- nl | |
- insert: "Test Suite 'FibonacciTests' started at 2013-06-13 14:06:44 +0000 \n" | |
- delay: 100 | |
- insert: "Test Case '-[FibonacciTests testFibonacci0]' started. \n" | |
- delay: 100 | |
- delay: 5000 | |
- write: "(lldb) Thread 1: EXC_BAD_ACCESS (code=2, address=0xbf7fffcc)" | |
- clear: 0 # screen 09 : Algorithm improvements | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- goto: [0, 0] | |
- write: '/* Beispiel E: Implementierung der Klasse `Fibonacci` */' | |
- nl | |
- nl | |
- delay: 500 | |
- write: | |
- '// in Fibonacci.m' | |
- '' | |
- '@implementation Fibonacci' | |
- '' | |
- '+ (NSInteger)fibonacci:(NSInteger)n' | |
- '{' | |
- set_mark: fib4_early_return | |
- '' | |
- ' NSInteger fn;' | |
- '' | |
- ' switch (n) {' | |
- ' case 1: {' | |
- ' fn = 1;' | |
- ' break;' | |
- ' }' | |
- ' case 2: {' | |
- ' fn = 1;' | |
- ' break;' | |
- ' }' | |
- ' default: {' | |
- ' fn = [self fibonacci:n - 1] + [self fibonacci:n - 2];' | |
- ' break;' | |
- ' }' | |
- ' }' | |
- '' | |
- ' return fn;' | |
- '}' | |
- '' | |
- '@end' | |
- goto_mark: fib4_early_return | |
- write: | |
- '' | |
- ' if (n <= 0) return 0;' | |
- clear: 0 # screen 09 A : execution log | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- write: | |
- 'Execution Log' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- nl | |
- write: | |
delay_min: 1 | |
delay_max: 1 | |
write: | |
- "Test Suite 'All tests' finished at 2013-06-13 13:25:59 +0000." | |
- "Executed 4 tests, with 0 failures (0 unexpected) in 0.000 (0.001) seconds" | |
- clear: 0 # screen 10 : Abschluss "Was ist ein Unit Test" | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Warum das Ganze?' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- goto: [3, 1] | |
- write_lines: | |
- '1. Reduzierung (offensichtlicher) Bugs' | |
- delay: 500 | |
- goto: [5, 4] | |
- write_lines: | |
- 'Wenn für Algorithmen vorher die wichtigsten/problematischsten/meisten' | |
- 'Fälle identifiziert werden, können offensichtliche Fehler wie der eben' | |
- 'gezeigte vermieden werden.' | |
- clear_lines: [5, -1] | |
- goto: [4, 1] | |
- write_lines: | |
- '2. Erleichterung von Refactoring' | |
- delay: 500 | |
- goto: [6, 4] | |
- write_lines: | |
- 'Die innere Implementierung einer Methode kann beliebig verändert werden.' | |
- 'solang die Schnittstelle identisch bleibt, zeigen die Tests weiterhin, ob' | |
- 'die neue Implementierung den spezifizierten Anforderungen genügt.' | |
- clear_lines: [6, -1] | |
- goto: [5, 1] | |
- write_lines: | |
- '3. Reduzierung des Testzeit' | |
- delay: 500 | |
- goto: [7, 4] | |
- write_lines: | |
- 'Ein Unittest ist immer schneller als ein manueller Test.' | |
- clear_lines: [7, -1] | |
- goto: [6, 1] | |
- write_lines: | |
- '4. Verbesserung des Software Designs (TDD)' | |
- delay: 500 | |
- goto: [8, 4] | |
- write_lines: | |
- 'Durch Definition des Verhaltens einer Methode muss von Vorneherein auf' | |
- 'saubere Kapselung und Struktur des Codes geachtet werden. Auch eine Art' | |
- '"Schnittstelle" wird implizit definiert. Betrifft vor allem das Test-' | |
- 'Driven-Development.' | |
- clear_lines: [8, -1] | |
- goto: [9, 0] | |
- write_lines: | |
- '"Aber"' | |
- '______' | |
- goto: [12, 1] | |
- write_lines: | |
- '- Ein Unittest kann manuelles Testen nicht ersetzen.' | |
- goto: [13, 1] | |
- write_lines: | |
- '- Nicht jeder Code / jede Architektur is "Unittest-bar".' | |
- goto: [14, 1] | |
- write_lines: | |
- '- Asynchroner Code ist (meist) nur mit Tricks testbar.' | |
- goto: [15, 1] | |
- write_lines: | |
- '- Unittesting verlangt eiserne Disziplin' | |
- ' (vor allem wenn die Zeit knapp wird).' | |
- clear: 0 # screen 11 : Agenda (2) | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [4, 14] | |
- write_lines: | |
- 'Agenda' | |
- '======' | |
- goto: [7, 14] | |
- delay: 500 | |
- write_lines: | |
- '1. Was ist ein Unittest?' | |
- '2. Unittesting in Xcode' | |
- '3. Logic Test vs. Application Test' | |
- '4. TDD (Test Driven Development)' | |
- delay: 500 | |
- goto: [7, 12] | |
- select_delta: 1 | |
- insert: '✓' | |
- clear: 0 # screen 12 : Unittesting in Xcode | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Unittesting in Xcode' | |
- '====================' | |
- goto: [3, 1] | |
- write_lines: | |
- '- Unittests werden als separates Target in Xcode angelegt.' | |
- goto: [4, 1] | |
- write_lines: | |
- '- Gem. Konvention endet der Name des Targets auf "Tests".' | |
- goto: [5, 1] | |
- write_lines: | |
- '- Jedem Target kann ein oder mehrere Testtargets zugewiesen werden, die' | |
- ' Testtargets werden dann mit dem Shortcut ⌘+U gestartet.' | |
- goto: [7, 1] | |
- write_lines: | |
- '- Xcode unterscheidet zwischen Logic Tests und Application Tests.' | |
- ' (dazu später mehr)' | |
- clear: 0 # screen 13 : Testsuites / Testklassen | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Testsuites / Testklassen' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- goto: [3, 1] | |
- write_lines: | |
- '- Eine Testsuite besteht aus einer einzelnen Objective-C Klasse.' | |
- goto: [4, 1] | |
- write_lines: | |
- '- Jede dieser Klassen muss von der Klasse "SenTestCase" ableiten.' | |
- goto: [5, 1] | |
- write_lines: | |
- '- Ein Test entspricht einer Methode.' | |
- goto: [6, 1] | |
- write_lines: | |
- '- Jede Methode, welche den Präfix "test" hat, wird als TestCase erkannt' | |
- ' und ausgeführt.' | |
- goto: [8, 1] | |
- write_lines: | |
- '- Testmethoden haben keine Argumente und geben immer `void` zurück.' | |
- goto: [9, 1] | |
- write_lines: | |
- '- Testmethoden machen `Assertions` um zu bestimmen ob sie den Status' | |
- ' `Pass` oder `Fail` annehmen.' | |
- goto: [11, 1] | |
- write_lines: | |
- '- Weitere besondere Methoden sind `setUp` und `tearDown`, andere Methoden' | |
- ' können vom Entwickler als Helfermethoden eingeführt werden.' | |
- goto: [13, 1] | |
- write_lines: | |
- '- Die Methoden setUpTestWithSelector:` und `tearDownTestWithSelector:`' | |
- ' können zusätzlich für Spezialfälle verwendet werden.' | |
- goto: [15, 1] | |
- write_lines: | |
- '- Headerfiles sind im Prinzip unnötig, da SenTestingKit direkt auf den' | |
- ' Selektoren einer Klasse arbeitet. Sie sollten aber aus Konsistenzgründen' | |
- ' dennoch beibehalten werden und können zur Dokumentation von' | |
- ' Hilfsmethoden nützlich sein.' | |
- clear: 0 # screen 14 : Beispiel Testsuite Header | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- goto: [0, 0] | |
- write: '/* Beispiel F1: Eine "vollständige" Testsuite */' | |
- nl | |
- nl | |
- delay: 500 | |
- write: | |
- '// in ExampleTests.h' | |
- '' | |
- '#import <SenTestingKit/SenTestingKit.h>' | |
- '' | |
- '@interface ExampleTests : SenTestCase' | |
- '' | |
- '@end' | |
- clear: 0 # screen 15 : Beispiel Testsuite Implementation | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- goto: [0, 0] | |
- write: '/* Beispiel F2: Eine "vollständige" Testsuite */' | |
- nl | |
- nl | |
- delay: 500 | |
- write: | |
- '// in ExampleTests.m' | |
- '' | |
- '#import "ExampleTests.h"' | |
- '' | |
- '@implementation ExampleTests' | |
- '' | |
- '+ (void)setUp // set up the whole testsuite before it runs' | |
- '{' | |
- ' [super setUp]; NSLog(@"in testsuite setUp");' | |
- '}' | |
- '' | |
- '- (void)setUp // set up each testcase before it runs' | |
- '{' | |
- ' [super setUp]; NSLog(@"in testcase setup");' | |
- '}' | |
- '' | |
- '- (void)testExample1' | |
- '{' | |
- ' NSLog(@"in testcase `testExample1`");' | |
- ' STAssertEquals((1+1), 2, @"The compiler isn`t feeling very well today");' | |
- '}' | |
- '' | |
- '- (void)testExample2' | |
- '{' | |
- ' NSLog(@"in testcase `testExample2`");' | |
- ' STAssertTrue(YES, @"Something is seriously wrong here");' | |
- '}' | |
- '' | |
- '- (void)tearDown // clean up each testcase after it has been run' | |
- '{' | |
- ' NSLog(@"in testcase tearDown"); [super tearDown];' | |
- '}' | |
- '' | |
- '+ (void)tearDown // clean up after the whole testsuite has been run' | |
- '{' | |
- ' NSLog(@"in testsuite tearDown"); [super tearDown];' | |
- '}' | |
- '' | |
- '@end' | |
- clear: 0 # screen 16 : execution log | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- write: | |
- 'Execution Log' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- nl | |
- insert: "2013-06-14 10:54:51.095 Tests[1854:c07] in testsuite setUp \n" | |
- delay: 100 | |
- insert: "Test Suite 'ExampleTests' started at 2013-06-14 08:54:51 +0000 \n" | |
- delay: 100 | |
- insert: "Test Case '-[ExampleTests testExample1]' started. \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.095 Tests[1854:c07] in testcase setup \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.095 Tests[1854:c07] in testcase `testExample1` \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.095 Tests[1854:c07] in testcase tearDown \n" | |
- delay: 100 | |
- insert: "Test Case '-[ExampleTests testExample1]' passed (0.001 seconds). \n" | |
- delay: 100 | |
- insert: "Test Case '-[ExampleTests testExample2]' started. \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.096 Tests[1854:c07] in testcase setup \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.096 Tests[1854:c07] in testcase `testExample2` \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.096 Tests[1854:c07] in testcase tearDown \n" | |
- delay: 100 | |
- insert: "Test Case '-[ExampleTests testExample2]' passed (0.000 seconds). \n" | |
- delay: 100 | |
- insert: "Test Suite 'ExampleTests' finished at 2013-06-14 08:54:51 +0000. \n" | |
- delay: 100 | |
- insert: "Executed 2 tests, with 0 failures (0 unexpected) in 0.001 (0.001) seconds \n" | |
- delay: 100 | |
- insert: "2013-06-14 10:54:51.096 Tests[1854:c07] in testsuite tearDown \n" | |
- clear: 0 # screen 17 : STAsserts | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'STAsserts' | |
- '‾‾‾‾‾‾‾‾‾' | |
- goto: [3, 1] | |
- write_lines: | |
- '- Mithilfe von STAssert Macros wird die Erfüllung der Erwartungen an' | |
- ' den Test überprüft.' | |
- goto: [5, 1] | |
- write_lines: | |
- '- Ein Testcase OHNE assert gilt immer als bestanden, solang keine' | |
- ' Exception auftritt.' | |
- goto: [8, 1] | |
- write_lines: | |
- 'Die folgenden Macros existieren:' | |
- goto: [10, 1] | |
- write_lines: | |
- '- STFail' | |
- '' | |
- '- STAssertNil' | |
- '' | |
- '- STAssertNotNil' | |
- '' | |
- '- STAssertTrue' | |
- '' | |
- '- STAssertFalse' | |
- '' | |
- '- STAssertEquals' | |
- '- STAssertEqualObjects' | |
- '- STAssertEqualsWithAccuracy' | |
- '' | |
- '- STAssertThrows' | |
- '- STAssertThrowsSpecific' | |
- '- STAssertThrowsSpecificNamed' | |
- '' | |
- '- STAssertNoThrow' | |
- '- STAssertNoThrowSpecific' | |
- '- STAssertNoThrowSpecificNamed' | |
- '' | |
- '- STAssertTrueNoThrow' | |
- '' | |
- '- STAssertFalseNoThrow' | |
- clear: 0 # screen 18 : Agenda (3) | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [4, 14] | |
- write_lines: | |
- 'Agenda' | |
- '======' | |
- goto: [7, 12] | |
- delay: 500 | |
- write_lines: | |
- '✓ 1. Was ist ein Unittest?' | |
- ' 2. Unittesting in Xcode' | |
- ' 3. Logic Test vs. Application Test' | |
- ' 4. TDD (Test Driven Development)' | |
- delay: 500 | |
- goto: [8, 12] | |
- select_delta: 1 | |
- insert: '✓' | |
- clear: 0 # screen 19 : Logic Test vs. Application Test | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Logic Test vs. Application Test' | |
- '===============================' | |
- goto: [3, 1] | |
- write_lines: | |
- 'Es handelt sich dabei um einen rein konzeptionellen Unterschied' | |
- goto: [5, 1] | |
- write_lines: | |
- '"Logic Tests" sind klassische Unittests:' | |
- goto: [7, 1] | |
- write_lines: | |
- '- Testen einer einzelnen Methode oder Klasse' | |
- '- Geeignet zum Testen von Algorithmen und Datenstrukturen' | |
- '- sehr schnell in der Ausführung' | |
- '- in etwa: "White Box Testing"' | |
- goto: [13, 1] | |
- write_lines: | |
- '"Application Tests" sind eher Integrationstests:' | |
- ' ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ ' | |
- goto: [15, 1] | |
- write_lines: | |
- '- Tested "die App"' | |
- '- Testen von Zusammenspiel zwischen der View- und Controllerschicht' | |
- '- Vergleichsweise langsam in der Ausführung' | |
- '- in etwa: "Black Box Testing"' | |
- goto: [21, 0] | |
- write_lines: | |
- 'Technischer Unterschied' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- goto: [23, 1] | |
- write_lines: | |
- '- Logic Tests haben keinen Bundle Loader und demnach auch kein' | |
- ' Application Bundle' | |
- goto: [25, 1] | |
- write_lines: | |
- '- Ein Zugriff auf eine *.xib file, ein *.xcdatamodel u.ä. ist also nicht' | |
- ' möglich.' | |
- goto: [30, 0] | |
- write_lines: | |
- '> Der Trend geht start dazu über, ausschließlich Application tests zu' | |
- ' verwenden, da der Nachteil (längere Ausführungszeit) mittlerweile' | |
- ' kaum noch spürbar ist.' | |
- clear: 0 # screen 20 : Agenda (4) | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [4, 14] | |
- write_lines: | |
- 'Agenda' | |
- '======' | |
- goto: [7, 12] | |
- delay: 500 | |
- write_lines: | |
- '✓ 1. Was ist ein Unittest?' | |
- '✓ 2. Unittesting in Xcode' | |
- ' 3. Logic Test vs. Application Test' | |
- ' 4. TDD (Test Driven Development)' | |
- delay: 500 | |
- goto: [9, 12] | |
- select_delta: 1 | |
- insert: '✓' | |
- clear: 0 # screen 21 : Logic Test vs. Application Test | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'TDD (Test Driven Development)' | |
- '=============================' | |
- goto: [3, 1] | |
- write_lines: | |
- '- Bei TDD werden zuerst die Tests und dann der Code geschrieben.' | |
- goto: [4, 1] | |
- write_lines: | |
- '- Dabei wird immer nur der Code geschrieben, der die aktuell vorliegenden' | |
- ' Testfälle mit minimalem Aufwand abdeckt.' | |
- goto: [6, 1] | |
- write_lines: | |
- '- Man beginnt mit einem einzigen Testcase, implementiert die' | |
- ' geforderte Funktionalität bis der Test erfüllt ist und fügt dann den' | |
- ' nächsten Test hinzu, bis schließlich die gesamte Testsuite aktiv ist und' | |
- ' fehlerfrei ausgeführt werden kann.' | |
- goto: [10, 1] | |
- write_lines: | |
- '- Diese Form des Testens wird auch "Red-Green-Testing" genannt.' | |
- clear: 0 # screen 22 : TDD Example | |
- set_syntax: 'Packages/Objective-C/Objective-C.tmLanguage' | |
- goto: [0, 0] | |
- write: '/* Beispiel G: Test-Driven Fibonacci */' | |
- nl | |
- nl | |
- delay: 500 | |
- write_lines: | |
- '@implementation TDDFibonacciTests' | |
- '' | |
- '- (void)testFibonacci' | |
- '{' | |
- ' STAssertTrue([TDDFibonacci fib:0] == 0, nil);' | |
- '}' | |
- '' | |
- '@end' | |
- '' | |
- '@implementation TDDFibonacci' | |
- '' | |
- '+ (NSInteger)fib:(NSInteger)n' | |
- '{' | |
- '}' | |
- '' | |
- '@end' | |
- goto: [6, 60] | |
- write: '✘' | |
- goto: [14, 2] | |
- nl | |
- write: ' return 0;' | |
- goto: [6, 60] | |
- select_delta: 1 | |
- insert: '✔' | |
- goto: [6, 61] | |
- nl | |
- write: ' STAssertTrue([TDDFibonacci fib:1] == 1, nil);' | |
- goto: [7, 60] | |
- write: '✘' | |
- goto: [16, 11] | |
- select_delta: 1 | |
- insert: '1' | |
- goto: [6, 60] | |
- select_delta: 1 | |
- insert: '✘' | |
- goto: [7, 60] | |
- select_delta: 1 | |
- insert: '✔' | |
- goto: [15, 2] | |
- nl | |
- write: | |
- ' if (0 == n) {' | |
- ' return 0;' | |
- ' }' | |
- goto: [6, 60] | |
- select_delta: 1 | |
- insert: '✔' | |
- goto: [7, 61] | |
- nl | |
- write: ' STAssertTrue([TDDFibonacci fib:2] == 1, nil);' | |
- goto: [8, 60] | |
- write: '✔' | |
- goto: [8, 61] | |
- nl | |
- write: ' STAssertTrue([TDDFibonacci fib:3] == 2, nil);' | |
- goto: [9, 60] | |
- write: '✘' | |
- goto: [20, 8] | |
- write: | |
- 'else if (n <= 2) {' | |
- ' return 1;' | |
- ' }' | |
- select_lines: [23, 23] | |
- delete | |
- goto: [24, 11] | |
- select_delta: 1 | |
- insert: '2' | |
- goto: [9, 60] | |
- select_delta: 1 | |
- insert: '✔' | |
- goto: [9, 61] | |
- nl | |
- write: ' STAssertTrue([TDDFibonacci fib:4] == 3, nil);' | |
- goto: [10, 60] | |
- write: '✘' | |
- goto: [25, 11] | |
- select_delta: 1 | |
- write: '1 + 1' | |
- goto: [25, 11] | |
- select_delta: 1 | |
- write: '[self fib:(n-1)]' | |
- goto: [25, 30] | |
- select_delta: 1 | |
- write: '[self fib:(n-2)]' | |
- goto: [10, 60] | |
- select_delta: 1 | |
- insert: '✔' | |
- clear: 0 # screen 23 : Agenda (5) | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [4, 14] | |
- write_lines: | |
- 'Agenda' | |
- '======' | |
- goto: [7, 12] | |
- delay: 500 | |
- write_lines: | |
- '✓ 1. Was ist ein Unittest?' | |
- '✓ 2. Unittesting in Xcode' | |
- '✓ 3. Logic Test vs. Application Test' | |
- ' 4. TDD (Test Driven Development)' | |
- delay: 500 | |
- goto: [10, 12] | |
- select_delta: 1 | |
- insert: '✓' | |
- goto: [11, 6] | |
- write_lines: | |
- '[NEW] 5. Unittesting in Xcode 5' | |
- clear: 0 # screen 24 : Unittesting in Xcode 5 | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Unittesting in Xcode 5' | |
- '======================' | |
- goto: [3, 1] | |
- write_lines: | |
- '- XCTest ersetzt OCUnit (ist aber direkt davon abgeleitet).' | |
- goto: [4, 1] | |
- write_lines: | |
- '- Xcode 5 ist vollständig Rückwärtskompatibel zu OCUnit.' | |
- goto: [5, 1] | |
- write_lines: | |
- '- OCUnit Testcases können automatisch migriert werden.' | |
- clear: 0 # screen 25 : Integration in Xcode 5 | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [0, 0] | |
- write_lines: | |
- 'Integration in Xcode 5' | |
- '‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾' | |
- goto: [3, 1] | |
- write_lines: | |
- '- Es existiert ein vollständig neuer Workflow.' | |
- goto: [4, 1] | |
- write_lines: | |
- '- Neuer Testcase Navigator, der alle Testcases im Projekt auflistet und' | |
- ' deren aktuellen Status anzeigt.' | |
- goto: [6, 1] | |
- write_lines: | |
- '- One-Click Testing: Um einen einzelnen Testcase auszuführen, kann direkt' | |
- ' neben der Methode im Editor geklickt werden, man bekommt sofortiges' | |
- ' rot/grün Feedback.' | |
- goto: [9, 1] | |
- write_lines: | |
- '- One-Click Testing: Um eine Testsuite oder alle Tests auszuführen, kann' | |
- ' neben der entsprechenden Entität im Testcase Navigator geklickt werden.' | |
- ' Auch hier gibt es via rot/grün Marker sofortiges Feedback.' | |
- goto: [12, 1] | |
- write_lines: | |
- '- Test Failure Breakpoints zum einfacheren Debuggen von Fehlern in' | |
- ' Unittests. Diese spezielle Form von Breakpoints stoppen exakt BEVOR ein' | |
- ' Assert fehlschlagen würde.' | |
- goto: [15, 1] | |
- write_lines: | |
- '- Run Again Command: Führt währed des Debugging das zuletzt ausgeführte' | |
- ' Set an Testcases aus.' | |
- goto: [17, 1] | |
- write_lines: | |
- '- Test Callers: Ein neue Assistant Kategorie, die alle Testcases für eine' | |
- ' bestimmte API auflistet.' | |
- goto: [19, 1] | |
- write_lines: | |
- '- Continous Integration mit OS X Server möglich: Automatischer Test unter' | |
- ' verschiedenen Soft- und Hardware Konfigurationen, sowohl auf dem' | |
- ' Simulator als auch auf dem Device.' | |
- goto: [22, 1] | |
- write_lines: | |
- '- Bis jetzt keine existieren keine Informationen darüber, ob zukünftig' | |
- ' noch ein Unterschied zwischen Logic- und Applicationtests gemacht wird.' | |
- clear: 0 # screen 26 : Abschluss | |
- set_syntax: 'Packages/Text/Plain text.tmLanguage' | |
- goto: [4, 14] | |
- write_lines: | |
- 'Unittesting für iOS & OS X' | |
- goto: [5, 14] | |
- delay: 500 | |
- write_lines: | |
- '==========================' | |
- goto: [8, 14] | |
- delay: 100 | |
- write_lines: | |
- 'Vielen Dank für die Aufmerksamkeit' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment