Quick Start

The intent of this quick start is to show that you can make testing an integral part of your software development, and that testing is convenient and easy to work with.

Introducing the Test Navigator

You’ll use the Xcode test navigator often when you are working with tests.

The test navigator is the part of the workspace designed to ease your ability to create, manage, run, and review tests. You access it by clicking its icon in the navigator selector bar, located between the issue navigator and the debug navigator. When you have a project with a suite of tests defined, you see a navigator view similar to the one shown here.

../Art/twx-qs-1.shot/Resources/shot_2x.png

The test navigator shown above displays a hierarchical list of the test bundles, classes, and methods included in a sample project. This particular project is a sample calculator app. The calculator engine is implemented as a framework. You can see at the top level of the hierarchy the SampleCalcTests test bundle, for testing the code in the application.

The active test bundle in this view is SampleCalcTests. SampleCalcTests includes one test class, which in turn contains nine test methods. The Run button (../Art/twx-test_navigator_run_button_2x.png) appears to the right of the item name when you hold the pointer over any item in the list. This is a quick way to run all the tests in a bundle, all the tests in the class, or any individual test. Tests return pass or fail results to Xcode. As tests are being executed, these indicators update to show you the results, a green checkmark for pass or a red x for fail. In the test navigator shown here, two of the tests have asserted a failure.

../Art/twx-qs-2.shot/Resources/shot_2x.png

Clicking any test class or test method in the list opens the test class in the source editor. Test classes and test methods are marked in the source editor gutter with indicators as well, which work in the same way that they do in the test navigator. Test failures display the result string at the associated assertions in the source editor.

At the bottom of the test navigator is the Add button (+) as well as filtering controls. You can narrow the view to just tests in the active scheme or just failed tests, and you can also filter by name.

Add Testing to Your App

New app, framework, and library projects created in Xcode 5 or later are preconfigured with a test target. When you start with a new project and open the test navigator, you see a test bundle, a test class, and a template test method. But you might be opening a preexisting project from an earlier version of Xcode that has no test targets defined yet. The workflow presented here assumes a preexisting project with no tests incorporated.

Create a Test Target

With the test navigator open, click the Add button (+) in the bottom-left corner and choose New Unit Test Target from the menu.

../Art/twx-qs-3.shot/Resources/shot_2x.png

Pick the macOS or iOS Unit Testing Bundle from the next dialog and click Next. In the new target setup assistant that appears, edit the Product Name and other parameters to your preferences and needs.

../Art/twx-qs-4.shot/Resources/shot_2x.png../Art/twx-qs-4.shot/Resources/shot_2x.png

Click Finish to add your target, which contains a template test class and two test method templates, to the test navigator view.

../Art/twx-qs-5.shot/Resources/shot_2x.png

Run the Test and See the Results

Now that you’ve added testing to your project, you want to develop the tests to do something useful. But first, hold the pointer over the SampleCalcTests test class in the test navigator and click the Run button to run all the test methods in the class. The results are indicated by the green checkmarks next to the function names and in the source editor gutter.

../Art/twx-qs-6.shot/Resources/shot_2x.png../Art/twx-qs-6.shot/Resources/shot_2x.png

The template unit and performance tests are both empty, which is why they post success indications; no failure was asserted. Notice the gray diamond on line 34 in the figure at the measureBlock: method. Clicking this diamond displays the Performance Result panel.

../Art/twx-qs-7.shot/Resources/shot_2x.png

This panel allows you to set a performance baseline as well as edit the baseline and Max STDDEV parameters. These features will be discussed later.

Edit the Tests and Run Again

Because this sample project is a calculator app, you want to check whether it performs the operations of addition, subtraction, multiplication, and division correctly, as well as test other calculator functions. Because tests are built in the app project, you can add all the context and other information needed to perform tests at whatever level of complexity makes sense for your needs. Creating tests is a matter of adding methods to the unit tests implementation file.

For example, you insert the following #import and instance variable declarations into the SampleCalcTests.m file.

#import <XCTest/XCTest.h>
//
// Import the application specific header files
#import "CalcViewController.h"
#import "CalcAppDelegate.h"
 
@interface CalcTests : XCTestCase {
// add instance variables to the CalcTests class
@private
    NSApplication       *app;
    CalcAppDelegate     *appDelegate;
    CalcViewController  *calcViewController;
    NSView              *calcView;
}
@end

Then give the test method a descriptive name, such as testAddition, and add the implementation source for the method.

- (void) testAddition
{
   // obtain the app variables for test access
   app                  = [NSApplication sharedApplication];
   calcViewController   = (CalcViewController*)[[NSApplication sharedApplication] delegate];
   calcView             = calcViewController.view;
 
   // perform two addition tests
   [calcViewController press:[calcView viewWithTag: 6]];  // 6
   [calcViewController press:[calcView viewWithTag:13]];  // +
   [calcViewController press:[calcView viewWithTag: 2]];  // 2
   [calcViewController press:[calcView viewWithTag:12]];  // =
    XCTAssertEqualObjects([calcViewController.displayField stringValue], @"8", @"Part 1 failed.");
 
   [calcViewController press:[calcView viewWithTag:13]];  // +
   [calcViewController press:[calcView viewWithTag: 2]];  // 2
   [calcViewController press:[calcView viewWithTag:12]];  // =
    XCTAssertEqualObjects([calcViewController.displayField stringValue], @"10", @"Part 2 failed.");
}

Notice that the list in the test navigator changed to reflect that the sample test method, testExample, has been replaced by testAddition.

../Art/twx-qs-8.shot/Resources/shot_2x.png../Art/twx-qs-8.shot/Resources/shot_2x.png

Now use the Run button in the test navigator (or the indicator in the source editor) to run the testAddition method.

../Art/twx-qs-9.shot/Resources/shot_2x.png../Art/twx-qs-9.shot/Resources/shot_2x.png

As you can see, an assertion failed and is highlighted in the test navigator and the source editor. Looking at the source, Part 1 succeeded—it is Part 2 that has a problem. On closer examination, the error is obvious: In line 76, [calcView viewWithTag:11] is off by one, it should be [calcView viewWithTag:12]. Correcting this error fixes the problem and the test succeeds.

../Art/twx-qs-8a.shot/Resources/shot_2x.png../Art/twx-qs-8a.shot/Resources/shot_2x.png

Use the setUp() and tearDown() Methods for Common Code

Xcode runs test methods one at a time for all the test classes in the active test bundle. In this small example only the one test method was implemented in the test class, and it needed access to three of the calculator app variable objects to function. If you wrote four or five test methods in this same class, you might find yourself repeating the same code in every test method to obtain access to the app object state. The XCTest framework provides you with instance methods for test classes, setUp and tearDown, which you can use to put such common code called before and after runs each test method runs.

Using setUp and tearDown is simple. From the testAddition source in Mac_Calc_Tests.m, cut the four lines starting with // obtain the app variable for test access and paste them into the default setUp instance method provided by the template.

- (void)setUp
{
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
 
   // obtain the app variables for test access
   app                  = [NSApplication sharedApplication];
   calcViewController   = (CalcViewController*)[[NSApplication sharedApplication] delegate];
   calcView             = calcViewController.view;
}

Now add more test methods—testSubtraction and others—with minimal duplicated code.

../Art/twx-qs-10.shot/Resources/shot_2x.png../Art/twx-qs-10.shot/Resources/shot_2x.png

Summary

As you can see from this short Quick Start, it is simple to add testing to a project. Here are some things to notice: