0
Macoun
⌘
96% Testabdeckung
Maxim Zaks @iceX33
Ablauf
Ablauf
•Was ist Test Abdeckung und wie kann man es messen
Ablauf
•Was ist Test Abdeckung und wie kann man es messen
•Wann ist hohe Testabdeckung eine gute Strategie
Ablauf
•Was ist Test Abdeckung und wie kann man es messen
•Wann ist hohe Testabdeckung eine gute Strategie
•Taktiken wie m...
Was ist Testabdeckung?
Jenkins CI / Cobertura Plugin
https://travis-ci.org/
Wie funktioniert Testabdeckung?
Einfach ... aber ... XCode5
__gcov_flush()
http://stackoverflow.com/questions/18394655/xcode5-
code-coverage-from-cmd-line-for-ci-builds/
18977454#18977...
http://gcovr.com
Wann ist hohe Testabdeckung
eine gute Strategie
Fakten aus unseren Projekt
Das Projekt
Das Projekt
•Laufdauer - über ein Jahr
Das Projekt
•Laufdauer - über ein Jahr
•3 iOS Entwickler
Das Projekt
•Laufdauer - über ein Jahr
•3 iOS Entwickler
•Agile Entwicklung
Das Projekt
•Laufdauer - über ein Jahr
•3 iOS Entwickler
•Agile Entwicklung
•Anzahl der Kompilierten Quelldateien für Prod...
Das Projekt
•Laufdauer - über ein Jahr
•3 iOS Entwickler
•Agile Entwicklung
•Anzahl der Kompilierten Quelldateien für Prod...
Codezeilen
Codezeilen
•Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt
Codezeilen
•Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt
•Gesamte Anzahl der Codezeilen wenn Test und .h Dateie...
Codezeilen
•Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt
•Gesamte Anzahl der Codezeilen wenn Test und .h Dateie...
Schlussfolgerung:
Tests machen Dich nicht
schneller
Weitere Fakten aus unseren
Projekt
Leistung
Leistung
•Robust gegen Refactoring und Änderung
Leistung
•Robust gegen Refactoring und Änderung
•Schnelle Einarbeitung neuer Kollegen
Leistung
•Robust gegen Refactoring und Änderung
•Schnelle Einarbeitung neuer Kollegen
•Sehr geringe Anzahl von Bugs
Schlussfolgerung:
Tests geben Dir mehr Leistung
Meine ACID Theorie
ACIDsiehe http://de.wikipedia.org/wiki/ACID
•Atomic = Nichts ist abhängig von deinen Code
•Consistent = Es ist Eindeutig w...
Eine weniger strenge Theorie
Sprint vs. Marathon
Taktiken für hohe Testabdeckung
Falls ihr im Team arbeitet,
jeder muss mitziehen!
Pair Programming hilft!
Unit vs. Integration Test
Scharfschutze vs. Streubombe
Testabdeckung
•Mit Integration Test (Streubombe) erreicht man schnell hohe
Testabdeckung (alte gute 80 / 20 Regel)
•Um ein...
Unit Test Framework
Wir benutzen Kiwi
•Basiert auf OCUnit / XCTest
•Testbeschreibungsprache ist angenehm
•describe what you expect it should d...
Das Hauptrezept eines UnitTests
ist Isolierung
Reine Funktion
•Eingabe A resultiert immer in Ausgabe B
•Keine Seiteneffekte - es wird Nichts im Hintergrund gemacht
it(@"should convert snake case string to camel case string", ^{
// given
NSString *string = @"some_string_in_snake_case";
...
it(@"should handle empty string", ^{
// when
NSString *convertedString = [@"" snakeCaseToCamelCase];
// then
[[convertedSt...
it(@"should still work even if converting a string several times (used to test
caching)", ^{
// given
NSString *string = @...
Delegieren stat selber machen
•@property (Dependency Injection)
•Mit Erwartungen Arbeiten
__block GXRecruitmentService *service;
__block GXBackendInterface *backendInterface;
beforeEach(^{
service = [GXRecruitmen...
it(@"should call add_unit in the backend", ^{
// given
// expectation
[[backendInterface should] receive:@selector(postMet...
Geburtenkontrolle
•Stub alloc und init Methoden
•Stub Klassen Methoden
•Manchmal muss man sogar eine Extraschicht spendier...
__block GXBackendInterface *backendInterface;
__block AFHTTPClient *httpClient;
beforeEach(^{
httpClient = [AFHTTPClient n...
it(@"should set the base URL on init", ^{
! // given
! NSURL *url = [[NSURL alloc] initWithString:BACKEND_SERVICE_URL];
//...
Was mache ich mit Callback
blocks?
•Auf Parameter spionieren
•Callback selber aufrufen
- (void) postMethod:(NSString *)method parameters:(NSDictionary *)parameters
success:(void (^)(NSDictionary *))successBloc...
__block void (^failureBlock)(AFHTTPRequestOperation *, id);
beforeEach(^{
KWCaptureSpy *failureSpy = [(id) httpClient
capt...
it(@"should show an alert", ^{
// given
[[operation stubAndReturn:theValue(NO)] isCancelled];
UIAlertView *alertView = [UI...
Kann ich etwas nicht Testen?
•Aufruf von C Funktionen
•Wenn Code auf dem Bildschirm Zeichnet
Kleine Tips
•Given,When,Then Kommentare helfen
•Versuche Wiederverwendung in Tests zu erzielen
•Erstelle Templates um Klas...
Fazit
•Hohe Testabdeckung erhöht die Leistung (keine Geschwindigkeit)
•Beantwortet folgende Fragen:
•Muss ich ein Sprint o...
Fragen?
Vielen Dank
@iceX33
Macoun
⌘
96% macoun 2013
96% macoun 2013
96% macoun 2013
96% macoun 2013
96% macoun 2013
Upcoming SlideShare
Loading in...5
×

96% macoun 2013

529

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
529
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "96% macoun 2013"

  1. 1. Macoun ⌘
  2. 2. 96% Testabdeckung Maxim Zaks @iceX33
  3. 3. Ablauf
  4. 4. Ablauf •Was ist Test Abdeckung und wie kann man es messen
  5. 5. Ablauf •Was ist Test Abdeckung und wie kann man es messen •Wann ist hohe Testabdeckung eine gute Strategie
  6. 6. Ablauf •Was ist Test Abdeckung und wie kann man es messen •Wann ist hohe Testabdeckung eine gute Strategie •Taktiken wie man eine hohe Testabdeckung erreichen kann
  7. 7. Was ist Testabdeckung?
  8. 8. Jenkins CI / Cobertura Plugin
  9. 9. https://travis-ci.org/
  10. 10. Wie funktioniert Testabdeckung?
  11. 11. Einfach ... aber ... XCode5
  12. 12. __gcov_flush() http://stackoverflow.com/questions/18394655/xcode5- code-coverage-from-cmd-line-for-ci-builds/ 18977454#18977454
  13. 13. http://gcovr.com
  14. 14. Wann ist hohe Testabdeckung eine gute Strategie
  15. 15. Fakten aus unseren Projekt
  16. 16. Das Projekt
  17. 17. Das Projekt •Laufdauer - über ein Jahr
  18. 18. Das Projekt •Laufdauer - über ein Jahr •3 iOS Entwickler
  19. 19. Das Projekt •Laufdauer - über ein Jahr •3 iOS Entwickler •Agile Entwicklung
  20. 20. Das Projekt •Laufdauer - über ein Jahr •3 iOS Entwickler •Agile Entwicklung •Anzahl der Kompilierten Quelldateien für Production Target 465
  21. 21. Das Projekt •Laufdauer - über ein Jahr •3 iOS Entwickler •Agile Entwicklung •Anzahl der Kompilierten Quelldateien für Production Target 465 • Anzahl der Kompilierten Quelldateien für Test Target 795
  22. 22. Codezeilen
  23. 23. Codezeilen •Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt
  24. 24. Codezeilen •Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt •Gesamte Anzahl der Codezeilen wenn Test und .h Dateien nicht erfasst werden 8745 davon 91% Abgedeckt
  25. 25. Codezeilen •Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt •Gesamte Anzahl der Codezeilen wenn Test und .h Dateien nicht erfasst werden 8745 davon 91% Abgedeckt •Folgerung nur etwa 25% der Codezeilen befinden sich in Produktiven .m Dateien
  26. 26. Schlussfolgerung: Tests machen Dich nicht schneller
  27. 27. Weitere Fakten aus unseren Projekt
  28. 28. Leistung
  29. 29. Leistung •Robust gegen Refactoring und Änderung
  30. 30. Leistung •Robust gegen Refactoring und Änderung •Schnelle Einarbeitung neuer Kollegen
  31. 31. Leistung •Robust gegen Refactoring und Änderung •Schnelle Einarbeitung neuer Kollegen •Sehr geringe Anzahl von Bugs
  32. 32. Schlussfolgerung: Tests geben Dir mehr Leistung
  33. 33. Meine ACID Theorie
  34. 34. ACIDsiehe http://de.wikipedia.org/wiki/ACID •Atomic = Nichts ist abhängig von deinen Code •Consistent = Es ist Eindeutig was, wie und warum es tut, was es tut •Isolated = Es ist absolut unabhängig von Anderen •Durable = Es wird nie verändert
  35. 35. Eine weniger strenge Theorie
  36. 36. Sprint vs. Marathon
  37. 37. Taktiken für hohe Testabdeckung
  38. 38. Falls ihr im Team arbeitet, jeder muss mitziehen!
  39. 39. Pair Programming hilft!
  40. 40. Unit vs. Integration Test Scharfschutze vs. Streubombe
  41. 41. Testabdeckung •Mit Integration Test (Streubombe) erreicht man schnell hohe Testabdeckung (alte gute 80 / 20 Regel) •Um eine Testabdeckung über 90% zu erreichen braucht man Scharfschutzen an jeder Ecke
  42. 42. Unit Test Framework
  43. 43. Wir benutzen Kiwi •Basiert auf OCUnit / XCTest •Testbeschreibungsprache ist angenehm •describe what you expect it should do (RSpec style) •Wir ergänzen mit (given, expectations, when, then) Kommentaren •Mocking und Matching ist integriert
  44. 44. Das Hauptrezept eines UnitTests ist Isolierung
  45. 45. Reine Funktion •Eingabe A resultiert immer in Ausgabe B •Keine Seiteneffekte - es wird Nichts im Hintergrund gemacht
  46. 46. it(@"should convert snake case string to camel case string", ^{ // given NSString *string = @"some_string_in_snake_case"; // when NSString *convertedString = [string snakeCaseToCamelCase]; // then [[convertedString should] equal:@"someStringInSnakeCase"]; });
  47. 47. it(@"should handle empty string", ^{ // when NSString *convertedString = [@"" snakeCaseToCamelCase]; // then [[convertedString should] equal:@""]; });
  48. 48. it(@"should still work even if converting a string several times (used to test caching)", ^{ // given NSString *string = @"some_string_in_snake_case"; // when NSString *convertedString1 = [string snakeCaseToCamelCase]; NSString *convertedString2 = [string snakeCaseToCamelCase]; NSString *convertedString3 = [string snakeCaseToCamelCase]; // then [[convertedString1 should] equal:@"someStringInSnakeCase"]; [[convertedString2 should] equal:@"someStringInSnakeCase"]; [[convertedString3 should] equal:@"someStringInSnakeCase"]; });
  49. 49. Delegieren stat selber machen •@property (Dependency Injection) •Mit Erwartungen Arbeiten
  50. 50. __block GXRecruitmentService *service; __block GXBackendInterface *backendInterface; beforeEach(^{ service = [GXRecruitmentService new]; backendInterface = [GXBackendInterface mockWithName:@"bi"]; ! ! ! ! ! ! ! service.backendInterface = backendInterface; });
  51. 51. it(@"should call add_unit in the backend", ^{ // given // expectation [[backendInterface should] receive:@selector(postMethod:parameters:) withCount:1 arguments:ADD_UNIT_METHOD, @{ @"position": @{ @"x": @20, @"y": @21 }, @"type": @"unit1" }]; // when [service addUnitOfType:@"unit1" toBarrackAtPosition:CGPointMake(20, 21)]; });
  52. 52. Geburtenkontrolle •Stub alloc und init Methoden •Stub Klassen Methoden •Manchmal muss man sogar eine Extraschicht spendieren
  53. 53. __block GXBackendInterface *backendInterface; __block AFHTTPClient *httpClient; beforeEach(^{ httpClient = [AFHTTPClient nullMockWithName:@"httpClient"]; [AFHTTPClient stub:@selector(alloc) andReturn:httpClient]; });
  54. 54. it(@"should set the base URL on init", ^{ ! // given ! NSURL *url = [[NSURL alloc] initWithString:BACKEND_SERVICE_URL]; // expectations [[httpClient should] receive:@selector(initWithBaseURL:) withArguments:url]; // when backendInterface = [GXBackendInterface new]; });
  55. 55. Was mache ich mit Callback blocks? •Auf Parameter spionieren •Callback selber aufrufen
  56. 56. - (void) postMethod:(NSString *)method parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))successBlock { ... [_httpClient postPath:nil parameters:requestParams success:^(AFHTTPRequestOperation *operation, id responseObject) { ... } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (![operation isCancelled]) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"" message:@"" delegate:self cancelButtonTitle:@"Reload" otherButtonTitles:nil]; ! ! [alertView show]; } }];
  57. 57. __block void (^failureBlock)(AFHTTPRequestOperation *, id); beforeEach(^{ KWCaptureSpy *failureSpy = [(id) httpClient captureArgument:@selector(postPath:parameters:success:failure:) atIndex:3]; [backendInterface postMethod:@"" parameters:@{} success:^(NSDictionary *responseObject) { }]; failureBlock = failureSpy.argument; operation = [AFHTTPRequestOperation nullMockWithName:@"operation"]; });
  58. 58. it(@"should show an alert", ^{ // given [[operation stubAndReturn:theValue(NO)] isCancelled]; UIAlertView *alertView = [UIAlertView mockWithName:@"alertView"]; [UIAlertView stub:@selector(alloc) andReturn:alertView]; [alertView stub:@selector(initWithTitle:message:delegate:cancelButtonTitle:otherButtonTi tles:) andReturn:alertView]; // expectations [[alertView should] receive:@selector(show)]; // when failureBlock(operation, nil); });
  59. 59. Kann ich etwas nicht Testen? •Aufruf von C Funktionen •Wenn Code auf dem Bildschirm Zeichnet
  60. 60. Kleine Tips •Given,When,Then Kommentare helfen •Versuche Wiederverwendung in Tests zu erzielen •Erstelle Templates um Klassen direkt mit Specs zu erstellen
  61. 61. Fazit •Hohe Testabdeckung erhöht die Leistung (keine Geschwindigkeit) •Beantwortet folgende Fragen: •Muss ich ein Sprint oder ein Marathon laufen? •Kann ich mein Code isolieren?
  62. 62. Fragen?
  63. 63. Vielen Dank @iceX33
  64. 64. Macoun ⌘
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×