是否可以在没有 Xcode 的情况下使用 XCTest 单元测试?

Nor*_*ray 5 xcode xctest

我想实现 XCTest 单元测试,但实际上并不想使用 XCode 来实现。目前尚不清楚如何做到这一点,我想知道这是否可能?

\n\n

从我到目前为止所发现的情况来看,人们可能会觉得 XCTest 完全依赖于 XCode。我已经找到了xcodebuild test命令行支持,但这取决于是否找到 XCode 项目或工作区。

\n\n

我在这里有什么选择,或者我只是撕掉现有的SenTestingKit代码并恢复为一些自制的单元测试代码?我手头有一些这样的代码,但这不是正确的做法。

\n\n
\n\n

理由/历史:

\n\n

这不仅仅是我老了。我有一个 Objective-C 程序,我上次接触它是在两年前,我为它开发了一套基于SenTestingKit. 现在我回到这段代码 \xe2\x80\x93 我可能至少必须重建这个东西,因为干预库更改 \xe2\x80\x93 我发现SenTestingKit已经消失了,被 XCTest 取代。那好吧....

\n\n

该代码不是使用 XCode 开发的,因此没有与之.project关联的文件,并且到目前为止,测试已使用 SenTestingKit\ 的主程序和 Makefile 顺利管理check目标(部分是 old-skool再说一次,部分原因是对 IDE 缺乏兴趣,部分原因是这是对 Objective-C 的实验,所以最初坚持我所知道的)。

\n

Sta*_*ich 2

如果您正在寻找基于 Xcode 的解决方案,请参阅示例及其链接的解决方案。

如需完整的非基于 Xcode 的解决方案,请继续阅读。

几年前我曾经问过类似的答案:Is there any non-Xcode-based command line unit testing tool for Objective-C? 但从那以后情况发生了变化。

随着时间的推移,XCTest 中出现的一项有趣的功能是能够运行自定义测试套件。我曾经为了我的研究需求成功地实现了它们,下面是一个示例代码,它是一个命令行 Mac OS 应用程序:

@interface FooTest : XCTestCase
@end

@implementation FooTest
- (void)testFoo {
  XCTAssert(YES);
}
- (void)testFoo2 {
  XCTAssert(NO);
}

@end

@interface TestObserver : NSObject <XCTestObservation>
@property (assign, nonatomic) NSUInteger testsFailed;
@end

@implementation TestObserver

- (instancetype)init {
  self = [super init];

  self.testsFailed = 0;

  return self;
}

- (void)testBundleWillStart:(NSBundle *)testBundle {
  NSLog(@"testBundleWillStart: %@", testBundle);
}

- (void)testBundleDidFinish:(NSBundle *)testBundle {
  NSLog(@"testBundleDidFinish: %@", testBundle);
}

- (void)testSuiteWillStart:(XCTestSuite *)testSuite {
  NSLog(@"testSuiteWillStart: %@", testSuite);
}

- (void)testCaseWillStart:(XCTestCase *)testCase {
  NSLog(@"testCaseWillStart: %@", testCase);
}

- (void)testSuiteDidFinish:(XCTestSuite *)testSuite {
  NSLog(@"testSuiteDidFinish: %@", testSuite);
}

- (void)testSuite:(XCTestSuite *)testSuite didFailWithDescription:(NSString *)description inFile:(NSString *)filePath atLine:(NSUInteger)lineNumber {
  NSLog(@"testSuite:didFailWithDescription:inFile:atLine: %@ %@ %@ %tu",
        testSuite, description, filePath, lineNumber);
}

- (void)testCase:(XCTestCase *)testCase didFailWithDescription:(NSString *)description inFile:(NSString *)filePath atLine:(NSUInteger)lineNumber {
  NSLog(@"testCase:didFailWithDescription:inFile:atLine: %@ %@ %@ %tu",
        testCase, description, filePath, lineNumber);
  self.testsFailed++;
}

- (void)testCaseDidFinish:(XCTestCase *)testCase {
  NSLog(@"testCaseWillFinish: %@", testCase);
}

@end

int RunXCTests() {
  XCTestObserver *testObserver = [XCTestObserver new];

  XCTestObservationCenter *center = [XCTestObservationCenter sharedTestObservationCenter];
  [center addTestObserver:testObserver];

  XCTestSuite *suite = [XCTestSuite defaultTestSuite];

  [suite runTest];

  NSLog(@"RunXCTests: tests failed: %tu", testObserver.testsFailed);

  if (testObserver.testsFailed > 0) {
    return 1;
  }

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

要编译此类代码,您需要显示 XCTest 所在文件夹的路径,如下所示:

# in your Makefile
clang -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks XCTestDriver.m
Run Code Online (Sandbox Code Playgroud)

不要指望代码能够编译,但它应该会给您一个想法。如果您有任何疑问,请随时询问。另请参阅 XCTest 框架的标题以了解有关其类及其文档的更多信息。