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
Xcode 4: Run tests from the command line (xcodebuild)?
提问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) test
is 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 -destination
options. man xcodebuild
for 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
and
和
Xcode4: Running Application Tests From the Command Line in 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_TESTS
environment 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 environment
hash in the middle of the script then use some ruby grunge to join them into a series of command line arguments for the ios-sim
application.
接下来,我为正在运行的应用程序创建了一组运行时环境变量,用于注入单元测试包。我environment
在脚本中间的散列中设置这些变量,然后使用一些 ruby grunge 将它们连接到ios-sim
应用程序的一系列命令行参数中。
Near the bottom I grab the TEST_HOST
from the environment as the app I want to launch and the system
command actually executes ios-sim
passing the application, the command arguments to set up the environment, and the arguments -SenTest All
and 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 帖子的启发,并找到了一种方法:
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
我们在我们的持续集成服务器上使用它没有问题