【问题标题】:Don't launch simulator when running unittests运行单元测试时不要启动模拟器
【发布时间】:2013-08-10 16:13:45
【问题描述】:

一些背景:

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

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

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

问题

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

  • 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 launching the simulator

更新 2

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

【问题讨论】:

  • 这个问题也可能有帮助。对于 iOS 应用程序,这些步骤应该几乎相同。 stackoverflow.com/questions/19219706/…
  • @CleverError:谢谢。我会看的。
  • 为什么不想运行模拟器?
  • @quellish:因为从 Xcode 5 开始,如果你在不同的用户(没有 UI 会话)下运行它是一个问题
  • @VictorRonin ,在早期版本的 Xcode 上也是如此。然而,Xcode 5 确实支持在无头模式下运行这些场景。 Xcode Server 以这种方式工作。在早期版本的 Xcode 中,可以将模拟器作为守护程序用户运行,但很难正确设置。要在测试中使用 iPhone 特定功能(如 UIKit),您需要模拟器。

标签: ios xcode jenkins


【解决方案1】:

使用 xCode 7 和 xCtool。

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

为了让它工作,

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

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

2。如果没有,请安装 xctool。

brew install xctool

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

xctool -workspace yourWorkspace.xcworkspace -scheme yourScheme run-tests -sdk iphonesimulator

【讨论】:

【解决方案2】:

您可以创建 Mac OSX 单元测试而不是 iOS 单元测试。这要求您不要在单元测试中包含任何 iOS 特定库。您可以通过以下方式做到这一点:

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

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

【讨论】:

  • 这就是我现在前进的方向。但是,iOS 和 OS X 并不是完全相同的操作系统(尤其是考虑到框架之间的所有差异)
【解决方案3】:

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

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

我还让一位苹果工程师确认这是一个合法的检查。并且要在应得的地方给予信任,这是来自:Programmatically determine current target (run or test) in iOS project

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

static BOOL isTesting() {
    return [[[NSProcessInfo processInfo] processName] isEqualToString:@"xctest"];
}

【讨论】:

  • 我猜你想做:return isTesting;而不是'return NO;'
  • 是的,抱歉。粘贴了一个项目的代码,没注意!
  • 这是一个有趣的解决方案!
【解决方案4】:

一个 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
    } 

...

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

【讨论】:

  • 我不明白,如果它不能阻止模拟器启动,这怎么能回答这个问题?
【解决方案5】:

您可以使用 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

【讨论】:

    【解决方案6】:

    解决方法:

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

    方法:

    1. 通过复制 Debug 创建一个名为 Test 的自定义构建配置(项目 > 信息 > 创建新配置)
    2. Build Settings > Active Compilation ConditionsTest 添加TESTING
    3. Edit Scheme > Info > Build Configuration,设置构建配置为Test
    4. 在测试时不想执行的代码周围使用#if !TESTING#endif

    框架:

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

    【讨论】:

      猜你喜欢
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 2021-07-21
      • 1970-01-01
      • 2021-01-23
      • 2020-03-24
      相关资源
      最近更新 更多