Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unit Testing WTWs

Unit Testing WTWs

A tale about what *surprised* me *while* unit *testing*...

Meetup: https://www.meetup.com/Poznan-iOS-Developers-Meetup/events/230893632/

Maciej Piotrowski

May 12, 2016
Tweet

More Decks by Maciej Piotrowski

Other Decks in Programming

Transcript

  1. I have met 3 types of programmers · a few

    ones that say unit testing is cool ❤
  2. I have met 3 types of programmers · some that

    don't know how the ! can they start doing it?
  3. Standard bla bla bla... In computer programming, unit testing is

    a so!ware testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use. — Wikipedia
  4. WT! a unit test is? · unit test = checks(!

    ← interaction " → !) == ✅
  5. WT! a unit test is? "BluetoothModule" "when turned on" "advertises

    services" "when turned off" "doesn't advertise services"
  6. What the ! spec?! context("BluetoothModule") { describe("when turned on") {

    it("advertises services") {} } describe("when turned off") { it("doesn't advertise services") {} } }
  7. What the ! spec?! import Quick import Nimble @testable import

    <#Module#> class <#TestedClass#>Spec: QuickSpec { override func spec() { //!Magic goes here "#$ } }
  8. Arrange phase class BluetoothModuleSpec: QuickSpec { override func spec() {

    context("BluetoothModule") { //i.e. newly initialized var sut: BluetoothModule! var peripheralManager: CBPeripheralManagerProtocol! beforeEach { peripheralManager = MockPeripheralManager() sut = BluetoothModule(peripheralManager: peripheralManager) } afterEach { peripheralManager = nil sut = nil } } } }
  9. Arrange phase · context - description of object's state (e.g.

    object is newly initialised) · beforeEach - local variables setup (XCTest's setup) · a!erEach - local variables cleanup (XCTest's tearDown)
  10. Act phase ! ... And all the men and women

    merely players ... — Shakespeare !
  11. Act phase context("BluetoothModule") { //... describe("when turned on") { beforeEach

    { sut.turnOn() } } describe("when turned off") { beforeEach { sut.turnOff() } } }
  12. Act phase · describe - description of action performed on

    the subject · beforeEach - action on the sut (subject of unit testing)
  13. Assert phase context("BluetoothModule") { describe("when turned on") { //... it("advertises

    services") { expect(peripheralManager.isAdvertising) .to(beTrue()) } } }
  14. Assert phase context("BluetoothModule") { describe("when turned off") { //... it("advertises

    services") { expect(peripheralManager.isAdvertising) .to(beFalse()) } } }
  15. What to ! expect? · Nimble ! provides a number

    of matchers · Matchers are used in it blocks to assert the expectation ✅
  16. What to ! expect? extension MyClass: Equatable {} func ==(lhs:

    MyClass, rhs: MyClass) -> Bool { return lhs.propertyX == rhs.propertyX && lhs.propertyY == rhs.propertyY && lhs.propertyZ == rhs.propertyZ }
  17. What to ! expect? extension MyClass: Equatable {} func ==(lhs:

    MyClass, rhs: MyClass) -> Bool { return ObjectIdetifier(lhs) == ObjectIdentifier(rhs) }
  18. What to ! expect? class class1: NSObject {} class class2:

    NSObject {} let c1 = class1() let c2 = class2() it("should not be equal") { expect(c1).toNot(equal(c2)) }
  19. What's a Mock? protocol CBPeripheralManagerProtocol: class { //... weak var

    delegate: CBPeripheralManagerDelegate { get set } func startAdvertising() func stopAdvertising() }
  20. If you don't you will end up with inheritance and

    partial mocks, which is not recommended...
  21. What's a Mock? context("BluetoothModule") { describe("when turned on") { //...

    it("advertises services") { expect(peripheralManager.startAdvertisingCount) .to(equal(1)) } } }
  22. Unit test all the things! ! context("ViewController") { describe("when view

    loads") { beforeEach { sut.viewDidLoad() } it("does sth") { expect(sut.didSomething).to(beTrue()) } } }
  23. Unit test all the things! ! it("has right button") {

    expect(sut.navigationItem.rightBarButtonItem) .to(beAKindOf(UIBarButtonItem)) expect(sut.navigationItem.rightBarButtonItem?.enabled) .to(beTrue()) }
  24. Unit test all the things! ! Unit Test Helper comes

    in handy class UnitTestHelper { class func presentViewControllerModally(vc: UIViewController) {} class func tap(button: UIButton?) {} class func tap(button: UIBarButtonItem?) {} //... }
  25. Unit test all the things! ! describe("tap on the right

    button") { beforeEach { Helper.tap(sut.navigationItem.rightBarButtonItem) } it("shows my other view controller") { expect(sut.presentedViewController) .toEventually(beAKindOf(MyOtherViewController)) } }
  26. Do pure Swift objects have load() ?! ! class MyViewModel

    { func load() {} } class MyViewController: UIViewController { let viewModel = MyViewModel() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.whiteColor() viewModel.load() } }
  27. Do pure Swift objects have load() ?! ! describe("when view

    loads") { beforeEach { sut.viewDidLoad() } it("calls load on viewModel") { expect(viewModel.loadCount) .to(equal(1)) //ASSERTION FAILURE: expected 1, got 2 } }
  28. Do pure Swift objects have load() ?! ! //The view

    controller calls this method //when its view property is requested but is currently nil. func loadView()
  29. What is it all f!r ? · getting to know

    ! Apple frameworks better
  30. Resources · swi!ing.io - code quality and unit testing ·

    Paweł Dudek - BDD presentastions · objc.io - issue #15 · realm.io - Real-world mocking in Swi!