Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Swift testing ftw

978 views

Published on

Talk for the Appsterdam community 20150520:
Brief introduction to unit testing and some of the most relevant aspect of writing unit tests in Swift.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Swift testing ftw

  1. 1. Swift Testing FTW! Jorge D. Ortiz-Fuentes @jdortiz #SwiftTesting
  2. 2. A Canonical Examples production #SwiftTesting
  3. 3. #SwiftTesting Agenda ★ Basics about unit testing ★ 4 challenges of Swift Testing ★ Proposed enhancements
  4. 4. Basics about Unit Testing
  5. 5. But my code is always awesome!
  6. 6. #SwiftTesting Unit Tests ★ Prove correctness of different aspects of the public interface. • Prove instead of intuition • Define contract and assumptions • Document the code • Easier refactoring or change ★ Reusable code = code + tests
  7. 7. #SwiftTesting Use Unit Testing Incrementally ★ You don’t have to write every unit test ★ Start with the classes that take care of the logic • If mixed apply SOLID ★ The easier entry point is fixing bugs
  8. 8. Time writing tests < Time debugging
  9. 9. Ask for your wishes
  10. 10. #SwiftTesting Types of Unit Tests ★ Test return value ★ Test state ★ Test behavior
  11. 11. #SwiftTesting The Rules of Testing ★ We only test our code ★ Only a level of abstraction ★ Only public methods ★ Only one assertion per test ★ Tests are independent of sequence or state
  12. 12. 4 Challenges of Swift Testing
  13. 13. Lost
  14. 14. #SwiftTesting New to Swift ★ Still learning the language ★ Functional Paradigm ★ Swift has bugs
  15. 15. #SwiftTesting Implicitly unwrapped SUT ★ SUT cannot be created in init ★ Thus, it needs to be optional ★ But once set in setUp, it never becomes nil ★ Syntax is clearer with an implicitly unwrapped optional.
  16. 16. #SwiftTesting XCTAssertEquals ★ Works with non custom objects ★ But requires objects to be equatable ★ Use reference comparison instead
  17. 17. #SwiftTesting func createSut() { interactor = ShowAllSpeakersInteractorMock() sut = SpeakerListPresenter(interactor: interactor) view = SpeakersListViewMock() sut.view = view } func testViewIsPersisted() { if let persitedView = shut.view as? SpeakersListViewMock { XCTAssertTrue(persistedView === view, “Wrong view persisted”) } else { XCTFail(“View must be persisted”) } } Example: Test persistence public class SpeakersListPresenter { let interactor: ShowAllSpeakersInteractorPro tocol public weak var view SpeakersListViewProtocol? public init(interactor: ShowAllSpeakersInteractorPro tocol) { self.interactor = interaction } }
  18. 18. No Courage
  19. 19. #SwiftTesting Room for improvement ★ Brian Gesiak: XCTest: The Good Parts: • Replace/customize Testing frameworks • XCTAssertThrows • assert/precondition • 1,000+ tests ★ I add: • Run tests without the simulator • Jon Reid provides a method to speed up AppDelegate launch, but not for Swift
  20. 20. No Brains
  21. 21. #SwiftTesting Access control NTFTC ★ It would be nice to have access to internal properties, but you should only test the public interface ★ Implicit constructors for structs are internal ★ However, mocks defined in the same test case can be accessed (internal) ★ If not tested, view controllers may not be public. But it makes things more complicated. More on that later.
  22. 22. #SwiftTesting Create your own templates import XCTest import ___PACKAGENAMEASIDENTIFIER___ class ___FILEBASENAMEASIDENTIFIER___: ___VARIABLE_testSubclass___ { // MARK: - Parameters & Constants // MARK: - Test vatiables. var sut: ___VARIABLE_classUnderTest___! // MARK: - Set up and tear down override func setUp() { super.setUp() createSut() } func createSut() { sut = ___VARIABLE_classUnderTest___() } override func tearDown() { releaseSut() super.tearDown() } func releaseSut() { sut = nil }
  23. 23. No Heart
  24. 24. #SwiftTesting Dependency Injection ★ Code of an object depends on other objects. ★ Those are considered dependencies. ★ Dependencies must be controlled in order to reproduce behavior properly.
  25. 25. #SwiftTesting Dependency Injection ★ Extract and override: move to a method and override in testing class (more fragile) ★ Method injection: change the signature of the method to provide the dependency ★ Property injection: lazy instantiation ★ Constructor injection: not always possible
  26. 26. #SwiftTesting Stubs & Mocks ★ Both are fake objects ★ Stubs provide desired responses to the SUT ★ Mocks also expect certain behaviors
  27. 27. OCMock / OCMockito Not Available!
  28. 28. #SwiftTesting Testing with dependency class ViewController: UIViewController { @IBOutlet weak var messageLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() let userDefaults = NSUserDefaults.standardUserDefaults() let score = userDefaults.integerForKey("PreservedScore") messageLabel.text = String(score) } }
  29. 29. #SwiftTesting func testMessageLabelDisplaysStoredScore() { var labelMock = LabelMock() sut.messageLabel = labelMock sut.userDefaults = UserDefaultsMock() var view = sut.view if let text = sut.messageLabel.text { XCTAssertEqual(text, "1337", "Label must display the preserved score.") } else { XCTFail("Label text must not be nil.") } } class UserDefaultsMock: NSUserDefaults { override func integerForKey(defaultName: String) -> Int { return 1337 } } class LabelMock: UILabel { var presentedText: String? override internal var text: String? { get { return presentedText } set { presentedText = newValue } } } } Dependency injection import UIKit public class ViewController: UIViewController { @IBOutlet public weak var messageLabel: UILabel! lazy public var userDefaults = NSUserDefaults.standardUserDefaults() override public func viewDidLoad() { super.viewDidLoad() let score = userDefaults.integerForKey("Score") messageLabel.text = String(score) } }
  30. 30. Let the Architecture Help You
  31. 31. #SwiftTesting Clean Architecture View (VC) Presenter Wireframe Interactor Repository Persistence WSC
  32. 32. Follow the Clean Brick Road
  33. 33. canonicalexamples.com coupon: APPSTERDAMERS
  34. 34. Thank you!
  35. 35. @jdortiz #SwiftTesting

×