Xcode 4:从命令行(xcodebuild)运行测试?
我在 Xcode 4 中创建了一个全新的 iOS 项目,并包含单元测试。默认应用程序有 2 个目标,主应用程序和单元测试包。使用“Product > Test”(Command-U) 构建应用程序、构建单元测试包、启动 iOS 模拟器并运行测试。现在我希望能够从命令行执行同样的操作。命令行工具(xcodebuild)没有“测试”操作,但似乎我应该能够直接构建单元测试包目标,因为它取决于应用程序本身。但是,运行:
xcodebuild -target TestAppTests -sdk iphonesimulator4.3 -configuration Debug build
会给出以下消息:
/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).
这似乎是一个谎言,因为当我从 GUI 运行 Command-U 时,测试主机已为我的单元测试捆绑包目标设置。我之前看过有关逻辑测试和应用程序测试之间分离的文章,但 Xcode 4 似乎消除了这种区别。有什么线索可以让我从命令行运行测试吗?
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:
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
重要提示
对于 Xcode 5.1(也许还有更早的 Xcode),
test
是有效的构建操作。我们能够使用 test 的构建操作和适当的
-destination
选项通过调用 xcodebuild 来替换下面的整个 hack。man xcodebuild
了解更多信息。下面的信息留在这里供后代使用
我尝试破解Apple的脚本来运行单元测试,如
从命令行运行 Xcode 4 单元测试
和
Xcode4: Running Application Tests From the Command Line in iOS
以及网络上许多类似的帖子。
但是,我在这些解决方案中遇到了问题。我们的一些单元测试使用了 iOS 钥匙串,当在来自破解 Apple 脚本的环境中运行时,这些调用因错误而失败(对于病态好奇的人来说,
errSecNotAvailable
[-25291])。结果,测试总是失败……这是测试中不受欢迎的功能。我根据在网络上其他地方找到的信息尝试了多种解决方案。例如,其中一些解决方案涉及尝试启动 iOS 模拟器的安全服务守护进程。在与这些问题作斗争之后,我最好的选择似乎是在 iOS 模拟器中运行,并充分利用模拟器环境的优势。
然后我所做的是获取 iOS 模拟器启动工具 ios-sim。该命令行工具使用私有 Apple 框架从命令行启动 iOS 应用程序。然而,对我来说特别有用的是,它允许我将环境变量和命令行参数传递给它正在启动的应用程序。
通过环境变量,我能够将单元测试包注入到我的应用程序中。通过命令行参数,我可以传递让应用程序运行单元测试并退出所需的“-SenTest All”。
我为我的单元测试包创建了一个方案(我将其称为“CommandLineUnitTests”),并检查了构建部分中的“运行”操作,如上面的帖子中所述。
不过,我并没有破解 Apple 的脚本,而是用使用 ios-sim 启动应用程序的脚本替换了该脚本,并设置了环境以将我的单元测试包单独注入到应用程序中。
我的脚本是用 Ruby 编写的,我比 BASH 脚本更熟悉它。这是该脚本:
从命令行运行该脚本如下所示:
查找 SL_RUN_UNIT_TESTS 环境变量后,脚本在项目的源代码树中找到“启动器”(iOS-sim 可执行文件)。然后,它根据 Xcode 在环境变量中传递的构建设置构建单元测试包的路径。
接下来,我为正在运行的应用程序创建一组运行时环境变量,以注入单元测试包。我在脚本中间的环境哈希中设置了这些变量,然后使用一些 ruby grunge 将它们加入到 ios-sim 应用程序的一系列命令行参数中。
在底部附近,我从环境中获取
TEST_HOST
作为我想要启动的应用程序,并且system
命令实际上执行传递应用程序的ios-sim
、设置环境的命令参数、参数-SenTest All
以及正在运行的应用程序的测试包路径。这个方案的优点是它在模拟器环境中运行单元测试,就像我相信 Xcode 本身所做的那样。该方案的缺点是它依赖于外部工具来启动应用程序。该外部工具使用私有 Apple 框架,因此在后续操作系统版本中它可能会很脆弱,但目前可以使用。
PS 出于叙述原因,我在这篇文章中多次使用“我”,但很大程度上要归功于我的犯罪伙伴 Pawel,他和我一起解决了这些问题。
Important Note
With Xcode 5.1 (perhaps earlier Xcode as well)
test
is a valid build action.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.The information below is left here for posterity
I tried hacking Apple's scripts to run unit tests as mentioned in
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.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.
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.
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.
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.
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.
My script is written in Ruby which is more familiar to me than BASH scripting. Here's that script:
Running this from the command line looks like:
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.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 theios-sim
application.Near the bottom I grab the
TEST_HOST
from the environment as the app I want to launch and thesystem
command actually executesios-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.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.
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.
我受到乔纳的帖子的启发,找到了一种方法:
http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/
基本上,你需要 Xcode 4 并且必须编写一个脚本才能使其工作,但它确实如此。
关键点是说服 Xcode 4 运行您的 iOS 测试包,就好像它是 MacOS X 包一样 - 这是平台的问题,Xcode 不想在命令行上开箱即用地运行应用程序测试。有趣的是,因为它似乎有效。
该网站上还有一个示例项目。
I was inspired by Jonah's post and found a way to do it:
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.
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.
There's also a sample project on the site.
您正在寻找的是这个未记录的参数(您也需要 sdk 和目标)来从终端运行 OCUnit 测试
what you're looking for is this undocumented argument (you do need sdk and target too) to run your OCUnit Tests from the terminal
这是一个不完整的解决方案,但我能够在自己的方案和构建目标中运行逻辑测试的命令行构建: http://blog.carbon Five.com/2011/04/06/running-xcode-4-unit-tests-from-the-命令行/
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/
xctool 解决了这个问题:https://github.com/facebook/xctool
我们在持续集成中使用它服务器没有问题
xctool solves this issue: https://github.com/facebook/xctool
we use it on our continuous integration server without problems