Go for Quality - automatisiertes Testen in iOS

Post on 06-May-2015

241 views 2 download

description

Für die Entwicklung konsequent stabiler Software, sind automatisierte Tests unabdingbar. Es geht nicht nur um das Auffinden von Fehlern, sondern darum, Komponenten einer Software funktional korrekt und technisch stabil zu entwickeln. Dies gilt gerade für mobile Apps. Diese Session bietet eine Einführung in die Welt der automatisierten Tests unter iOS. Der Fokus liegt hierbei auf den Möglichkeiten von User Interface Tests. Damit hat der leidige Klick-Test nach jeder Änderung ein Ende und die App funktioniert auch nach dem nächsten Release wie gewohnt - versprochen!

Transcript of Go for Quality - automatisiertes Testen in iOS

Go for Quality - automatisiertes Testen in iOS Michael Kotten | open knowledge GmbH @michaelkotten

@_openKnowledge

MTD 2014

„Chuck Norris can unit test

entire applications with a single

assert.“

Facts of the day Go for Quality - automatisiertes Testen in iOS

Warum testen?

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

„Wer testet, ist feige!“

„Ich weiß doch, dass mein Code

funktioniert!“

„Wenn ich den Test selber schreibe, hat es eh keinen Sinn!“

„Keine Zeit für Unit Tests!“

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

„Unit testing is not about finding bugs.“

‣  Notwendig bei komplexen Systemen

‣  Sicherung von ‣  Qualität ‣  Funktionalität

‣  Wichtig bei agilen Entwicklungsprozessen ‣  Schnelle Entwicklungszyklen

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

Wie testen?

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

eXtreme Clicking

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

nur auf dem Entwicklerrechner

Motivation Go for Quality - automatisiertes Testen in iOS

MTD 2014

Kunden

Motivation Go for Quality - automatisiertes Testen in iOS

MTD 2014

Motivation Go for Quality - automatisiertes Testen in iOS

MTD 2014

Expect the Unexpected!

Anforderungen an Testabdeckung ‣  Alles “Offensichtliche” plus …"

‣  … Umwelteinflüsse & Störungen ‣  … System Notifications ‣  … zu unterstützende Devices, Locales …

Motivation Go for Quality - automatisiertes Testen in iOS

MTD 2014

Was testen?

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

Go for Quality - automatisiertes Testen in iOS MTD 2014

Motivation

„It makes no sense "to test something that "

can’t be broken (or fixed)!“ (Zitat: alter weiser Mann)

Gute Tests ... ‣ … treffen Annahmen nur einmal ‣ … sind isoliert ‣ … laufen unabhängig ‣ … sind vorhersehbar

Motivation Go for Quality - automatisiertes Testen in iOS

MTD 2014

Unit Test ‣  Testen der korrekten Funktionsweise

einzelner, isolierter Komponenten

‣  Automatisiert ‣  Wiederholbar

Motivation Go for Quality - automatisiertes Testen in iOS

MTD 2014

Tests in Action Go for Quality - automatisiertes Testen in iOS

MTD 2014

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

OCUnit a.k.a SenTestingKit ‣  basiert auf SUnit* von Kent Beck ‣  eingeführt 2005 mit Xcode 2.1 ‣  seit Xcode 5 obsolet

* Mutter aller Test Frameworks

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

XCTest ‣  Apple-eigenes Test Framework ‣  ähnelt stark OCUnit ‣  Standard Test Framework seit Xcode 5

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

@interface Calculator : NSObject -(int) add:(int)a to:(int)b; -(int) subtract:(int)a from:(int)b; -(float) divide:(int)a by:(int)b; @end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

@interface CalculatorTests : XCTestCase @end @implementation CalculatorTests + (void) setUp {...} + (void) tearDown {...} - (void) setUp {...} - (void) tearDown {...}

- (void) testMyMethod {...}

@end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

#import "Calculator.h" @interface CalculatorTests : XCTestCase { Calculator* calculator; } @end @implementation CalculatorTests - (void) setUp { calculator = [[Calculator alloc] init]; } @end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

@implementation CalculatorTests - (void) setUp { calculator = [[Calculator alloc] init]; } - (void) testAdd { int result = [calculator add:5 to:6]; XCTAssertEqual(result, 11, @"result should be 11"); } @end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

XCTFail (format…) XCTAssertNil (a1, format…) XCTAssertNotNil (a1, format…) XCTAssert (a1, format…) XCTAssertTrue (a1, format…) XCTAssertFalse (a1, format…) XCTAssertEqualObjects (a1, a2, format…) XCTAssertEquals (a1, a2, format…) XCTAssertEqualsWithAccuracy (a1, a2, accuracy, format…) XCTAssertThrows (expression, format…) XCTAssertThrowsSpecific (expression, specificException, format…) XCTAssertThrowsSpecificNamed (expression, specificException, exceptionName, format…) XCTAssertNoThrow (expression, format…) XCTAssertNoThrowSpecific (expression, specificException, format…) XCTAssertNoThrowSpecificNamed (expression, specificExcepton, exceptionName, format…)

* siehe XCTestAssertions.h

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Code Diving

CalculatorTests

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Pitfall 1: Multithreading @interface Calculator : NSObject ... -(void) calculateSenseOfLife:(void(^)(int))answer; @end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Pitfall 1: Multithreading - (void) testCalculateSenseOfLife { Calculator* calculator = [[Calculator alloc]init]; [calculator calculateSenseOfLife:^(int answer) { XCTAssertEqual(answer, 23); }]; }

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Code Diving

Multithreading

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Pitfall 2: Umgang mit Abhängigkeiten ‣  Unit soll getestet werden ‣  Abhängigkeiten zu anderen „Units“ bestehen ‣  Lösung: Mocks statt realer Objekte

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

OCMock* ‣  Mocking Framework ‣  Täuscht Schnittstellen vor ‣  Deterministisches Verhalten

* http://www.ocmock.org

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

@interface Controller @property (weak, nonatomic) TwitterConnection* connection; @property (weak, nonatomic) IBOutlet TweetView* tweetView; - (void) displayTweets; @end @implementation Controller -(void) displayTweets { NSArray *tweets = [connection retrieveTweets]; for (Tweet t in tweets) { [self.tweetView addTweet:t]; } @end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

@implementation ControllerTests - (void)testDisplayTweets { Controller* controller = [[Controller alloc] init]; id connection =

[OCMockObject mockForClass:[TwitterConnection class]]; controller.connection = connection; Tweet *testTweet = /* create a tweet somehow */; NSArray *tweetArray = [NSArray arrayWithObject:testTweet]; [[[connection stub] andReturn:tweetArray] displayTweets]; } @end

Stubs

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

@implementation ControllerTests - (void)testDisplayTweets { ... id view = [OCMockObject mockForClass:[TweetView class]]; controller.tweetView = view; [[view expect] addTweet:testTweet]; [controller displayTweets]; [view verify]; } @end

Expect & Verify

Und jetzt?

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

UI Automation

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Was ist UI Automation? ‣  JavaScript ‣  Integriert in Instruments ‣  benötigt Accessibility Features ‣  On-Device und Simulator

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

UIAElement ‣  Basisklasse für alle UI Elemente ‣  Name ‣  Value ‣  Elements ‣  Parent

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Control Hierarchie ‣  Target Application

UIATarget.localTarget().frontMostApp();!

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Control Hierarchie ‣  Target Application ‣  Main Window

UIATarget.localTarget().frontMostApp()!.mainWindow();!

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Control Hierarchie ‣  Target Application ‣  Main Window ‣  View

UIATarget.localTarget().frontMostApp()!.mainWindow().staticTexts()[0];!

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Control Hierarchie ‣  Target Application ‣  Main Window ‣  View

UIATarget.localTarget().frontMostApp()!.mainWindow().buttons()["add"];!

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Interaktion UIATarget.localTarget().frontMostApp() .mainWindow().buttons()["add"].tap(); UIATarget.localTarget().frontMostApp() .mainWindow().textFields()[0].setValue("Hello"); UIATarget.localTarget().frontMostApp() .mainWindow().tableViews()[0] .scrollToElementWithPredicate("name beginswith ‘Foo’");

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Timeouts UIATarget.localTarget().pushTimeout(2); UIATarget.localTarget().popTimeout(); UIATarget.localTarget().delay(2);

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Lifecycle var testName = "do something"; UIALogger.logStart(testName); ... if (testPassed){

UIALogger.logPass(testName); } else {

UIALogger.logFail(testName); }

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Debugging UIALogger.logMessage("I am here!"); UIATarget.localTarget() .logElementTree(); UIATarget.localTarget() .captureScreenWithName("Screenshot-001");

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

Assertions #import "lib/tuneup_js/tuneup.js test("Checking label text", function(target, app) { var labelText = app.mainWindow().staticTexts()[0].value(); assertEquals(labelText, "Hello World"); });

http://www.tuneupjs.org

Go for Quality - automatisiertes Testen in iOS MTD 2014

UI Automation in Action

test("my test", function(target, app) { assertWindow({

tableViews: [ { groups: [ { name: "First Name" }, { name: "Last Name" } ], cells: [ { name: "Fred" }, { name: "Flintstone" } ] } ]}); });

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Code Diving

UI Automation

Go for Quality - automatisiertes Testen in iOS MTD 2014

KIF in Action

KIF – Keep It Functional

https://github.com/kif-framework/KIF

Go for Quality - automatisiertes Testen in iOS MTD 2014

KIF in Action

KIF – Keep It Functional ‣  Objective-C ‣  KIFTestCase : XCTestCase ‣  Integration in XCode ‣  Test Navigator ‣  Debugging

Go for Quality - automatisiertes Testen in iOS MTD 2014

KIF in Action

KIFUITestActor ‣  als tester in jedem KIFTestCase ‣  „tap this view“ ‣  „enter text into this view“ ‣  „wait for this view“

Go for Quality - automatisiertes Testen in iOS MTD 2014

KIF in Action

Installation via Cocoapods

target 'CalculatorTests', :exclusive => true do pod 'KIF', '~> 3.0' end pod install

Go for Quality - automatisiertes Testen in iOS MTD 2014

KIF in Action

@implementation CalculatorUiTests - (void) testAdd { [tester tapViewWithAccessibilityLabel:@"one"]; [tester tapViewWithAccessibilityLabel:@"add"]; [tester tapViewWithAccessibilityLabel:@"two"]; [tester tapViewWithAccessibilityLabel:@"equal"]; UILabel* display = (UILabel*)[tester waitForViewWithAccessibilityLabel:@"display"]; XCTAssertEqualObjects(display.text, @"3", @"result should be 3"); } @end

Go for Quality - automatisiertes Testen in iOS MTD 2014

Tests in Action

Code Diving

Keep It Functional

UI Automation Keep it Functional

Sprache Javascript Objective-C

Accessibility ✔ ✔

XCode Integration ✖ ✔

Debugging ✖ ✔

Mocking ✖ ✔

Continuous Integration ✔ ✔

Maintainer Apple Community

Go for Quality - automatisiertes Testen in iOS MTD 2014

KIF vs. UI Automation

One more thing ...

Social Media

One more thing… Go for Quality - automatisiertes Testen in iOS

MTD 2014

Broken Windows Theorie

Go for Quality - automatisiertes Testen in iOS Michael Kotten | open knowledge GmbH @michaelkotten

@_openKnowledge