Skip to content

Instantly share code, notes, and snippets.

@mattstevens
Created June 2, 2013 04:36
Show Gist options
  • Save mattstevens/5692633 to your computer and use it in GitHub Desktop.
Save mattstevens/5692633 to your computer and use it in GitHub Desktop.
Google Test integration for an Xcode unit test target
#import <SenTestingKit/SenTestingKit.h>
@interface GoogleTests : SenTestCase
@end
#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
#import <SenTestingKit/SenTestingKit.h>
@interface SenTestStub : SenTest
+ (instancetype)testCaseStubWithName:(NSString *)name suite:(NSString *)suiteName;
+ (instancetype)testSuiteStubWithName:(NSString *)name testCaseCount:(unsigned int)count;
@end
#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
@mattstevens
Copy link
Author

I've since turned this into its own repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment