Skip to content

Instantly share code, notes, and snippets.

@mattstevens
Created June 2, 2013 04:36

Revisions

  1. mattstevens created this gist Jun 2, 2013.
    5 changes: 5 additions & 0 deletions GoogleTests.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    #import <SenTestingKit/SenTestingKit.h>

    @interface GoogleTests : SenTestCase

    @end
    111 changes: 111 additions & 0 deletions GoogleTests.mm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,111 @@
    #import "GoogleTests.h"
    #import "SenTestStub.h"

    using testing::TestCase;
    using testing::TestInfo;
    using testing::TestResult;
    using testing::TestPartResult;

    class SenTestPrinter : public testing::EmptyTestEventListener {
    public:
    SenTestPrinter(SenTestSuiteRun *run) :
    enclosingRun(run),
    testSuiteRun(nil),
    testRun(nil) {}

    void OnTestCaseStart(const TestCase& test_case) {
    NSString *name = [NSString stringWithCString:test_case.name() encoding:NSUTF8StringEncoding];
    SenTest *testSuite = [SenTestStub testSuiteStubWithName:name testCaseCount:test_case.test_to_run_count()];
    testSuiteRun = [[SenTestSuiteRun alloc] initWithTest:testSuite];
    [testSuiteRun start];
    }

    void OnTestStart(const TestInfo& test_info) {
    NSString *suite = [[testSuiteRun test] name];
    NSString *name = [NSString stringWithCString:test_info.name() encoding:NSUTF8StringEncoding];
    testRun = [[SenTestCaseRun alloc] initWithTest:[SenTestStub testCaseStubWithName:name suite:suite]];
    [testRun start];
    }

    void OnTestPartResult(const TestPartResult& test_part_result) {
    if (test_part_result.passed())
    return;

    NSString *path = [[NSString stringWithCString:test_part_result.file_name() encoding:NSUTF8StringEncoding] stringByStandardizingPath];
    NSString *description = [NSString stringWithCString:test_part_result.message() encoding:NSUTF8StringEncoding];
    NSException *exception = [NSException failureInFile:path atLine:test_part_result.line_number() withDescription:description];
    [testRun addException:exception];
    }

    void OnTestEnd(const TestInfo& test_info) {
    [testSuiteRun addTestRun:testRun];
    [testRun stop];
    [testRun release];
    testRun = nil;
    }

    void OnTestCaseEnd(const TestCase& test_case) {
    [enclosingRun addTestRun:testSuiteRun];
    [testSuiteRun stop];
    [testSuiteRun release];
    testSuiteRun = nil;
    }

    SenTestSuiteRun *enclosingRun;
    SenTestSuiteRun *testSuiteRun;
    SenTestCaseRun *testRun;
    };

    @implementation GoogleTests

    // OCUnit loads tests by looking for all classes derived from SenTestCase and
    // calling defaultTestSuite on them. Normally this method returns a
    // SenTestSuite containing a SenTestCase for each method of the receiver whose
    // name begins with "test". Instead this class acts as its own test suite.

    + (id)defaultTestSuite {
    return [[[self alloc] init] autorelease];
    }

    - (Class)testRunClass {
    return [SenTestSuiteRun class];
    }

    - (NSString *)name {
    return NSStringFromClass([self class]);
    }

    - (unsigned int)testCaseCount {
    return testing::UnitTest::GetInstance()->test_to_run_count();
    }

    - (void)performTest:(SenTestRun *)testRun {
    NSArray *arguments = [[NSProcessInfo processInfo] arguments];

    int i = 0;
    int argc = [arguments count];
    const char **argv = (const char **)calloc(argc + 1, sizeof(const char *));
    for (NSString *arg in arguments) {
    argv[i++] = [arg UTF8String];
    }

    testing::InitGoogleTest(&argc, (char **)argv);
    testing::TestEventListeners& listeners = testing::UnitTest::GetInstance()->listeners();
    delete listeners.Release(listeners.default_result_printer());
    listeners.Append(new SenTestPrinter((SenTestSuiteRun *)testRun));
    free(argv);

    // Uncomment start/stop to place all external test cases under a suite with
    // the name of this class in test output. By default external test cases
    // appear as peers to other SenTestCases.
    //[testRun start];

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wunused-result"
    RUN_ALL_TESTS();
    #pragma clang diagnostic pop

    //[testRun stop];
    }

    @end
    8 changes: 8 additions & 0 deletions SenTestStub.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    #import <SenTestingKit/SenTestingKit.h>

    @interface SenTestStub : SenTest

    + (instancetype)testCaseStubWithName:(NSString *)name suite:(NSString *)suiteName;
    + (instancetype)testSuiteStubWithName:(NSString *)name testCaseCount:(unsigned int)count;

    @end
    44 changes: 44 additions & 0 deletions SenTestStub.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    #import "SenTestStub.h"

    @implementation SenTestStub {
    NSString *_name;
    unsigned int _count;
    }

    - (id)initWithName:(NSString *)name testCaseCount:(unsigned int)count {
    self = [super init];
    if (self) {
    _name = [name copy];
    _count = count;
    }

    return self;
    }

    - (void)dealloc {
    [_name release];
    [super dealloc];
    }

    + (instancetype)testCaseStubWithName:(NSString *)name suite:(NSString *)suiteName {
    NSString *senTestCompatibleName = [NSString stringWithFormat:@"-[%@ %@]", suiteName, name];
    return [[[self alloc] initWithName:senTestCompatibleName testCaseCount:1] autorelease];
    }

    + (instancetype)testSuiteStubWithName:(NSString *)name testCaseCount:(unsigned int)count {
    return [[[self alloc] initWithName:name testCaseCount:count] autorelease];
    }

    - (NSString *)name {
    return [[_name retain] autorelease];
    }

    - (unsigned int)testCaseCount {
    return _count;
    }

    - (NSString *) description {
    return [self name];
    }

    @end