cocoa heads testing and viewcontrollers

23
Testing and ViewControllers "Extract testable code” & ”Test UI without the simulator”. Small is the beauty!

Upload: stijn-willems

Post on 18-Jul-2015

200 views

Category:

Engineering


9 download

TRANSCRIPT

Testing and ViewControllers

"Extract testable code” &

”Test UI without the simulator”.

Small is the beauty!

• What did I do?

• Why / When / Dangers unit test

• A way to make viewControllers testable

• Make tests visible

What did I do

• TDD at Philips, small and big projects

• Lots of legacy code refactoring

• App that could have benefitted from testing

Unit testing

Integration testing

Webservice

Local device test

External web service

VC’s Mock web service Views

UI Automation (Calabash)

Helped Developers

Helped ?

Legacy code

Legacy class

Sprout Class -> Unit tests

Unit test killers:

• Object should not set there own properties.

• Reach out to a database

• Many dependencies, no default working state on its own

Legacy code

Object should not set there own properties.

class ExampleVC: UIViewController {

let userDefaults = NSUserDefaults.standardUserDefaults() }

class ExampleVC: UIViewController {

var userDefaults : NSUserDefaults? override func viewDidLoad() { super.viewDidLoad() userDefaults = NSUserDefaults.standardUserDefaults() } }

Legacy code

Object should not set there own properties.

class ExampleVC: UIViewController {

lazy var userDefaults : NSUserDefaults = { NSUserDefaults.standardUserDefaults() }() }

Why

Tests written for code coverage are a waste of time

Write them to write better code or stop writing tests!

When

Data Manipulation Draw view

What value should I use for this IndexPath?

I need a list but I have an object with properties

ViewController

Different states

Do not test animations wait for the result

Only visible for a very peculiar state

What value should I use for this IndexPath?

Data Manipulation

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as TableViewCell

cell.label.text = self.datasource.item(indexPath) return cell }

func testThenHasMessageAndDescription() { let resultMessage = tableDatasource.item(NSIndexPath(forItem: 0, inSection: 0)) let resultDescription = tableDatasource.item(NSIndexPath(forItem: 1, inSection: 0)) XCTAssertEqual(resultMessage!, “Message”) XCTAssertEqual(resultDescription!, “Description”) }

Data Manipulation

I need a list but I have an object with properties

let fakeResponse = ["message" : "bla", "description" : "bla some more"] self.mappedArray = [fakeResponse["message"]!, fakeResponse["description"]!]

func item(indexPath: NSIndexPath) -> (String?){

if indexPath.item < mappedArray?.count{ return mappedArray![indexPath.item] }else{ return nil } }

Draw view

Different states

Do not test animations wait for the result

Draw view

- (void)testThenShowInPlaceError { XCTestExpectation *exp = [self expectationWithDescription:@"Wait for error view"]; self.viewController.viewControllerDatasource.respondWithError = YES;

[self.viewController.viewControllerDatasource reloadDataWithDataCompletion:nil failure:nil animationCompletion:^(BOOL success) {

FBSnapshotVerifyView(self.viewController.view, @""); [exp fulfill]; }];

NSTimeInterval animationTime = kAsyncViewsAnimationDuration; [self waitForExpectationsWithTimeout:animationTime + 2 handler:nil]; }

Only visible for a very peculiar state

Draw view

- (void)testThenOfferCancel { id vc = OCMPartialMock([[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"]); //We only use a stub here to have faster test cycles OCMStub([vc async_timeOutDelay]).andReturn(@1); XCTestExpectation *exp = [self expectationWithDescription:@"Wait for cancel"]; [self offerCancelOnViewController:vc exp: exp test:^(XCTestExpectation *exp) { FBSnapshotVerifyView(((UIViewController *) vc).view, @""); [vc stopMocking];

[exp fulfill]; }]; }

Danger

Don’t fall in love with your tests

Make VC’s Testable

Data Manipulation Draw view

ViewController

SharedAsyncDatasource UIViewController+Async

Demo

https://github.com/doozMen/SharedAsyncViewController

Make Tests visible

Tests are just as important as application code. Why not put them together?

Jon Reid

Inspiration

• http://qualitycoding.org/xcode-unit-testing/

• http://iosunittesting.com

• https://github.com/Inferis/IIAsyncViewController

• “Working Effectively with Legacy Code “ Michael Feathers