69
Macoun

96% macoun 2013

Embed Size (px)

Citation preview

Page 1: 96% macoun 2013

Macoun⌘

Page 2: 96% macoun 2013

96% TestabdeckungMaxim Zaks @iceX33

Page 3: 96% macoun 2013

Ablauf

Page 4: 96% macoun 2013

Ablauf

•Was ist Test Abdeckung und wie kann man es messen

Page 5: 96% macoun 2013

Ablauf

•Was ist Test Abdeckung und wie kann man es messen

•Wann ist hohe Testabdeckung eine gute Strategie

Page 6: 96% macoun 2013

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

Page 7: 96% macoun 2013

Was ist Testabdeckung?

Page 8: 96% macoun 2013
Page 9: 96% macoun 2013
Page 10: 96% macoun 2013

Jenkins CI / Cobertura Plugin

Page 11: 96% macoun 2013

https://travis-ci.org/

Page 12: 96% macoun 2013
Page 13: 96% macoun 2013

Wie funktioniert Testabdeckung?

Page 14: 96% macoun 2013
Page 15: 96% macoun 2013
Page 16: 96% macoun 2013

Einfach ... aber ... XCode5

Page 18: 96% macoun 2013

http://gcovr.com

Page 19: 96% macoun 2013

Wann ist hohe Testabdeckung eine gute Strategie

Page 20: 96% macoun 2013

Fakten aus unseren Projekt

Page 21: 96% macoun 2013

Das Projekt

Page 22: 96% macoun 2013

Das Projekt

• Laufdauer - über ein Jahr

Page 23: 96% macoun 2013

Das Projekt

• Laufdauer - über ein Jahr

• 3 iOS Entwickler

Page 24: 96% macoun 2013

Das Projekt

• Laufdauer - über ein Jahr

• 3 iOS Entwickler

• Agile Entwicklung

Page 25: 96% macoun 2013

Das Projekt

• Laufdauer - über ein Jahr

• 3 iOS Entwickler

• Agile Entwicklung

• Anzahl der Kompilierten Quelldateien für Production Target 465

Page 26: 96% macoun 2013

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

Page 27: 96% macoun 2013

Codezeilen

Page 28: 96% macoun 2013

Codezeilen

• Gesamte Anzahl der Codezeilen 32615 davon 97% Abgedeckt

Page 29: 96% macoun 2013

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

Page 30: 96% macoun 2013

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

Page 31: 96% macoun 2013

Schlussfolgerung:Tests machen Dich nicht

schneller

Page 32: 96% macoun 2013

Weitere Fakten aus unseren Projekt

Page 33: 96% macoun 2013

Leistung

Page 34: 96% macoun 2013

Leistung

• Robust gegen Refactoring und Änderung

Page 35: 96% macoun 2013

Leistung

• Robust gegen Refactoring und Änderung

• Schnelle Einarbeitung neuer Kollegen

Page 36: 96% macoun 2013

Leistung

• Robust gegen Refactoring und Änderung

• Schnelle Einarbeitung neuer Kollegen

• Sehr geringe Anzahl von Bugs

Page 37: 96% macoun 2013

Schlussfolgerung:Tests geben Dir mehr Leistung

Page 38: 96% macoun 2013

Meine ACID Theorie

Page 39: 96% macoun 2013

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

Page 40: 96% macoun 2013

Eine weniger strenge Theorie

Page 41: 96% macoun 2013

Sprint vs. Marathon

Page 42: 96% macoun 2013

Taktiken für hohe Testabdeckung

Page 43: 96% macoun 2013

Falls ihr im Team arbeitet,jeder muss mitziehen!

Page 44: 96% macoun 2013

Pair Programming hilft!

Page 45: 96% macoun 2013

Unit vs. Integration TestScharfschutze vs. Streubombe

Page 46: 96% macoun 2013

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

Page 47: 96% macoun 2013

Unit Test Framework

Page 48: 96% macoun 2013

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

Page 49: 96% macoun 2013

Das Hauptrezept eines UnitTests ist Isolierung

Page 50: 96% macoun 2013

Reine Funktion

• Eingabe A resultiert immer in Ausgabe B

• Keine Seiteneffekte - es wird Nichts im Hintergrund gemacht

Page 51: 96% macoun 2013

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"];});

Page 52: 96% macoun 2013

it(@"should handle empty string", ^{

// when NSString *convertedString = [@"" snakeCaseToCamelCase];

// then [[convertedString should] equal:@""];});

Page 53: 96% macoun 2013

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"];});

Page 54: 96% macoun 2013

Delegieren stat selber machen

•@property (Dependency Injection)

•Mit Erwartungen Arbeiten

Page 55: 96% macoun 2013

__block GXRecruitmentService *service;__block GXBackendInterface *backendInterface;

beforeEach(^{ service = [GXRecruitmentService new]; backendInterface = [GXBackendInterface mockWithName:@"bi"]; ! ! ! ! ! ! ! service.backendInterface = backendInterface;});

Page 56: 96% macoun 2013

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)];});

Page 57: 96% macoun 2013

Geburtenkontrolle

• Stub alloc und init Methoden

• Stub Klassen Methoden

•Manchmal muss man sogar eine Extraschicht spendieren

Page 58: 96% macoun 2013

__block GXBackendInterface *backendInterface;__block AFHTTPClient *httpClient;

beforeEach(^{

httpClient = [AFHTTPClient nullMockWithName:@"httpClient"]; [AFHTTPClient stub:@selector(alloc) andReturn:httpClient];

});

Page 59: 96% macoun 2013

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];

});

Page 60: 96% macoun 2013

Was mache ich mit Callback blocks?

• Auf Parameter spionieren

• Callback selber aufrufen

Page 61: 96% macoun 2013

- (void) postMethod:(NSString *)method parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))successBlock {...

[_httpClient postPath:nilparameters:requestParamssuccess:^(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]; }}];

Page 62: 96% macoun 2013

__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"];});

Page 63: 96% macoun 2013

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:otherButtonTitles:) andReturn:alertView];

// expectations [[alertView should] receive:@selector(show)];

// when failureBlock(operation, nil);

});

Page 64: 96% macoun 2013

Kann ich etwas nicht Testen?

• Aufruf von C Funktionen

•Wenn Code auf dem Bildschirm Zeichnet

Page 65: 96% macoun 2013

Kleine Tips

• Given,When,Then Kommentare helfen

• Versuche Wiederverwendung in Tests zu erzielen

• Erstelle Templates um Klassen direkt mit Specs zu erstellen

Page 66: 96% macoun 2013

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?

Page 67: 96% macoun 2013

Fragen?

Page 68: 96% macoun 2013

Vielen Dank@iceX33

Page 69: 96% macoun 2013

Macoun⌘