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.

7 Stages of Unit Testing in iOS

521 views

Published on

Introductory talk about Unit Testing for iOS: Motivations and basics.
Some example code included.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

7 Stages of Unit Testing in iOS

  1. 1. 7 Stages of Unit Testing in iOS Jorge D. Ortiz-Fuentes @jdortiz #7SUnitTest
  2. 2. A Canonical Examples production #7SUnitTest
  3. 3. #7SUnitTest Agenda Evangelize about unit tests to seasoned programmers Introduce them to everybody else
  4. 4. 1.
  5. 5. Shock & Disbelief
  6. 6. But my code is always awesome!
  7. 7. #7SUnitTest 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
  8. 8. Test the parts that you aren’t developing now
  9. 9. #7SUnitTest 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 are bugs
  10. 10. 2.
  11. 11. Denial
  12. 12. C’mon, it takes ages to write tests!
  13. 13. Time writing tests < Time debugging
  14. 14. #7SUnitTest Good & Bad News Most already available in Xcode / not doubles Projects are created with • test target • a crappy example ⌘+U is your friend Behaviors provide Pavlov reinforcement XCTest is THE tool for the rest you are on your own
  15. 15. 3.
  16. 16. Anger
  17. 17. How do I write those f***ing tests?
  18. 18. #7SUnitTest Types of Unit Tests Test return value Test state Test behavior
  19. 19. #7SUnitTest The SUT @interface Thermostat : NSObject @property (strong, nonatomic) NSNumber *setpoint; @property (assign, nonatomic) BOOL imperialSystem; - (NSString *) showSetpoint; - (void) increaseSetpoint; - (void) saveSetpoint; @end
  20. 20. #7SUnitTest Return - (NSString *) showSetpoint { return [NSString stringWithFormat:@"%@ %@", self.setpoint, self.imperialSystem?@"F":@"C"]; }
  21. 21. #7SUnitTest Test return - (void) testSetpointIsShownWithTheRightUnits { // Arrange sut.setpoint = @23; sut.imperialSystem = NO; // Act NSString *shownSetpoint = [sut showSetpoint]; // Assert XCTAssertEqualObjects(shownSetpoint, @"23 C"); }
  22. 22. #7SUnitTest State - (void) increaseSetpoint { self.setpoint = @([self.setpoint intValue] + 1); }
  23. 23. #7SUnitTest Test state - (void) testIncreaseSetpointAddsOne { // Arrange sut.setpoint = @23; // Act [sut increaseSetpoint]; // Assert XCTAssertEqualObjects(sut.setpoint, @24); }
  24. 24. #7SUnitTest Behavior @interface Thermostat() @property (strong, nonatomic) NSUserDefaults *userDefaults; @end @implementation Thermostat - (void) saveSetpoint { [self.userDefaults setObject:self.setpoint forKey:@"setpoint"]; } - (NSUserDefaults *) userDefaults { if (_userDefaults == nil) { _userDefaults = [NSUserDefaults standardUserDefaults]; } return _userDefaults; } @end
  25. 25. #7SUnitTest Create a Spy @interface UserDefaultsMock: NSUserDefaults @property (assign, nonatomic) BOOL valueWasSet; @end @implementation UserDefaultsMock - (void)setValue:(id)value forKey:(NSString *)key { self.valueWasSet = YES; } @end
  26. 26. #7SUnitTest Test behavior - (void) testSetpointIsPersisted { // Arrange sut.setpoint = @23; UserDefaultsMock *userDefMock = [UserDefaultsMock new]; [sut setValue:userDefMock forKey:@"userDefaults"]; // Act [sut saveSetpoint]; // Assert XCTAssertTrue(userDefMock.valueWasSet); }
  27. 27. 4.
  28. 28. Bargain
  29. 29. Ok, I’ll write some tests, but make my life simpler
  30. 30. - (void) testSetpointIsPersisted { // Arrange sut.setpoint = @23; id userDefMock = [OCMockObject mockForClass:[NSUserDefaults class]]; OCMExpect([userDefMock setObject:sut.setpoint forKey:@"setpoint"]); [sut setValue:userDefMock forKey:@"userDefaults"]; // Act [sut saveSetpoint]; // Assert XCTAssertNoThrow([userDefMock verify]); } Simulating and Testing Behavior Stubs & Mocks • Both are test doubles • Stubs provide desired responses to the SUT • Spies also expect certain behaviors • Mocks include verification
  31. 31. #7SUnitTest Use a Mocking Framework Install as a pod • OCMock • OCMockito Not for Swift 😱
  32. 32. #7SUnitTest Dependency Injection Control behavior of the dependencies • Constructor • Method overwriting • Property injection:Lazy instantiation Or use a DI framework (uncommon)
  33. 33. #7SUnitTest An Assertion Framework Richer semantics • OCHamcrest • Expecta • Nimble
  34. 34. 5.
  35. 35. Guilt
  36. 36. My tests are never good enough!
  37. 37. #7SUnitTest Follow the rules Test your code only Only a level of abstraction Only public methods Only one assertion per test Tests are independent of sequence or state
  38. 38. 6.
  39. 39. Depression
  40. 40. But my coverage is poor
  41. 41. #7SUnitTest Improve your coverage Measure it Assign priorities Agree upon rules for your team/project
  42. 42. Coverage
  43. 43. Improve
  44. 44. #7SUnitTest And when I have too many tests? Disable test cases Run from command line • xcodebuild • xcpretty
  45. 45. 7.
  46. 46. Acceptance & Hope
  47. 47. No tests, no fun
  48. 48. #7SUnitTest Evolve Clean Architecture TDD Other tests: integration, ui, performance… CI (OSX Server / Jenkins)
  49. 49. Thank you!
  50. 50. @jdortiz #7SUnitTest

×