Unit testing is a standard technique in computer programming whereby we break the software into small, independent pieces of code (a.k.a. the unit), isolate it from the rest of the code and test it. The main goal of unit testing is to try and find as many bugs as possible, as soon as possible. html
Unit testing will be a large part of your work in the Software Development Project (and of your software engineer career!). Neglecting it will nearly always be a huge mistake! ios
We distinguish to kinds of testing : git
In this tutorial, you will learn how to logic test and application test your iOS applications in Xcode using the integrated tools. web
A full tutorial on Unit testing can be found on Apple website : objective-c
Unit Testing in iOS xcode
$(BUILT_PRODUCTS_DIR)/MyLocation.app/MyLocation
$(BUNDLE_LOADER)
#import "MyLocationLogicTests.h" #import "Calculator.h" @implementation MyLocationLogicTests - (void)setUp { [super setUp]; // Set-up code here. } - (void)tearDown { // Tear-down code here. [super tearDown]; } - (void)testAddition { NSString* test = [Calculator computeWithOperand:@"+" number1:@"2" andNumber2:@"3"]; NSString* realResult = [NSString stringWithFormat:@"%lf", 5.0]; STAssertTrue([test isEqualToString:realResult], @""); } - (void)testSubstraction { NSString* test = [Calculator computeWithOperand:@"-" number1:@"2" andNumber2:@"3"]; NSString* realResult = [NSString stringWithFormat:@"%lf", -1.0]; STAssertTrue([test isEqualToString:realResult], test); } - (void)testProduct { NSString* test = [Calculator computeWithOperand:@"*" number1:@"2" andNumber2:@"3"]; NSString* realResult = [NSString stringWithFormat:@"%lf", 6.0]; STAssertTrue([test isEqualToString:realResult], @""); } - (void)testDivision { NSString* test = [Calculator computeWithOperand:@"/" number1:@"6" andNumber2:@"3"]; NSString* realResult = [NSString stringWithFormat:@"%lf", 2.0]; STAssertTrue([test isEqualToString:realResult], @""); STAssertThrows([Calculator computeWithOperand:@"/" number1:@"6" andNumber2:@"0"], @""); } - (void)testBadInputs { // must throw an exception to pass the test STAssertThrows([Calculator computeWithOperand:@"/+" number1:@"6" andNumber2:@"0"], @""); STAssertThrows([Calculator computeWithOperand:@"" number1:@"6" andNumber2:@"0"], @""); STAssertThrows([Calculator computeWithOperand:@"a" number1:@"6" andNumber2:@"0"], @""); STAssertThrows([Calculator computeWithOperand:@"ab" number1:@"6" andNumber2:@"0"], @""); STAssertThrows([Calculator computeWithOperand:@"+" number1:@"a" andNumber2:@"0"], @""); STAssertThrows([Calculator computeWithOperand:@"+" number1:@"5" andNumber2:@"a"], @""); } @end
Test Suite '/Users/<gaspar>/Library/Developer/Xcode/DerivedData/MyLocation-aigvggguqsokvbbpxwtxqdyqmhzp/Build/Products/Debug-iphonesimulator/MyLocationLogicTests.octest(Tests)' started at 2011-10-30 19:42:28 +0000 Test Suite 'MyLocationLogicTests' started at 2011-10-30 19:42:28 +0000 Test Case '-[MyLocationLogicTests testAddition]' started. Test Case '-[MyLocationLogicTests testAddition]' passed (0.000 seconds). Test Case '-[MyLocationLogicTests testBadInputs]' started. Test Case '-[MyLocationLogicTests testBadInputs]' passed (0.000 seconds). Test Case '-[MyLocationLogicTests testDivision]' started. Test Case '-[MyLocationLogicTests testDivision]' passed (0.000 seconds). Test Case '-[MyLocationLogicTests testProduct]' started. Test Case '-[MyLocationLogicTests testProduct]' passed (0.000 seconds). Test Case '-[MyLocationLogicTests testSubstraction]' started. Test Case '-[MyLocationLogicTests testSubstraction]' passed (0.000 seconds). Test Suite 'MyLocationLogicTests' finished at 2011-10-30 19:42:28 +0000. Executed 5 tests, with 0 failures (0 unexpected) in 0.001 (0.001) seconds Test Suite '/Users/<gaspar>/Library/Developer/Xcode/DerivedData/MyLocation-aigvggguqsokvbbpxwtxqdyqmhzp/Build/Products/Debug-iphonesimulator/MyLocationLogicTests.octest(Tests)' finished at 2011-10-30 19:42:28 +0000. Executed 5 tests, with 0 failures (0 unexpected) in 0.001 (0.002) seconds
#import <SenTestingKit/SenTestingKit.h> #import "MyLocationAppDelegate.h" #import "NameViewController.h" #import "MapViewController.h" @interface MyLocationApplicationTests : SenTestCase { MyLocationAppDelegate* appDelegate; UINavigationController* mainNavigationController; NameViewController* nameViewController; MapViewController* mapViewController; } @end
You can see we need a pointer to the application delegate class itself. We will indeed check that the application starts correctly. app
Now, implement MyLocationApplicationTests.m with the following : less
#import "MyLocationApplicationTests.h" @implementation MyLocationApplicationTests - (void)setUp { [super setUp]; // Set-up code here. appDelegate = [[[UIApplication sharedApplication] delegate] retain]; mainNavigationController = (UINavigationController*)appDelegate.window.rootViewController; nameViewController = (NameViewController*)mainNavigationController.visibleViewController; } - (void)tearDown { // Tear-down code here. [appDelegate release]; [super tearDown]; } - (void)testApplicationDelegate { STAssertTrue([appDelegate isMemberOfClass:[MyLocationAppDelegate class]], @"bad UIApplication delegate"); STAssertTrue([mainNavigationController isMemberOfClass:[UINavigationController class]], @"bad mainViewController"); } - (void)testNameViewController { STAssertTrue([nameViewController isMemberOfClass:[NameViewController class]], @""); UIButton* nextButton = (UIButton*)[nameViewController.view viewWithTag:1]; [nextButton sendActionsForControlEvents:(UIControlEventTouchUpInside)]; STAssertTrue(mainNavigationController.visibleViewController == nameViewController, @"empty name check did not work"); //should not go to next view as username textfield is empty UITextField* nameTextField = (UITextField*)[nameViewController.view viewWithTag:2]; nameTextField.text = @"Toto"; [nextButton sendActionsForControlEvents:(UIControlEventTouchUpInside)]; STAssertTrue([mainNavigationController.visibleViewController isMemberOfClass:[MapViewController class]], @"mapViewController not coming when touching next button"); } @end
Test Suite 'All tests' started at 2011-11-13 21:32:12 +0000 Test Suite '/Users/<gaspar>/Library/Developer/Xcode/DerivedData/MyLocation-glwkfxnrtujdosesedhjfujyjnxy/Build/Products/Debug-iphonesimulator/MyLocationApplicationTests.octest(Tests)' started at 2011-11-13 21:32:12 +0000 Test Suite 'MyLocationApplicationTests' started at 2011-11-13 21:32:12 +0000 Test Case '-[MyLocationApplicationTests testApplicationDelegate]' started. Test Case '-[MyLocationApplicationTests testApplicationDelegate]' passed (0.000 seconds). Test Case '-[MyLocationApplicationTests testNameViewController]' started. Test Case '-[MyLocationApplicationTests testNameViewController]' passed (0.150 seconds). Test Suite 'MyLocationApplicationTests' finished at 2011-11-13 21:32:13 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.150 (0.150) seconds Test Suite '/Users/<gaspar>/Library/Developer/Xcode/DerivedData/MyLocation-glwkfxnrtujdosesedhjfujyjnxy/Build/Products/Debug-iphonesimulator/MyLocationApplicationTests.octest(Tests)' finished at 2011-11-13 21:32:13 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.150 (0.150) seconds Test Suite 'All tests' finished at 2011-11-13 21:32:13 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.150 (0.151) seconds