54

一些背景:

我有一个目标配置为运行 unitTests 的 iOS 应用程序。我正在我的 MacBook 上运行构建自动化工具 jenkins,它会自动构建这个应用程序并运行所有测试(使用命令行 xcodebuild 工具)。

Xcode 4 一切正常。这个构建自动化工具在不同的用户下运行并运行所有这些测试。

我最近切换到 Xcode 5 并开始失败,因为它无法启动模拟器。

问题

我有一个配置为运行测试(逻辑测试)的方案 UnitTests。AI 使用以下两种方法之一运行这些测试:

  • Xcode中的命令U

  • 或命令行“/usr/bin/xcodebuild -scheme UnitTests -sdk iphonesimulator -configuration Release clean build TEST_AFTER_BUILD=YES”

在这两种情况下,它都会尝试启动模拟器。但是,据我了解,它不需要它。无论如何,它在顶级 x86 上运行,并且看起来没有任何应用程序安装在模拟器上。

有没有办法摆脱这个讨厌的模拟器启动(因为它破坏了我的构建自动化)?

更新 1

似乎找到了非常相似的问题,但无法正常工作: Run logic tests in Xcode 4 without launch the simulator

更新 2

我发现非常相关和有趣的问题/答案:Apple CI / Xcode Service and Jenkins

4

6 回答 6

38

使用 xCode 7 和 xCtool。

xctool能够在没有模拟器的情况下执行单元测试。

为了让这个工作,

1. 更新目标设置以在没有主机应用程序的情况下运行。

选择您的项目 --> 然后测试目标 --> 将宿主应用程序设置为无。

在此处输入图像描述

2. 安装 xctool ,如果你没有的话。

brew install xctool

3. 使用带有 xctool 的终端运行测试。

xctool -workspace yourWorkspace.xcworkspace -scheme yourScheme run-tests -sdk iphonesimulator
于 2016-05-25T09:20:14.673 回答
22

您可以创建 Mac OSX 单元测试而不是 iOS 单元测试。这要求您不要在单元测试中包含任何 iOS 特定库。您可以通过以下方式执行此操作:

  1. 选择项目->目标下拉菜单->“添加目标...”
  2. 选择“Mac OSX”->“其他”->“可可单元测试包”
  3. 像创建普通项目一样创建测试包

您现在可以将源添加到单元测试并像 iOS 测试一样运行它,而无需启动模拟器。

于 2013-11-07T13:17:25.007 回答
14

我向苹果工程师提出了同样的问题。不幸的是,您似乎无法做到这一点并同时使用 iOS。您可以采取一些技巧来检查是否进行了测试。您可以将此代码片段放在 AppDelegate.h 或其他一些全局类中,以说明不加载根视图控制器并防止任何奇怪的 ui 内容破坏您的单元测试:

static BOOL isTesting() {
    BOOL isTesting = !isEmpty([[[NSProcessInfo processInfo] environment] objectForKey:@"XCInjectBundle"]);
    return isTesting;
}

我也让苹果工程师验证这是一个合法的检查。并且要在应得的地方给予信任,这来自:以编程方式确定 iOS 项目中的当前目标(运行或测试)

编辑: 我在这方面也取得了成功,而且更直接一点:

static BOOL isTesting() {
    return [[[NSProcessInfo processInfo] processName] isEqualToString:@"xctest"];
}
于 2013-11-12T17:44:47.107 回答
5

osx 测试目标可能会变得非常麻烦,因为您必须自己管理要包含的源文件。放在@testable import YourAppName您的 XCTest 文件之上更方便。因此,只需阻止您的应用程序在 XCTest 运行的情况下启动。

在您的 AppDelegate 中放置:(Swift 3 解决方案)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
    if ProcessInfo.processInfo.environment["XCInjectBundleInto"] != nil {
        return false
    } 

...

这不会阻止模拟器启动,但会为您节省大量时间。

于 2016-12-19T03:15:37.493 回答
2

您可以使用Xcode 9和终端中的命令在无头模式下运行单元和 ui 测试。参考示例命令:

构建和测试工作区

xcrun xcodebuild -workspace "YOUR_WORKSPACE_NAME.xcworkspace" -scheme "YOUR_SCHEME" -sdk "iphonesimulator12.0" -destination "OS=12.0,name=iPhone X" -configuration Debug -enableCodeCoverage YES clean build test

对于项目

xcrun xcodebuild -project "YOUR_PROJECT_NAME.xcodeproj" -scheme "YOUR_SCHEME" -sdk "iphonesimulator12.0" -destination "OS=12.0,name=iPhone X" -configuration Debug -enableCodeCoverage YES clean build test
于 2018-10-05T10:34:27.557 回答
0

解决方法:

应用程序仍会启动,但您可以#if定义您不想运行的内容。

方法:

  1. 创建Test通过复制调用的自定义构建配置Debug(项目>信息>创建新配置)
  2. Build Settings>Active Compilation ConditionsTest添加TESTING
  3. 编辑方案>信息>构建配置,将构建配置设置为测试
  4. 在测试时使用#if !TESTING #endif您不想执行的代码。

构架:

如果您有嵌入式框架,请在框架中创建相同的构建配置,以便正确链接框架二进制文件。

于 2017-10-02T13:28:59.637 回答