Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I trap OCUnit test pass/failure messages/events

I'm trying to use xcodebuild and OCUnit with my Continuous Integration server (TeamCity).

JetBrains offers test observer implementations for boost::test and CppUnit that format test output in a way that TeamCity can interpret. I need to do something similar for OCUnit if I want to use it.

There appears to be a SenTestObserver class in OCUnit but I'm ignorant of how exactly it should be used, and the OCUnit homepage doesn't seem to provide any documentation on the matter.

like image 655
orj Avatar asked Oct 29 '08 17:10

orj


2 Answers

You can write your own observer by extending the SenTestObserver class and implementing the notification listeners

  • (void) testSuiteDidStart:(NSNotification *) aNotification
  • (void) testSuiteDidStop:(NSNotification *) aNotification
  • (void) testCaseDidStart:(NSNotification *) aNotification
  • (void) testCaseDidStop:(NSNotification *) aNotification
  • (void) testCaseDidFail:(NSNotification *) aNotification

then add an entry to the info.plist SenTestObserverClass with the name of your class.

At least in the version of OCUnit i'm familiar with SenTestObserver is equal parts useful/equal parts broken. I just skip it altogether and register for the notifications myself in my own class. (see SenTestSuiteRun.h and SenTestCaseRun.h for the defines of the notification names).

You can use the test and run properties of the notification to access the SenTestSuite and SenTestSuiteRun instances, and the run instance contains the info needed on the actual results.

like image 173
superfell Avatar answered Nov 20 '22 04:11

superfell


I have implemented a simple Teamcity Adapter, you can view the gist here. SenTestObserver isn't exactly broken, it simply doesn't adhere to the best practices:

This is what you need to call in your Observer subclass to have it properly registered:

+(void)initialize
{
    [[NSUserDefaults standardUserDefaults] setValue:@"TeamCityAdapter" forKey:@"SenTestObserverClass"];
    // we need to force SenTestObserver to register us as a handler
    // SenTestObserver is properly guarding against this invocation so nothing bad will hapen
    // but this is required (bad design on SenTestObserver's side)...
    [super initialize];
}

because SenTestObserver's initialize looks like this:

+ (void) initialize
{
    if ([self class] == [SenTestObserver class]) {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSDictionary *registeredDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
            @"SenTestLog" , @"SenTestObserverClass",
            nil];
        [defaults registerDefaults:registeredDefaults];
        [NSClassFromString ([defaults objectForKey:@"SenTestObserverClass"]) class]; // make sure default observer is loaded
    }

    if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"SenTestObserverClass"] isEqualToString:NSStringFromClass(self)]) {
        [self setCurrentObserver:self];
    }
}

I hope this will help others out there looking for a teamcity adapter for OCUnit / SenTestingKit.

like image 41
Johannes Rudolph Avatar answered Nov 20 '22 03:11

Johannes Rudolph