Xcode 4:从命令行 (xcodebuild) 运行测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5403991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 03:49:37  来源:igfitidea点击:

Xcode 4: Run tests from the command line (xcodebuild)?

xcodeunit-testingxcode4xcodebuildocunit

提问by Steven Wisener

I've created a brand new iOS project in Xcode 4, and included unit tests. The default app has 2 targets, the main application and the unit test bundle. Using "Product > Test" (Command-U) builds the application, builds the unit test bundle, launches the iOS simulator and runs the tests. Now I'd like to be able to do the same thing from the command line. The command line tool (xcodebuild) doesn't have a "test" action, but it seems like I should be able to build the unit test bundle target directly, since it depends on the application itself. However, running:

我在 Xcode 4 中创建了一个全新的 iOS 项目,并包含了单元测试。默认应用程序有 2 个目标,主应用程序和单元测试包。使用“产品 > 测试”(Command-U)构建应用程序,构建单元测试包,启动 iOS 模拟器并运行测试。现在我希望能够从命令行做同样的事情。命令行工具 (xcodebuild) 没有“测试”操作,但似乎我应该能够直接构建单元测试包目标,因为它取决于应用程序本身。但是,运行:

xcodebuild -target TestAppTests -sdk iphonesimulator4.3 -configuration Debug build

gives the following message:

给出以下消息:

/Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/Tools/RunPlatformUnitTests:95: warning: Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set).

That seems like a lie, since Test Host is set for my unit test bundle target when I run Command-U from the GUI. I've seen previous posts about the separation between logic tests and application tests, but it seems like Xcode 4 does away with that distinction. Any clue how I can run my tests from the command line?

这似乎是个谎言,因为当我从 GUI 运行 Command-U 时,测试主机是为我的单元测试包目标设置的。我看过之前关于逻辑测试和应用程序测试之间分离的帖子,但似乎 Xcode 4 消除了这种区别。任何线索如何从命令行运行我的测试?

回答by Scott Thompson

Important Note

重要的提示

With Xcode 5.1 (perhaps earlier Xcode as well) testis a valid build action.

使用 Xcode 5.1(也许还有更早的 Xcode)test是一个有效的构建操作。

We were able to replace the entire hack below with a call to xcodebuild using the build action of test and with appropriate -destinationoptions. man xcodebuildfor more info.

我们能够使用 test 的构建操作和适当的-destination选项,通过调用 xcodebuild 来替换下面的整个 hack 。 man xcodebuild了解更多信息。

The information below is left here for posterity

下面的信息留在这里供后人使用



I tried hacking Apple's scripts to run unit tests as mentioned in

我尝试破解 Apple 的脚本来运行单元测试,如中所述

Running Xcode 4 unit tests from the command line

从命令行运行 Xcode 4 单元测试

and

Xcode4: Running Application Tests From the Command Line in iOS

Xcode4:在 iOS 中从命令行运行应用程序测试

and numerous similar postings across the web.

以及网络上许多类似的帖子。

However, I ran into a problem with those solutions. Some of our unit tests exercised the iOS Keychain and those calls, when running in the environment that comes from hacking Apple's scripts, failed with an error (errSecNotAvailable[-25291] for the morbidly curious). As a result, the tests always failed... an undesirable feature in a test.

但是,我遇到了这些解决方案的问题。我们的一些单元测试使用了 iOS 钥匙串,当这些调用在来自黑客 Apple 脚本的环境中运行时,失败并显示错误(errSecNotAvailable[-25291] 对于病态的好奇)。结果,测试总是失败……这是测试中不受欢迎的特性。

I tried a number of solutions based on information I found elsewhere on the web. Some of those solutions involved trying to launch the iOS simulator's security services daemon, for example. After struggling with those, My best bet seemed to be to run in the iOS simulator with the full benefit of the simulator's environment.

我根据在网上其他地方找到的信息尝试了许多解决方案。例如,其中一些解决方案涉及尝试启动 iOS 模拟器的安全服务守护程序。在与这些斗争之后,我最好的选择似乎是在 iOS 模拟器中运行,充分利用模拟器环境的优势。

What I did, then was get ahold of the iOS Simulator launching tool ios-sim. This command line tool uses private Apple frameworks to launch an iOS application from the command line. Of particular use to me, however, was the fact that it allows me to pass both Environment Variables and Command Line Arguments to the app that it is launching.

我所做的就是获得 iOS 模拟器启动工具ios-sim。此命令行工具使用私有 Apple 框架从命令行启动 iOS 应用程序。然而,对我特别有用的是,它允许我将环境变量和命令行参数传递给它正在启动的应用程序。

Though the Environment variables, I was able to get my Unit Testing bundle injected into my Application. Through the command line arguments, I can pass the "-SenTest All" needed to get the app to run the unit tests and quit.

通过环境变量,我能够将单元测试包注入到我的应用程序中。通过命令行参数,我可以传递让应用程序运行单元测试并退出所需的“-SenTest All”。

I created a Scheme (which I called "CommandLineUnitTests") for my unit testing bundle and checked the "Run" action in the build section as described in the posts above.

我为我的单元测试包创建了一个 Scheme(我称之为“CommandLineUnitTests”),并检查了构建部分中的“运行”操作,如上面的帖子所述。

Rather than hacking Apple's scripts, though, I replaced the script with one that launches the application using ios-sim and sets up the environment to inject my unit testing bundle into the application separately.

不过,我没有破解 Apple 的脚本,而是将脚本替换为使用 ios-sim 启动应用程序并设置环境以将我的单元测试包单独注入应用程序的脚本。

My script is written in Ruby which is more familiar to me than BASH scripting. Here's that script:

我的脚本是用 Ruby 编写的,我比 BASH 脚本更熟悉。这是那个脚本:

if ENV['SL_RUN_UNIT_TESTS'] then
    launcher_path = File.join(ENV['SRCROOT'], "Scripts", "ios-sim")
    test_bundle_path= File.join(ENV['BUILT_PRODUCTS_DIR'], "#{ENV['PRODUCT_NAME']}.#{ENV['WRAPPER_EXTENSION']}")

    environment = {
        'DYLD_INSERT_LIBRARIES' => "/../../Library/PrivateFrameworks/IDEBundleInjection.framework/IDEBundleInjection",
        'XCInjectBundle' => test_bundle_path,
        'XCInjectBundleInto' => ENV["TEST_HOST"]
    }

    environment_args = environment.collect { |key, value| "--setenv #{key}=\"#{value}\""}.join(" ")

    app_test_host = File.dirname(ENV["TEST_HOST"])
    system("#{launcher_path} launch \"#{app_test_host}\" #{environment_args} --args -SenTest All #{test_bundle_path}")
else
    puts "SL_RUN_UNIT_TESTS not set - Did not run unit tests!"
end

Running this from the command line looks like:

从命令行运行它看起来像:

xcodebuild -sdk iphonesimulator -workspace iPhoneApp.xcworkspace/ -scheme "CommandLineUnitTests" clean build SL_RUN_UNIT_TESTS=YES

After looking for the SL_RUN_UNIT_TESTSenvironment variable, the script finds the "launcher" (the iOS-sim executable) within the project's source tree. It then constructs the path to my Unit Testing Bundle based on build settings that Xcode passes in environment variables.

查找SL_RUN_UNIT_TESTS环境变量后,脚本会在项目的源代码树中找到“启动器”(iOS-sim 可执行文件)。然后它根据 Xcode 在环境变量中传递的构建设置构建我的单元测试包的路径。

Next, I create the set of runtime Environment Variables for my running application that inject the unit testing bundle. I set up those variables in the environmenthash in the middle of the script then use some ruby grunge to join them into a series of command line arguments for the ios-simapplication.

接下来,我为正在运行的应用程序创建了一组运行时环境变量,用于注入单元测试包。我environment在脚本中间的散列中设置这些变量,然后使用一些 ruby​​ grunge 将它们连接到ios-sim应用程序的一系列命令行参数中。

Near the bottom I grab the TEST_HOSTfrom the environment as the app I want to launch and the systemcommand actually executes ios-simpassing the application, the command arguments to set up the environment, and the arguments -SenTest Alland the test bundle path to the running application.

在底部附近,我TEST_HOST从环境中获取我想要启动的应用程序,system命令实际执行,ios-sim传递应用程序、设置环境的命令参数-SenTest All以及运行应用程序的参数和测试包路径。

The advantage of this scheme is that it runs the unit tests in the simulator environment much as I believe Xcode itself does. The disadvantage of the scheme is that it relies on an external tool to launch the application. That external tool uses private Apple frameworks, so it may be fragile with subsequent OS releases, but it works for the moment.

这种方案的优点是它在模拟器环境中运行单元测试,就像我相信 Xcode 本身一样。该方案的缺点是它依赖于外部工具来启动应用程序。该外部工具使用私有的 Apple 框架,因此它在后续操作系统版本中可能很脆弱,但目前可以使用。

P.S. I used "I" a lot in this post for narrative reasons, but a lot of the credit goes to my partner in crime, Pawel, who worked through these problems with me.

PS 出于叙述原因,我在这篇文章中经常使用“我”,但很多功劳归功于我的犯罪伙伴 Pawel,他与我一起解决了这些问题。

回答by makdad

I was inspired by Jonah's post and found a way to do it:

我受到了 Jonah 帖子的启发,并找到了一种方法:

http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/

http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/

Basically, you need Xcode 4 and you have to hack a script to make it work, but it does.

基本上,你需要 Xcode 4 并且你必须破解一个脚本才能让它工作,但它确实如此。

The key point is convincing Xcode 4 to run your iOS test bundle as if it was a MacOS X bundle - it's a problem with the platform, Xcode doesn't want to run application tests out of the box on the command line. Funny, because it seems to work.

关键点是说服 Xcode 4 像运行 MacOS X 包一样运行你的 iOS 测试包——这是平台的问题,Xcode 不想在命令行上运行开箱即用的应用程序测试。有趣,因为它似乎有效。

There's also a sample project on the site.

网站上还有一个示例项目。

回答by bigkm

what you're looking for is this undocumented argument (you do need sdk and target too) to run your OCUnit Tests from the terminal

您正在寻找的是这个未记录的参数(您也需要 sdk 和 target)来从终端运行您的 OCUnit 测试

xcodebuild  -target MyTarget -sdk iphonesimulator   TEST_AFTER_BUILD=YES

回答by Jonah

It's an incomplete solution but I was able to run command line builds of logic tests in their own scheme and build target: http://blog.carbonfive.com/2011/04/06/running-xcode-4-unit-tests-from-the-command-line/

这是一个不完整的解决方案,但我能够以自己的方案运行逻辑测试的命令行构建并构建目标:http: //blog.carbonfive.com/2011/04/06/running-xcode-4-unit-tests-从命令行/

回答by skrusche

xctool solves this issue: https://github.com/facebook/xctool

xctool 解决了这个问题:https: //github.com/facebook/xctool

we use it on our continuous integration server without problems

我们在我们的持续集成服务器上使用它没有问题