Automatisierte Akzeptanztests und TDD für iOS · 2016-11-10 · Automatisierte Akzeptanztests und...

Post on 10-Aug-2020

0 views 0 download

Transcript of Automatisierte Akzeptanztests und TDD für iOS · 2016-11-10 · Automatisierte Akzeptanztests und...

Automatisierte Akzeptanztests und

TDD für iOS

Sven Günther - it-agile GmbH

Donnerstag, 6. Dezember 12

User Storys

Als <Rolle> möchte ich <Funktionalität> damit

<Geschäftswert>

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

User Story

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

User Story User Story

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

User Story User Story User Story

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

User Story User Story User Story

Story-Splitting

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

Example 1

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

Example 1

Example II

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

Example 1

Example II

Example III

Donnerstag, 6. Dezember 12

Woher kommen die Details?

User Story

Example 1

Example II

Example III

Examples

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel beschreibt die Anforderungen

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

ausführbare Schritte

beschreibt die Anforderungen

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

ausführbare Schritte

beschreibt die Anforderungen

bildet Vokabular ab

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

ausführbare Schritte

Treiber

beschreibt die Anforderungen

bildet Vokabular ab

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

ausführbare Schritte

Treiber

beschreibt die Anforderungen

bildet Vokabular ab

steuert die zu testende Anwendung

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

ausführbare Schritte

Treiber

Anwendung

beschreibt die Anforderungen

bildet Vokabular ab

steuert die zu testende Anwendung

Donnerstag, 6. Dezember 12

Anatomie einer ausführbaren Spezifikationen

Ausführbares Beispiel

ausführbare Schritte

Treiber

Anwendung

beschreibt die Anforderungen

bildet Vokabular ab

steuert die zu testende Anwendung

getestetes System

Donnerstag, 6. Dezember 12

Cucumber

Donnerstag, 6. Dezember 12

Cucumberhttp://cukes.info

Donnerstag, 6. Dezember 12

Cucumberhttp://cukes.info

works with Ruby, Java, .NET, Flex or web applications written in any language

Donnerstag, 6. Dezember 12

Cucumberhttp://cukes.info

works with Ruby, Java, .NET, Flex or web applications written in any language

gem install cucumber

Donnerstag, 6. Dezember 12

Given - When - Then

Given <Vorbedingung>

When <Handlung, Aktion>

Then <beobachtbares Ergebnis>

Donnerstag, 6. Dezember 12

Given - When - Then

Given the browser shows the google homepage

When I enter "iPhone" into the the search field

Then I should see search results regarding "iPhone"

Donnerstag, 6. Dezember 12

Feature: AdditionIn order to avoid silly mistakesAs a math idiotI want to be told the sum of two numbers

Scenario: Add two numbersGiven I have entered 50 into the calculatorAnd I have entered 70 into the calculatorWhen I press addThen the result should be 120 on the screen

Feature-File

Donnerstag, 6. Dezember 12

Step-Definition

Given /I have entered (.*) into the calculator/ do |n|calculator = Calculator.newcalculator.push(n.to_i)

end

Donnerstag, 6. Dezember 12

Frank

Donnerstag, 6. Dezember 12

Frankwww.testingwithfrank.com

Donnerstag, 6. Dezember 12

Frankwww.testingwithfrank.com

Initiiert von Pete Hodgson (Thoughtworks)

Donnerstag, 6. Dezember 12

Frankwww.testingwithfrank.com

Initiiert von Pete Hodgson (Thoughtworks)

iOS-Treiber für cucumber

Donnerstag, 6. Dezember 12

Frankwww.testingwithfrank.com

Initiiert von Pete Hodgson (Thoughtworks)

iOS-Treiber für cucumber

Donnerstag, 6. Dezember 12

Demo

Donnerstag, 6. Dezember 12

TDD

Donnerstag, 6. Dezember 12

Warum TDD?

Donnerstag, 6. Dezember 12

Warum TDD?

Besseres Design weil

Donnerstag, 6. Dezember 12

Warum TDD?

Besseres Design weil

• voneinander losgelöste Einheiten entstehen

Donnerstag, 6. Dezember 12

Warum TDD?

Besseres Design weil

• voneinander losgelöste Einheiten entstehen

• die früh in der Entwicklung benutzt werden (durch die Tests)

Donnerstag, 6. Dezember 12

Warum TDD?

Besseres Design weil

• voneinander losgelöste Einheiten entstehen

• die früh in der Entwicklung benutzt werden (durch die Tests)

Sicherheitsnetz durch durchgängige Testsuite

Donnerstag, 6. Dezember 12

Wie ???

Donnerstag, 6. Dezember 12

Wie ???

Test

neue Funktionalität wird durch Test beschrieben

Donnerstag, 6. Dezember 12

Wie ???

Test

neue Funktionalität wird durch Test beschrieben

GreenFunktionalität wird

implementiert

Donnerstag, 6. Dezember 12

Wie ???

Test

neue Funktionalität wird durch Test beschrieben

GreenFunktionalität wird

implementiertRefactorCode wird aufgeräumt

Donnerstag, 6. Dezember 12

Wie ???

Test

neue Funktionalität wird durch Test beschrieben

GreenFunktionalität wird

implementiertRefactorCode wird aufgeräumt

Donnerstag, 6. Dezember 12

OCUnit - Anatomie eines Tests

Donnerstag, 6. Dezember 12

OCUnit - Anatomie eines Tests

#import <SenTestingKit/SenTestingKit.h>

Donnerstag, 6. Dezember 12

OCUnit - Anatomie eines Tests

#import <SenTestingKit/SenTestingKit.h>

@interface SmokeTest : SenTestCase@end

Donnerstag, 6. Dezember 12

OCUnit - Anatomie eines Tests

#import <SenTestingKit/SenTestingKit.h>

@interface SmokeTest : SenTestCase@end

@implementation SmokeTest

Donnerstag, 6. Dezember 12

OCUnit - Anatomie eines Tests

#import <SenTestingKit/SenTestingKit.h>

@interface SmokeTest : SenTestCase@end

@implementation SmokeTest

- (void)testThatItHaveSmoked {! STAssertEqualObjects(@"foo", @"bar", @"Description");}

Donnerstag, 6. Dezember 12

OCUnit - Anatomie eines Tests

#import <SenTestingKit/SenTestingKit.h>

@interface SmokeTest : SenTestCase@end

@implementation SmokeTest

- (void)testThatItHaveSmoked {! STAssertEqualObjects(@"foo", @"bar", @"Description");}

@end

Donnerstag, 6. Dezember 12

setup / tearDown

Donnerstag, 6. Dezember 12

setup / tearDown

@implementation SmokeTest

Donnerstag, 6. Dezember 12

setup / tearDown

@implementation SmokeTest

- (void)setUp {! // initialisiere Testumgebung}

Donnerstag, 6. Dezember 12

setup / tearDown

@implementation SmokeTest

- (void)setUp {! // initialisiere Testumgebung}

- (void)tearDown {! // räume Testumgebung wieder ab}

Donnerstag, 6. Dezember 12

setup / tearDown

@implementation SmokeTest

- (void)setUp {! // initialisiere Testumgebung}

- (void)tearDown {! // räume Testumgebung wieder ab}

Donnerstag, 6. Dezember 12

setup / tearDown

@implementation SmokeTest

- (void)setUp {! // initialisiere Testumgebung}

- (void)tearDown {! // räume Testumgebung wieder ab}

- (void)test... {}

Donnerstag, 6. Dezember 12

setup / tearDown

@implementation SmokeTest

- (void)setUp {! // initialisiere Testumgebung}

- (void)tearDown {! // räume Testumgebung wieder ab}

- (void)test... {}

@end

Donnerstag, 6. Dezember 12

MeinObjektTest

testMachtDies

testMachtDas

testMachtJenes

Tests als Dokumentation

Donnerstag, 6. Dezember 12

MeinObjekt

MachtDies

MachtDas

MachtJenes

Tests als Dokumentation

Donnerstag, 6. Dezember 12

Assertions prüfen

Donnerstag, 6. Dezember 12

STAssertEqualObjects(@"foo", @"bar", @"foo should be bar");

STAssertEquals(6*7, 45, @"6 x 7 should be 42");

STAssertNil(nil, @"nil should be nil");

Assertions prüfen

Donnerstag, 6. Dezember 12

STAssertEqualObjects(@"foo", @"bar", @"foo should be bar");

STAssertEquals(6*7, 45, @"6 x 7 should be 42");

STAssertNil(nil, @"nil should be nil");

NSArray *array = @[foo, bar];STAssertTrue([array indexOfObject:foo] > 0, @"array should contain foo");

STAssertEqualObjects(@"foo", @"bar", @"foo should be bar");

STAssertEquals(6*7, 45, @"6 x 7 should be 42");

STAssertNil(nil, @"nil should be nil");

Assertions prüfen

Donnerstag, 6. Dezember 12

STAssertEqualObjects(@"foo", @"bar", @"foo should be bar");

STAssertEquals(6*7, 45, @"6 x 7 should be 42");

STAssertNil(nil, @"nil should be nil");

NSArray *array = @[foo, bar];STAssertTrue([array indexOfObject:foo] > 0, @"array should contain foo");

STAssertEqualObjects(@"foo", @"bar", @"foo should be bar");

STAssertEquals(6*7, 45, @"6 x 7 should be 42");

STAssertNil(nil, @"nil should be nil");

Assertions prüfenSTAssertEqualObjects(@"foo", @"bar", @"foo should be bar");

STAssertEquals(6*7, 45, @"6 x 7 should be 42");

STAssertNil(nil, @"nil should be nil");

NSArray *array = @[foo, bar];STAssertTrue([array indexOfObject:foo] > 0, @"array should contain foo");

"[array indexOfObject:foo] > 0" should be true. array should contain foo

Donnerstag, 6. Dezember 12

Expecta

Donnerstag, 6. Dezember 12

github.com/petejkim/expecta

Expecta

Donnerstag, 6. Dezember 12

github.com/petejkim/expecta

expect(foo).to.equal(@"foo");expect(bar).notTo.equal(@"foo");

github.com/petejkim/expecta

Expecta

Donnerstag, 6. Dezember 12

github.com/petejkim/expecta

expect(foo).to.equal(@"foo");expect(bar).notTo.equal(@"foo");

NSArray *array = @[bar, foobar];expect(array).to.contain(foo);

github.com/petejkim/expecta

expect(foo).to.equal(@"foo");expect(bar).notTo.equal(@"foo");

github.com/petejkim/expecta

Expecta

Donnerstag, 6. Dezember 12

github.com/petejkim/expecta

expect(foo).to.equal(@"foo");expect(bar).notTo.equal(@"foo");

NSArray *array = @[bar, foobar];expect(array).to.contain(foo);

github.com/petejkim/expecta

expect(foo).to.equal(@"foo");expect(bar).notTo.equal(@"foo");

github.com/petejkim/expectagithub.com/petejkim/expecta

expect(foo).to.equal(@"foo");expect(bar).notTo.equal(@"foo");

NSArray *array = @[bar, foobar];expect(array).to.contain(foo);

expected (bar, foobar) to contain foo

Expecta

Donnerstag, 6. Dezember 12

Expecta

Donnerstag, 6. Dezember 12

expect(x).to.haveCountOf(y);

Expecta

Donnerstag, 6. Dezember 12

expect(x).to.haveCountOf(y);

expect(x).to.beEmpty();

Expecta

Donnerstag, 6. Dezember 12

expect(x).to.haveCountOf(y);

expect(x).to.beEmpty();

expect(x).to.beLessThan(y);

Expecta

Donnerstag, 6. Dezember 12

expect(x).to.haveCountOf(y);

expect(x).to.beEmpty();

expect(x).to.beLessThan(y);

expect(x).to.beGreaterThan(y);

Expecta

Donnerstag, 6. Dezember 12

expect(x).to.haveCountOf(y);

expect(x).to.beEmpty();

expect(x).to.beLessThan(y);

expect(x).to.beGreaterThan(y);

expect(x).to.beCloseToWithin(y, z);

Expecta

Donnerstag, 6. Dezember 12

Expecta

Donnerstag, 6. Dezember 12

expect(x).will.beNil();

Expecta

Donnerstag, 6. Dezember 12

expect(x).will.beNil();

[Expecta setAsynchronousTestTimeout:x]

Expecta

Donnerstag, 6. Dezember 12

Expecta

Donnerstag, 6. Dezember 12

@interface LightSwitch : NSObject

Expecta

Donnerstag, 6. Dezember 12

@interface LightSwitch : NSObject

@property (nonatomic, assign, getter=isTurnedOn) BOOL turnedOn;

Expecta

Donnerstag, 6. Dezember 12

@interface LightSwitch : NSObject

@property (nonatomic, assign, getter=isTurnedOn) BOOL turnedOn;

@end

Expecta

Donnerstag, 6. Dezember 12

@interface LightSwitch : NSObject

@property (nonatomic, assign, getter=isTurnedOn) BOOL turnedOn;

@end

expect(lightSwitch).isTurnedOn();

Expecta

Donnerstag, 6. Dezember 12

Demo

Donnerstag, 6. Dezember 12

Test-Stellvertreter

• dienen als Stellvertreter für reale Objekte

Donnerstag, 6. Dezember 12

Test-Stellvertreter

• dienen als Stellvertreter für reale Objekte

• sind essentiell zum Entkoppeln von Abhängigkeiten

Donnerstag, 6. Dezember 12

Test-Stellvertreter

• dienen als Stellvertreter für reale Objekte

• sind essentiell zum Entkoppeln von Abhängigkeiten

• Simulieren Interaktionen mit anderen Objekten

Donnerstag, 6. Dezember 12

Test-Stellvertreter

• dienen als Stellvertreter für reale Objekte

• sind essentiell zum Entkoppeln von Abhängigkeiten

• Simulieren Interaktionen mit anderen Objekten

- Mocks = Stellvertreter die ein erwartetes Verhalten überprüfen

Donnerstag, 6. Dezember 12

Test-Stellvertreter

• dienen als Stellvertreter für reale Objekte

• sind essentiell zum Entkoppeln von Abhängigkeiten

• Simulieren Interaktionen mit anderen Objekten

- Mocks = Stellvertreter die ein erwartetes Verhalten überprüfen

- Stubs = Stellvertreter mit einem definierten Ein- / Ausgabeverhalten

Donnerstag, 6. Dezember 12

Abhängigkeiten abschneiden

MyClass

Donnerstag, 6. Dezember 12

Abhängigkeiten abschneiden

MyClass OtherClassuses

Donnerstag, 6. Dezember 12

Abhängigkeiten abschneiden

MyClass

MyTest

OtherClassuses

tests

Donnerstag, 6. Dezember 12

Abhängigkeiten abschneiden

MyClass

MyTest

OtherClass

a Mock

uses

tests pretends to be

Donnerstag, 6. Dezember 12

Abhängigkeiten abschneiden

MyClass

MyTest

OtherClass

a Mock

uses

tests pretends to be

uses

Donnerstag, 6. Dezember 12

Dependency Injection

Donnerstag, 6. Dezember 12

Dependency Injection

• Klassen erzeugen von selbst keine neuen Abhängigkeiten

Donnerstag, 6. Dezember 12

Dependency Injection

• Klassen erzeugen von selbst keine neuen Abhängigkeiten

- z.B. kein [[... alloc] init]

Donnerstag, 6. Dezember 12

Dependency Injection

• Klassen erzeugen von selbst keine neuen Abhängigkeiten

- z.B. kein [[... alloc] init]

• Abhängigkeiten werden von außen hereingereicht

Donnerstag, 6. Dezember 12

Dependency Injection

• Klassen erzeugen von selbst keine neuen Abhängigkeiten

- z.B. kein [[... alloc] init]

• Abhängigkeiten werden von außen hereingereicht

- setter (@property)

Donnerstag, 6. Dezember 12

Dependency Injection

• Klassen erzeugen von selbst keine neuen Abhängigkeiten

- z.B. kein [[... alloc] init]

• Abhängigkeiten werden von außen hereingereicht

- setter (@property)

- Konstruktor (initWith...)

Donnerstag, 6. Dezember 12

OCMockito

Donnerstag, 6. Dezember 12

OCMockitogithub.com/jonreid/OCMockito

Donnerstag, 6. Dezember 12

OCMockitogithub.com/jonreid/OCMockito

#define HC_SHORTHAND#import <OCHamcrestIOS/OCHamcrestIOS.h>

Donnerstag, 6. Dezember 12

OCMockitogithub.com/jonreid/OCMockito

#define HC_SHORTHAND#import <OCHamcrestIOS/OCHamcrestIOS.h>

#define MOCKITO_SHORTHAND#import <OCMockitoIOS/OCMockitoIOS.h>

Donnerstag, 6. Dezember 12

Beispiel Mocks

Donnerstag, 6. Dezember 12

Beispiel Mocks

NSMutableArray *mockArray = mock([NSMutableArray class]);

Donnerstag, 6. Dezember 12

Beispiel Mocks

NSMutableArray *mockArray = mock([NSMutableArray class]);

[mockArray addObject:@"one"];[mockArray removeAllObjects];

Donnerstag, 6. Dezember 12

Beispiel Mocks

NSMutableArray *mockArray = mock([NSMutableArray class]);

[mockArray addObject:@"one"];[mockArray removeAllObjects];

[verify(mockArray) addObject:@"one"];[verify(mockArray) removeAllObjects];

Donnerstag, 6. Dezember 12

Beispiel Stub

Donnerstag, 6. Dezember 12

Beispiel Stub

NSArray *mockArray = mock([NSArray class]);

Donnerstag, 6. Dezember 12

Beispiel Stub

NSArray *mockArray = mock([NSArray class]);

[given([mockArray objectAtIndex:0]) willReturn:@"first"];

Donnerstag, 6. Dezember 12

Beispiel Stub

NSArray *mockArray = mock([NSArray class]);

[given([mockArray objectAtIndex:0]) willReturn:@"first"];

NSLog(@"%@", [mockArray objectAtIndex:0]);

Donnerstag, 6. Dezember 12

Demo

Donnerstag, 6. Dezember 12

Fragen?

Donnerstag, 6. Dezember 12

Fragen?

http://www.it-agile.de/mobile.html

Donnerstag, 6. Dezember 12