Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Cedar and OCUnit

tl;dr Latest version of Cedar can nicely integrate with Xcode just like OCUnit.


When creating new Xcode project you might have noticed that New Project dialog has ‘Include Unit Tests’ checkbox at the bottom. When that option is selected in addition to creating an app target Xcode will also create a separate target that is used for testing your application. This target most likely will be named [app]Tests. Convenient, huh! Since Xcode is such a nice IDE[1] it will also create an example test file that uses Xcode’s built-in unit testing framework — OCUnit (also known as SenTestingKit). If you never heard of it below is a screenshot of how that example OCUnit test file looks.

Because Apple ships OCUnit with Xcode it is tightly integrated into the IDE and that gives it somewhat of an advantage over other testing frameworks. Example of such unfair treatment is relatively nice looking red error markers (shown above) that show up next to failed test cases when application tests are run. If you have ever used Cedar before you would know that when Cedar specs fail we do not get those markers but rather we are presented with boring gray console output (we have dots though!). Unfortunately there is no documented way for custom testing frameworks to mimic OCUnit behavior without building on top of it. But even if do decide to use OCUnit as a base for your custom testing framework you will run into several problems. One of those problems, at least a year ago, was that you could not reliably use debugger with OCUnit tests. That was one of the main reasons why Cedar was not build on top of it. Recently, however, Xcode 4 was released with a lot of enhancements including better support for running OCUnit tests (with or without debugger) or so it seems. Red markers being a driving force, once again it was worth to investigate on how take advantage of OCUnit goodies from Cedar. Latest version of Cedar succeeds at that. What follows are the steps on how to setup Cedar for maximum Xcode integration.

Setup steps

Check ‘Include Unit Tests’ checkbox in New Project dialog. If you want to add application tests to an existing project here is a very nice tutorial:

After Xcode is done creating a new project file go to Build Settings for application tests target (in this case ExampleTests) and find Other Linker Flags settings. Add -ObjC, -all_load, and -lstdc++ to that setting and click Done.

Next step is to add Cedar static library to application tests target.

Now you are ready to create a Cedar spec file. Create a new empty file and end the filename with ‘’. ‘mm’ file extension is needed to be able to use built-in Cedar matcher library. Also since this file should only be run as part of application tests and not the actual application make sure that you only include it in application tests target.

Add a test or two (see above for example) to be able to test that Cedar is working correctly. Example above tries to assert that 2+2 equals 5 and that should hopefully fail. Notice that here I’m using recently added Cedar matchers should syntax. If you do not like that you can always rewrite that expectation as expect(2+2).to(equal(5));

Larger image.
And finally to run specs you just wrote select scheme for your app (in this case Example) from the drop down in the upper left corner and press ‘Cmd+U’. ‘Cmd+U’ in Xcode by default runs tests associated with selected scheme. That should first build your app (because application tests target lists the app as a target dependency), then build application tests target and then run the tests. Since 2+2 does not equal 5 you will see that Xcode will highlight that line in red and show that as an error in the errors panel on the left side. Fixing that expectation should make the test pass.

Running from the command line

If you want to run your application tests from the command line you can use rake ocunit:application to do that. Before doing so make sure you have updated APP_NAME and OCUNIT_APPLICATION_SPECS_TARGET_NAME in the Rakefile. Also you’ll need to use Debug for CONFIGURATION so that your tests are able to include classes from your application. What’s nice about this rake task is that it is ready to be used on your CI machine since it returns exit code 1 when any tests fail and 0 if they all succeed. It also prints in color.

How it actually works

If you are wondering how Cedar pretends to be OCUnit here is a short summary:

  • When Cedar is loaded it overrides runTests class method on SenTestProbe class (related file to look at is CDROTestIPhoneRunner.m)
  • SenTestProbe +runTests gets called by otest — an executable that Xcode uses to run tests after it injected the application tests bundle into TEST_HOST app
  • Since SenTestProbe +runTests was overridden with Cedar’s run method Cedar executes all of its specs following all the usual rules: focused, pended, etc.
  • When specs are running CDROTestReporter (source) gets notified which tests passed, failed, got skipped, etc. and prints out appropriate information which you see in console log
  • CDROTestReporter prints out failed tests in a way that is recognized by Xcode (OCUnit spits out same output for failed examples) e.g.:
Test Case '-[ExampleTests testExample]' started.
/Users/work/workspace/Example/ExampleTests/ExampleTests.m:16: error: -[ExampleTests testExample] : '4' should be equal to '5': 2+2 != 5
Test Case '-[ExampleTests testExample]' failed (0.000 seconds).
  • Xcode notices that pattern in the console output, parses it, gets filename and line number and marks that file location with a red marker to indicate a test failure

Drawbacks/Not implemented features

  • Debugger support is still a bit flaky but this is a problem with Xcode/OCUnit integration
  • I have not tried running it on the device but it should work
  • If you are used to specifying -SenTest option to run specific test case it will be ignored; however, you can use Cedar’s fit, fdescribe, and fcontext to focus on specific tests
  • Some third party OCUnit add-ons might not work (let us know about them)

Useful links

[1] It’s not.

  1. Thank you very much for this update, it’s really nice to be able to just ‘Cmd+U’ these tests.

    I’m experiencing some major inconsistencies, though.

    I’ve added this simple test (2+2 = 5), just like you described it here. Tests fail, as expected.

    First problem: there’s also a classic OCUnit test class (STAssert…) in the same target, and this test isn’t triggered anymore.

    Second problem: when I try to ‘Cmd+U’ again, it says “no issues”. Sometimes I need to clean/test it again, sometimes I need to close/open Xcode, it’s really weird.

    So, first question: Are Cedar tests supposed to run along side with classic OCUnit tests?
    And then: has anyone experienced the same inconstancies for this kind of tests?

  2. It seems to me that I need to create 2 distinct targets in order to run both Cedar tests and classic OCUnit tests. Could you confirm that?

    Is there any plan to make them run together (i.e. with just one ‘Cmd+U’) ?

  3. Dmitriy Kalinin says:

    Are Cedar tests supposed to run along side with classic OCUnit tests?
    – Yes, plain OCUnit tests do not run along with Cedar tests if they are in the same target. It is definitely possible to do that. I have not included that functionality (yet?) since I am still considering drawbacks of such action. In your case it seems like you just want to run two test suites when you press ‘Cmd+U’ and that could be achieved by going to Edit Scheme for your app, then going to Test side tab and adding new test suite. One problem with that though is that it will only show you output of the last test suite you ran.

    Has anyone experienced the same inconstancies for this kind of tests?
    – Which XCode version/compiler/OS are you using? Do similar issues happen when you are running plain OCUnit tests?

  4. Dmitriy Kalinin says:

    @Vincent Tourraine Also, when it claims that there are no issues but you are expecting that there are some, what does it say in the debug console? Does it tell you that some tests failed?

  5. Dmitriy Kalinin says:

    @Vincent Tourraine Looks like the method I suggested (two test suites) is not working correctly so I made appropriate changes to Cedar. Latest Cedar master will now run plain OCUnit tests and Cedar specs that are in the same target.

  6. @Dmitriy Kalinin
    It’s great to have both OCUnit and Cedar tests in the same target, thanks for the update!

    Regarding my inconsistent results, I use the latest version of Xcode (4.2.1), iOS 5 SDK, with OS X Lion. These problems don’t occur with regular OCUnit tests, and the debug console doesn’t mention errors either. This is really confusing, but I’m not sure Cedar is to blame here. I’ll investigate, and come back to you if I get more information.

    Thank you for your time. We’re just starting a pretty big project, and we’d love to use Cedar for our (extensive) tests.

  7. George James says:

    I am using cedar in my ios project and i have a scenario where i am coding like
    [RightNavigationItemView setWithViewController:self title:@”Done” Action:@selector(doneButtonTapped:)];
    RightNavigationItemView is a class where i am customizing the right navigation button using the following code

    + (RightNavigationItemView *)setWithViewController:(UIViewController *)viewController title:(NSString *)title Action:(SEL)selector {
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@”RightNavigationItemView” owner:self options:nil];
    RightNavigationItemView *item = [topLevelObjects objectAtIndex:0];
    [item.rightButton setTitle:title forState:UIControlStateNormal];
    [item.rightButton addTarget:viewController action:selector forControlEvents:UIControlEventTouchUpInside];
    item.rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:item.rightButton];
    viewController.navigationItem.rightBarButtonItem = item.rightBarButton;

    return item;
    now how can i check the rightNavigationButton title?
    please help me out here

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *