[cocoaheads tricity] andrzej dąbrowski - dependency injection and testable architecture in swift...

Post on 27-Jan-2017

179 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Testable apps in Swift

Andrzej Dąbrowski andrzej@amplituda.io amplituda.io

A client comes…

– Our Beloved Client

“I have a start-up, I need an app, previous team sucked so I’d like you to continue develop the

project”

Great!Let’s look at the code.

1Split code to independent single-purpose services.

(no tests without that, sorry)

2Write couple of tests.

Example service:

BeaconManager

Public API

Why should I make a wrapper around

CLLocationManager?

• seamlessly manages permissions

• smoothens out beacon power fluctuations

• doesn’t require all listeners to duplicate single beacon filtering code and leaving beacon logic

• enable / disable listening

• saves energy (takes care of switching between monitoring/ranging automatically)

• takes care of background ranging (☠☠☠)

• it’s listeners actually don’t have to care about anything, only implement code on beacon events.

BeaconManager uses another services/APIs

• CLLocationManager for permissions and background ranging (updating location)

• Logger (sends critical logs to back-end)

• Data

• SyncManager

• NSNotificationCenter

BeaconManager is critical service to test

Singletons.Hard to test.

Objective-C dynamic runtime allows us easily change implementation of classes /

methods.

OCMock!

Can I do this in Swift?

Hmm…

Let’s readhttp://ocmock.org/swift/

There are smart people around who claim differently:

http://nshipster.com/swift-objc-runtime/

IMVHO, not the best option.

Where is Swift going?

Will there ever be runtime access in Swift?

I have no idea.

But if Swift is about to be super-fast and super-safe,

I wouldn’t count on it.

Why Obj-C runtime is so great in testing?

• Effortless and quick mocks/stubs

• No refactoring needed at all. Just jump into writing tests.

Disadvantages of OCMock way of testing?

• No compile-time protection

• We can forget to stub some important things

• Encourages a bit to write ugly code (inline mocks / stubs) which could create problems with duplication later

• No explicit list of dependencies like in dependency injection

• Still have to write mocks / stubs :(

Alternatives?

Stubbing based on abstraction layer.

Service Locator or DI

How does it work?

Service Locator

Advantages of SL

• compile-time

• quite quick to implement (actually, sharedInstance properties could be overwritten so that they call Service Locator themselves).

• Service protocols are a beautiful way to investigate app architecture without going too deep into implementation details

Disadvantages of SL

• We need to complicate architecture (is that really bad thing?)

• We can forget to stub some libs

• No explicit list of dependencies (like in DI)

• Still have to write our stubs :(

Dependency injection

"Dependency Injection" is a 25-dollar term for a 5-cent concept.

James Shore

"Dependency Injection" is a 25-dollar term for a 5-cent concept.

James Shore

We must initialise services and inject properties when

app starts.

We could use some automation for initialising

services.

Advantages of DI• compile-time

• explicit list of dependencies (nice app architecture guard)

• we won’t forget to stub anything

• service protocols are a beautiful way to investigate app architecture without going too deep into implementation details

Disadvantages of DI

• Quite not-so-fast to implement

• Architecture gets more complicated (like in SL)

• We still need to write stubs

SL vs. DI

• http://www.martinfowler.com/articles/injection.html

• http://bayou.io/draft/In_Defense_of_Service_Locator.html

• rest of the Internet

Are there any libraries for Dependency Injection?

Typhoon

Swinject

Typhoon

December, 2012 1667StarsFirst github commit

Swinject

July, 2015 454StarsFirst github commit

There’s a single disadvantage of all testing

methods.

No lib with stubs.

I’d like to test like this

Why do I have to write mocks/stubs for Apple or

3rd party libs?

Let’s take a look at modern framework like

angular.js

Which iOS frameworks could be easily stubbed not to duplicate code?

Summary• method / class swizzling is probably not what you want

in Swift

• service locator is quickest way to get legacy code tested

• typhoon and swinject are 3rd party libs for Swift testing

• swinject seems to be nice

• unfortunately, there are no libraries which out of the box give developers stubs / mocks for Apple APIs.

Thank you

top related