Xcode 4:从命令行 (xcodebuild) 运行测试? [英] Xcode 4: Run tests from the command line (xcodebuild)?

查看:23
本文介绍了Xcode 4:从命令行 (xcodebuild) 运行测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

给出以下消息:

/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 消除了这种区别.知道如何从命令行运行测试吗?

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?

推荐答案

重要提示

使用 Xcode 5.1(可能还有更早的 Xcode)test 是有效的构建操作.

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

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.

以下信息留给后人

我尝试破解 Apple 的脚本来运行

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

运行来自命令行的 Xcode 4 单元测试

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

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

and numerous similar postings across the web.

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

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 模拟器的安全服务守护程序.在与这些斗争之后,我最好的选择似乎是在 iOS 模拟器中运行,并充分利用模拟器环境的优势.

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-sim.此命令行工具使用私有 Apple 框架从命令行启动 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.

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

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.

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

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.

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

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.

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

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

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

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

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.

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

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.

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

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.

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

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.

附言出于叙述原因,我在这篇文章中经常使用我",但很大程度上要归功于我的犯罪伙伴 Pawel,他与我一起解决了这些问题.

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.

这篇关于Xcode 4:从命令行 (xcodebuild) 运行测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆