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

I created a new iOS project in Xcode 4 and included unit tests. The default application has 2 goals, the main application and the unit test package. Using "Product> Test" (Command-U) creates the application, creates the unit test package, runs the iOS simulator and runs the tests. Now I would like to be able to do the same from the command line. The command line tool (xcodebuild) does not have a β€œtest” action, but it looks like I should be able to directly compose the target of the unit test package, since it depends on the application itself. However, the launch:

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

displays 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). 

This seems to be false since Test Host is installed for my unit test purpose when I run Command-U from the GUI. I have seen previous posts about the separation between logic tests and application tests, but Xcode 4 seems to eliminate this difference. Any hint how can I run my tests from the command line?

+46
unit-testing xcode xcode4 xcodebuild ocunit
Mar 23 2018-11-11T00:
source share
5 answers

Important Note

With Xcode 5.1 (possibly an earlier Xcode), test is a valid build action.

We were able to replace the entire hack below with an xcodebuild call using the test build action and with the appropriate -destination parameters. man xcodebuild for more information.

Information below is for posterity




I tried to hack Apple scripts to run unit tests as indicated in

Run Xcode 4 unit tests from the command line

and

Xcode4: running application tests from the command line in iOS

and numerous similar publications on the Internet.

However, I had a problem with these solutions. Some of our unit tests used iOS Keychain, and these calls when working in an environment caused by hacking Apple scripts failed with an error ( errSecNotAvailable [- 25291] for strangely curious people). As a result, tests always failed ... an unwanted function in the test.

I tried a number of solutions based on the information I found elsewhere on the Internet. Some of these solutions included, for example, trying to launch the iOS simulator security services daemon. After I struggled with them, the best option seemed to be running in an iOS simulator with the full advantage of a simulator environment.

What I did then was get the iOS Simulator ios-sim launch tool. This command line tool uses Apple's private frameworks to launch an iOS application from the command line. However, it was especially useful to me that it allows me to pass both environment variables and command line arguments to the application that it runs.

Despite the environment variables, I managed to get the Unit Testing package introduced in my application. Through command line arguments, I can pass "-SenTest All" to get the application to run unit tests and exit.

I created a circuit (which I called "CommandLineUnitTests") for my module testing module and checked the "Run" action in the build section, as described in the messages above.

Instead of hacking Apple scripts, I replaced the script with the one that launches the application using ios-sim, and sets up the environment for entering my module testing module into the application separately.

My script is written in Ruby, which is more familiar to me than BASH scripting. Here's the 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 this:

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

After searching for the environment variable SL_RUN_UNIT_TESTS , the script finds the "launcher" (iOS-sim executable file) in the project source tree. He then constructs the path to my unit batch testing based on the build parameters that Xcode passes in the environment variables.

Then I create a set of runtime variables for my running application that inject the unit testing package. I set these variables in the environment hash in the middle of the script, and then used some ruby ​​grunge to combine them into a series of command line arguments for the ios-sim application.

Next to the bottom, I take TEST_HOST from the environment as the application that I want to run, and the system command actually performs the ios-sim transfer of the application, the arguments of the command to configure the environment and the arguments -SenTest All and the path of the test package to the running application.

The advantage of this scheme is that it runs unit tests in a simulator environment, since I believe that Xcode itself. The drawback of the circuit is that it uses an external tool to run the application. This external tool uses Apple's private frameworks, so it can be fragile with subsequent releases of the OS, but it works at the moment.

PS I used β€œI” a lot in this post for storytelling reasons, but the great merit of my partner in crime is Pavel, who worked with me with these problems.

+47
May 30 '12 at 20:06
source share

I was inspired by John's post and found a way to do this:

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

Basically, you need Xcode 4, and you need to hack the script for it to work, but it does.

The key point is persuading Xcode 4 to launch the iOS test suite, as if it were a MacOS X package - this is a platform problem, Xcode does not want to run application tests from the box on the command line. Funny because it works.

There is also an example project on the site.

+9
Apr 17 2018-11-11T00:
source share

what you are looking for is an undocumented argument (you need sdk and target too) to run OCUnit tests from the terminal

 xcodebuild -target MyTarget -sdk iphonesimulator TEST_AFTER_BUILD=YES 
+8
Sep 10 '12 at 6:26
source share

This is an incomplete solution, but I was able to start the assembly of logical tests in my own scheme and create a goal: http://blog.carbonfive.com/2011/04/06/running-xcode-4-unit-tests-from-the-command -line /

+5
Apr 6 '11 at 20:45
source share

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

we use it on our continuous integration server without any problems

+3
Jun 21 '13 at 6:46
source share



All Articles