Unit Testing in iOSfeaturing OCUnit, GHUnit & OCMock            works for OS X too!               @hpique
The sad fate of developers who don’t write unit tests
Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
unit test             =code that tests a single unit          of code
Hey look! A unit test!- (void) testColorFromPointAndSize_SizeZero{    // Prepare input    CGSize size = CGSizeZero;    CGP...
Reasons not to unit      test
...
ReasonsExcuses not    to unit test
Excuses• “I don’t need it”• “Deadline is too tight”• “It’s not applicable for this [project|  class|method]”• “Unit testin...
Reasons to unit test• Fix bugs early• Refine design• Easier to make changes• Instant gratification :)• Useful documentation•...
quality code and testable  code are best buds
When?• After writing code• Before writing code (TDD)• After fixing a bug
Definitions          Test Suite           SetUpTest Case Test Case Test Case          TearDown
Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
OCUnit• De-facto unit testing framework for  Obj-C• Xcode provides native support
+N
#import <SenTestingKit/SenTestingKit.h>@interface HelloWorldTests : SenTestCase@end@implementation HelloWorldTests- (void)...
Writing tests with        OCUnit• Each Test Suite is a class that inherits  from SenTestCase• Each Test Case is a method w...
+U
Console output2011-12-09 12:43:01.394 HelloWorld[2858:fb03] Applications are expected to have aroot view controller at the...
OCUnit MacrosSTAssertEqualObjects(a1, a2, description, ...)STAssertEquals(a1, a2, description, ...)STAssertEqualsWithAccur...
Most used macrosSTAssertTrue(expr, description, ...)STAssertFalse(expr, description, ...)STAssertNil(a1, description, ...)...
Let’s see some code!github.com/hpique/Unit-Testing-in-iOS-Sample-Code
Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
GHUnit• The other Unit Testing framework for  Obj-C• Open-source: github.com/gabriel/gh-  unit• GUI!• No Xcode native supp...
#import <GHUnitIOS/GHUnit.h>@interface ExampleTest : GHTestCase@end@implementation ExampleTest- (BOOL)shouldRunOnMainThrea...
If you’re into macros...GHAssertNoErr(a1, description, ...)           GHAssertEquals(a1, a2, description, ...)GHAssertErr(...
GHUnitAsyncTestCase#import <GHUnitIOS/GHUnit.h>@interface AsyncTest : GHAsyncTestCase { }@end@implementation AsyncTest- (v...
Configure GHUnit1. Create target2. Add GHUnitiOS.framework 2.1.and QuartzCore.framework!3. Modify Other Linker Flags4. Chan...
1. Create target
1. Create target
2. AddGHUnitiOS.framework1. Download from github & unzip2. > cd gh-unit/Project-iOS3. > make                    orDownload...
3. Modify Other Link        Flags• Add -all_load• Add -ObjC
4. Change AppDelegate   1. Remove default AppDelegate   2. Modify main.m:int main(int argc, char *argv[]){    @autorelease...
+B
Let’s see some code!github.com/hpique/Unit-Testing-in-iOS-Sample-Code
OCUnit vs GHUnit                     OCUnit           GHUnitXcode integration    Built-in         Manual                  ...
Using OCUnit tests in     GHUnit target  1. Add OCUnit tests to target  2. Add tested files to target  3. Add SenTestKit.fr...
Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
mock object           =simulated object thatmimics the behavior  of a real object in   controlled ways
When to mock an        object?• supplies non-deterministic results (ie:  sensors)• has states that are difficult to create o...
OCMock• De-facto mocking framework for Obj-C• Open-source: github.com/erikdoe/  ocmock• mock objects on the fly via the  tr...
Hey look! Mock objects!- (void) testHandleGesture{    // Prepare input and state    id viewMock = [OCMockObject partialMoc...
Let’s see some code!github.com/hpique/Unit-Testing-in-iOS-Sample-Code
Thanks! @hpique
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Upcoming SlideShare
Loading in …5
×

Unit testing in iOS featuring OCUnit, GHUnit & OCMock

5,628 views

Published on

Published in: Technology
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,628
On SlideShare
0
From Embeds
0
Number of Embeds
94
Actions
Shares
0
Downloads
117
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide

Unit testing in iOS featuring OCUnit, GHUnit & OCMock

  1. 1. Unit Testing in iOSfeaturing OCUnit, GHUnit & OCMock works for OS X too! @hpique
  2. 2. The sad fate of developers who don’t write unit tests
  3. 3. Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
  4. 4. unit test =code that tests a single unit of code
  5. 5. Hey look! A unit test!- (void) testColorFromPointAndSize_SizeZero{ // Prepare input CGSize size = CGSizeZero; CGPoint point = CGPointZero; // Do something UIColor *color = [_viewController colorFromPoint:point andSize:size]; // Validate output STAssertNil(color, @"Color must be nil when size is zero");}
  6. 6. Reasons not to unit test
  7. 7. ...
  8. 8. ReasonsExcuses not to unit test
  9. 9. Excuses• “I don’t need it”• “Deadline is too tight”• “It’s not applicable for this [project| class|method]”• “Unit testing in Xcode sucks”
  10. 10. Reasons to unit test• Fix bugs early• Refine design• Easier to make changes• Instant gratification :)• Useful documentation• Reduce testing time
  11. 11. quality code and testable code are best buds
  12. 12. When?• After writing code• Before writing code (TDD)• After fixing a bug
  13. 13. Definitions Test Suite SetUpTest Case Test Case Test Case TearDown
  14. 14. Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
  15. 15. OCUnit• De-facto unit testing framework for Obj-C• Xcode provides native support
  16. 16. +N
  17. 17. #import <SenTestingKit/SenTestingKit.h>@interface HelloWorldTests : SenTestCase@end@implementation HelloWorldTests- (void)setUp{ [super setUp]; // Set-up code here.}- (void)tearDown{ // Tear-down code here. [super tearDown];}- (void)testExample{ STFail(@"Unit tests are not implemented yet in HelloWorldTests");}@end
  18. 18. Writing tests with OCUnit• Each Test Suite is a class that inherits from SenTestCase• Each Test Case is a method with prefix test• setUp & tearDown are optional
  19. 19. +U
  20. 20. Console output2011-12-09 12:43:01.394 HelloWorld[2858:fb03] Applications are expected to have aroot view controller at the end of application launchTest Suite All tests started at 2011-12-09 11:43:01 +0000Test Suite /Users/hermespique/Library/Developer/Xcode/DerivedData/HelloWorld-ezilismrgmrzecbbsndapbyeczre/Build/Products/Debug-iphonesimulator/HelloWorldTests.octest(Tests) started at 2011-12-09 11:43:01 +0000Test Suite HelloWorldTests started at 2011-12-09 11:43:01 +0000Test Case -[HelloWorldTests testExample] started./Users/hermespique/Documents/workspace/HelloWorld/HelloWorldTests/HelloWorldTests.m:33: error: -[HelloWorldTests testExample] : Unit tests are notimplemented yet in HelloWorldTestsTest Case -[HelloWorldTests testExample] failed (0.000 seconds).Test Suite HelloWorldTests finished at 2011-12-09 11:43:01 +0000.Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) secondsTest Suite /Users/hermespique/Library/Developer/Xcode/DerivedData/HelloWorld-ezilismrgmrzecbbsndapbyeczre/Build/Products/Debug-iphonesimulator/HelloWorldTests.octest(Tests) finished at 2011-12-09 11:43:01 +0000.Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) secondsTest Suite All tests finished at 2011-12-09 11:43:01 +0000.Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.001) seconds
  21. 21. OCUnit MacrosSTAssertEqualObjects(a1, a2, description, ...)STAssertEquals(a1, a2, description, ...)STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...)STFail(description, ...)STAssertNil(a1, description, ...)STAssertNotNil(a1, description, ...)STAssertTrue(expr, description, ...)STAssertTrueNoThrow(expr, description, ...)STAssertFalse(expr, description, ...)STAssertFalseNoThrow(expr, description, ...)STAssertThrows(expr, description, ...)STAssertThrowsSpecific(expr, specificException, description, ...)STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...)STAssertNoThrow(expr, description, ...)STAssertNoThrowSpecific(expr, specificException, description, ...)STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...)
  22. 22. Most used macrosSTAssertTrue(expr, description, ...)STAssertFalse(expr, description, ...)STAssertNil(a1, description, ...)STAssertNotNil(a1, description, ...)STAssertEqualObjects(a1, a2, description, ...)STAssertEquals(a1, a2, description, ...)STFail(description, ...)STAssertThrows(expr, description, ...)
  23. 23. Let’s see some code!github.com/hpique/Unit-Testing-in-iOS-Sample-Code
  24. 24. Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
  25. 25. GHUnit• The other Unit Testing framework for Obj-C• Open-source: github.com/gabriel/gh- unit• GUI!• No Xcode native support• Compatible with OCUnit
  26. 26. #import <GHUnitIOS/GHUnit.h>@interface ExampleTest : GHTestCase@end@implementation ExampleTest- (BOOL)shouldRunOnMainThread { return NO;}- (void)setUpClass { // Run at start of all tests in the class}- (void)setUp { // Run before each test method}- (void)tearDown { // Run after each test method}- (void)tearDownClass { // Run at end of all tests in the class}- (void)testFoo { NSString *a = @"foo"; GHAssertNotNil(a, nil);}@end
  27. 27. If you’re into macros...GHAssertNoErr(a1, description, ...) GHAssertEquals(a1, a2, description, ...)GHAssertErr(a1, a2, description, ...) GHAbsoluteDifference(left,right)GHAssertNotNULL(a1, description, ...) (MAX(left,right)-MIN(left,right))GHAssertNULL(a1, description, ...) GHAssertEqualsWithAccuracy(a1, a2,GHAssertNotEquals(a1, a2, description, ...) accuracy, description, ...)GHAssertNotEqualObjects(a1, a2, desc, ...) GHFail(description, ...)GHAssertOperation(a1, a2, op, GHAssertNil(a1, description, ...)description, ...) GHAssertNotNil(a1, description, ...)GHAssertGreaterThan(a1, a2, GHAssertTrue(expr, description, ...)description, ...) GHAssertTrueNoThrow(expr,GHAssertGreaterThanOrEqual(a1, a2, description, ...)description, ...) GHAssertFalse(expr, description, ...)GHAssertLessThan(a1, a2, description, ...) GHAssertFalseNoThrow(expr,GHAssertLessThanOrEqual(a1, a2, description, ...)description, ...) GHAssertThrows(expr, description, ...)GHAssertEqualStrings(a1, a2, GHAssertThrowsSpecific(expr,description, ...) specificException, description, ...)GHAssertNotEqualStrings(a1, a2, GHAssertThrowsSpecificNamed(expr,description, ...) specificException, aName,GHAssertEqualCStrings(a1, a2, description, ...)description, ...) GHAssertNoThrow(expr, description, ...)GHAssertNotEqualCStrings(a1, a2, GHAssertNoThrowSpecific(expr,description, ...) specificException, description, ...)GHAssertEqualObjects(a1, a2, GHAssertNoThrowSpecificNamed(expr,description, ...) specificException, aName, description, ...)
  28. 28. GHUnitAsyncTestCase#import <GHUnitIOS/GHUnit.h>@interface AsyncTest : GHAsyncTestCase { }@end@implementation AsyncTest- (void)testURLConnection { [self prepare]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:requestdelegate:self startImmediately:YES]; [self waitForStatus:kGHUnitWaitStatusSuccess timeout:10.0];}- (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self notify:kGHUnitWaitStatusSuccess forSelector:@selector(testURLConnection)];}@end
  29. 29. Configure GHUnit1. Create target2. Add GHUnitiOS.framework 2.1.and QuartzCore.framework!3. Modify Other Linker Flags4. Change AppDelegate
  30. 30. 1. Create target
  31. 31. 1. Create target
  32. 32. 2. AddGHUnitiOS.framework1. Download from github & unzip2. > cd gh-unit/Project-iOS3. > make orDownload the latest stable framework fromgithub downloads
  33. 33. 3. Modify Other Link Flags• Add -all_load• Add -ObjC
  34. 34. 4. Change AppDelegate 1. Remove default AppDelegate 2. Modify main.m:int main(int argc, char *argv[]){ @autoreleasepool { return UIApplicationMain(argc, argv, nil,@"GHUnitIOSAppDelegate"); }}
  35. 35. +B
  36. 36. Let’s see some code!github.com/hpique/Unit-Testing-in-iOS-Sample-Code
  37. 37. OCUnit vs GHUnit OCUnit GHUnitXcode integration Built-in Manual Console Console Results Contextual GUI More macros Development GHAsyncTestCase Everything, Execution Everything selection or failed
  38. 38. Using OCUnit tests in GHUnit target 1. Add OCUnit tests to target 2. Add tested files to target 3. Add SenTestKit.framework 4. Add this to Framework Search Paths (order matters):$(SDKROOT)/Developer/Library/Frameworks$(DEVELOPER_LIBRARY_DIR)/Frameworks
  39. 39. Agenda• Unit testing• OCUnit• GHUnit• OCMock• Profit!
  40. 40. mock object =simulated object thatmimics the behavior of a real object in controlled ways
  41. 41. When to mock an object?• supplies non-deterministic results (ie: sensors)• has states that are difficult to create or reproduce (ie: a network error)• is slow (ie: database)• does not yet exist or may change behavior• to avoid writing “test code”
  42. 42. OCMock• De-facto mocking framework for Obj-C• Open-source: github.com/erikdoe/ ocmock• mock objects on the fly via the trampoline pattern• Complementary with OCUnit & GHUnit
  43. 43. Hey look! Mock objects!- (void) testHandleGesture{ // Prepare input and state id viewMock = [OCMockObject partialMockForObject:_viewController.view]; CGRect viewFrame = CGRectMake(0, 0, 320, 480); [[[viewMock stub] andReturnValue:OCMOCK_VALUE(viewFrame)] frame]; _viewController.view = viewMock; UIGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] init]; id gestureMock = [OCMockObject partialMockForObject:gesture]; CGPoint gesturePoint = CGPointMake(viewFrame.size.width / 2, viewFrame.size.height / 2); [[[gestureMock stub] andReturnValue:OCMOCK_VALUE(gesturePoint)] locationInView:[OCMArg any]]; // Do something that changes state [_viewController handleGesture:gestureMock]; // Validate state UIColor *expectedColor = [UIColor colorWithRed:0.5 green:0.5 blue:0 alpha:1]; UIColor *color = _viewController.view.backgroundColor; [self assertEqualsColor:expectedColor toColor:color];}
  44. 44. Let’s see some code!github.com/hpique/Unit-Testing-in-iOS-Sample-Code
  45. 45. Thanks! @hpique

×