September 30th, 2013
One of the biggest areas of change in Xcode 5 involves unit testing. This post details those changes.
Xcode 5 adds a test navigator to the available navigators on the left side of the project window. You can see an example of the test navigator in the following screenshot:
The test navigator has one listing for each unit test class in your test target. Click the disclosure triangle next to a test class to see the tests for that class. Selecting a test class opens that class in Xcode’s editor. Selecting a test takes you to the selected test in Xcode’s editor.
The test navigator lets you control what tests are run. Selecting the unit testing target, a test class, or an individual test makes a Play button appear next to the selected item in the project navigator (where the green checkmarks are in the screenshot). Click the Play button to run tests. Clicking the Play button for the unit testing target runs all the tests. Clicking the Play button for a test class runs all the tests for that class. Clicking the Play button for an individual test runs one test. If a test passes, it has a green checkmark next to it. Failing tests have a red X next to them.
Xcode 5 also allows you to run tests from the editor. Look at the following screenshot for the start of a unit test:
Notice the diamond next to line 52 in the screenshot. Click the diamond to run the test. Running unit tests from the editor helps when you have a failing test. Click the diamond to rerun the failing test without having to run the whole test suite.
If you create a new Cocoa or iOS application project in Xcode 5, you will notice there is no checkbox to include a unit testing target. New Cocoa and iOS application projects automatically include a unit testing target.
If you don’t unit test your code, you can delete the unit testing target. Select the project from the project navigator to open the project editor. Select the unit testing target from the target list on the left side of the project editor. Right-click and choose Delete.
Xcode 5 introduces a new unit testing framework for Cocoa and Cocoa Touch applications, XCTest. If you used OCUnit in Xcode 4, you should have little trouble using XCTest because OCUnit and XCTest are very similar. The biggest difference is that XCTest assertions start with XCTAssert instead of STAssert. Another change I noticed is that XCTest has no equivalent to the assertions STAssertTrueNoThrow and STAssertFalseNoThrow. If you haven’t used OCUnit, you can read my Introduction to Unit Testing with OCUnit post to learn more about OCUnit. When reading that post, keep in mind that XCTest test classes do not have a header file.
Xcode 5 supports both XCTest and OCUnit, but XCTest is the future of Objective-C unit testing for Mac OS X and iOS. New projects use XCTest. If you are adding a unit testing target to an existing project, I recommend using XCTest unless you need to run unit tests in Xcode 4.
If you get a linker error when running your tests that looks similar to the following message:
Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_YourClass" ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
Where YourClass is one of the application classes you’re testing, you’ll need to make the application class a member of the unit testing target. Select the .m file from the project navigator. Go to the file inspector. Select the checkbox for the unit testing target in the Target Membership section.
Xcode 5 includes a refactoring tool to convert your OCUnit unit tests to XCTest. Choose Edit > Refactor > Convert to XCTest. The refactoring tool converts your OCUnit test target to XCTest and converts your test classes and tests to XCTest.
I recommend backing up your project before running the refactoring tool. I had a problem with the beta versions of Xcode 5 where the test navigator showed zero tests after running the refactoring tool, and my tests didn’t run. The problem was fixed in the release version, but I still had the problem in one project. My workaround was to perform the following steps:
The assistant editor in Xcode 5 places your tests and the application code being tested side by side. I haven’t been able to verify this feature, but it is mentioned in the What’s New in Xcode document (In Xcode choose Help > What’s New In Xcode) in the Testing section.
Why haven’t I been able to verify this feature? Xcode 5 crashes a lot when I switch to the assistant editor. When Xcode doesn’t crash, selecting a test from the test navigator doesn’t update the assistant editor with the code being tested. Hopefully you’ll have more success with the assistant editor than I have.
Xcode 4 had a Test After Build build setting that ran your unit tests after building your projects. Xcode 5 does not support this build setting. If your project sets Test After Build to YES, you should set it to NO, or you will get errors when running tests or running the XCTest refactoring tool.