Requirements:
- OS X Yosemite 10.10.5
- Xcode 7.2.1
- iOS Device (9.2.1)
- Homebrew
- Git
- SafariLauncher
- Appium (1.4.16)
- Apple ID with *Provisioning Profile (iOS Development)
*Note: Free iOS Development Provisioning Profile can be created via Xcode 7
I. Create iOS Development Provisioning Profile for SafariLauncher
- Clone https://github.com/budhash/SafariLauncher.git
- Open the project in Xcode
- Open Xcode > Preferences > Accounts
- Add an Apple ID
- Click the apple id and click View Details
- Create iOS Development Signing Identities
II. Create Provisioning Profile for SafariLauncher
- Using the same xcode project, provide ‘Bundle Identifier’ value.
i.e.com.github.blago.SafariLauncher
- Fix the issue with Provisioning Profile
- After fixing the issue, provide deployment information
- For Xcode 7.2.1, click Build Settings and edit Code Signing section
- Build and run SafariLauncher on the iOS Device
- Trust the developer of the app in the iOS Device.
Go to Settings > General > Device Management
III. Build SafariLauncher for Real Devices (using appium source)
- Clone https://github.com/appium/appium.git
- SHA-1 hash used: 54c2b4e6500eddbca4bb3047116ceb8d177f7294
- git checkout 54c2b4e6500eddbca4bb3047116ceb8d177f7294
- Go to the appium directory (clone) and edit reset.sh then provide the BUNDLE_ID used in the provisioning profile
- Run the command inside the appium directory
./reset.sh --ios --real-safari --verbose
IV. Install Homebrew Packages
- Do the following command
brew update
brew install libimobiledevice libplist libtasn1 usbmuxd openssl ideviceinstaller
brew install ios-webkit-debug-proxy
brew install node
V. iOS Device Configuration
- Enable UI Automation (Settings > Developer)
- Turn on Safari Web Inspector (Settings > Safari > Advanced)
VI. Appium Server Configuration
- Start ios_webkit_debug_proxy
ios_webkit_debug_proxy -c <iOS_SERIAL_NUMBER>:27753
- Start the sever inside the appium directory
node . -U <iOS_SERIAL_NUMBER> --app 'safari' --command-timeout 120
iOS_SERIAL_NUMBER can be found in
About This Mac > Overview > System Report > Hardware > USB
VII. Code Configuration
String hubUrl = "http://127.0.0.1:4723/wd/hub"; String iOSBrowserName = "Safari"; String iOSDeviceName = "<iOS_SERIAL_NUMBER>"; String iOSVersion = “9.2”; DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability("deviceName", iOSDeviceName); capabilities.setCapability("platformName", "iOS"); capabilities.setCapability("platformVersion", iOSVersion); capabilities.setCapability("browserName", iOSBrowserName); WebDriver driver = new RemoteWebDriver(new URL(hubUrl), capabilities);
VIII. Possible Runtime Errors
- FBSOpenApplicationErrorDomain error
info: [debug] [INST STDERR] Instruments Trace Error : Target failed to run: The operation couldn’t be completed. (FBSOpenApplicationErrorDomain error 3.) : Failed to launch process with bundle identifier ‘com.github.blago.SafariLauncher'
Solution:
Trust the developer who signed the SafariLauncher app (Settings > General > Device Management)
- ideviceinstaller error
Error: Command failed: /bin/sh -c ideviceinstaller
Solution:
Select the target device in Xcode for the SafariLauncher then restart the appium node.
IX. Sample Appium Server Output with iOS Device Screen
- On standby, waiting for test to run
- Test executed, SafariLauncher started on iOS device.
- Actual test being executed, application under test is m.facebook.com
Click here to watch the execution.
Thanks for visiting my blog!
Bernard, Thank you! Thank you!!!
ReplyDeleteI spent the whole weekend trying to make this work. Then I found your article...
Very grateful to you for putting all this together in a clear way.
Cheers
Omer Shatil
Will this work for Xcode 7.1
ReplyDeleteHi Bernard,
ReplyDeleteGetting the below Error,Will you please help me.
An App ID with Identifier 'com.github.blago.SafariLauncher' is not available. Please enter a different string.
The free ios provisioning started with Xcode 7... It might work.
DeleteProvide your own bundle id for the app. That one was already used and was provided as an example.
Thank you, it is works. Can I know how to do it in simulator, since there is no serial number for simulator.
ReplyDeleteInside the appium directory start the node using:
Deletenode . --app 'safari'
If there are errors such as the one below...
error: uncaughtException: Cannot find module 'rimraf'
Just do the following command inside the appium directory:
npm install rimraf
Some modules are: adm-zip, mkdirp
For the script setup:
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", "iPhone 6");
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("platformVersion", "9.2");
capabilities.setCapability("browserName", "safari");
driver = new RemoteWebDriver(new URL(hubUrl), capabilities);
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.get(url);
With XCode 7.2.1, available devices are:
["iPad 2 (9.2) [5938A9F7-A0D2-49C7-8F15-F07B34F58FBC]","iPad Air (9.2) [ADDFBAFE-4F28-44C0-A492-8A1E4D699EA0]","iPad Air 2 (9.2) [E041DAAA-FF81-449B-A8DE-DE73CC032803]","iPad Pro (9.2) [1B693D22-DDA3-4B59-A399-BDC48469D626]","iPad Retina (9.2) [94F3009C-B287-44B7-AF18-54402F9D7D3B]","iPhone 4s (9.2) [4A7C33D1-9A4C-432F-B6A0-6CE0DB6951D8]","iPhone 5 (9.2) [90CA0C5A-E732-408E-A60F-C52D74D66081]","iPhone 5s (9.2) [EE817852-113F-41F9-85EB-D69852E00A6F]","iPhone 6 (9.2) [D15DB589-368A-482F-B4F0-CDE525A7C380]","iPhone 6 Plus (9.2) [63BC22C8-47DF-4DA8-AE62-A779B5CA6629]","iPhone 6s (9.2) [1EACC8D5-B07F-4906-A491-84412E5473F8]","iPhone 6s (9.2) + Apple Watch - 38mm (2.1) [C393DB9E-0C9E-4F29-8576-FBD119955BCE]","iPhone 6s Plus (9.2) [0F3B4E66-1E12-4A38-90BD-D7A7071E760C]","iPhone 6s Plus (9.2) + Apple Watch - 42mm (2.1) [1306CD4C-E745-483E-8782-4A04F390B019]"]
Thanks for reply, how about the ios_webkit_debug_proxy, it is not working, because error come with this line
Deletenew RemoteWebDriver(new URL(hubUrl), capabilities);
debug proxy is no longer needed if you're starting an iOS simulator. That is needed for the real device.
DeleteYou need to define the hub url:
String hubUrl = "http://127.0.0.1:4723/wd/hub"
WebDriver driver = new RemoteWebDriver(new URL(hubUrl), capabilities);
DeleteYa, I already defined before that. I mean the error is come from the hubUrl
DeleteWhich error?
DeletePaste the error here: http://pastebin.com
Just
DeleteException in thread "main" org.openqa.selenium.UnsupportedCommandException: That URL did not map to a valid JSONWP resource
If the appium node is successfully started, there shouldn't be any problem with this:
DeleteString hubUrl = "http://127.0.0.1:4723/wd/hub";
WebDriver driver = new RemoteWebDriver(new URL(hubUrl), capabilities);
Paste this in your browser to check if the node is started.
http://127.0.0.1:4723/wd/hub/status
Other than that, you can try tweaking the values to localhost instead of 127.0.0.1
Working fine.Great article.
ReplyDeleteis it possible to excute the script on Multiple Devices at the same time?(Real Devices)
Yes, familiarize yourself with using Selenium Grid and TestNG.
DeleteHere's an example of a testng suite:
https://github.com/SrinivasanTarget/AppiumIOSParallel/blob/master/testng.xml
For the selenium grid config, you'll need a nodeconfig.json file.
you can refer to this:
https://github.com/appium/appium/issues/273
REMOTE_DEBUGGER_PORT=27753
node appium --session-override --nodeconfig /path/to/iOSDevice1.json --show-ios-log --tmp /tmp/iOSDevice1/ -p 4623 --bootstrap-port 4464 --webkit-debug-proxy-port 27753 --full-reset --native-instruments-lib --safari > logs/iOSDevice1.txt &
REMOTE_DEBUGGER_PORT=27754
node appium --session-override --nodeconfig /path/to/iOSDevice2.json --show-ios-log --tmp /tmp/iOSDevice2/ -p 4523 --bootstrap-port 4465 --webkit-debug-proxy-port 27754 --full-reset --native-instruments-lib --safari > logs/iOSDevice2.txt &
REMOTE_DEBUGGER_PORT=27753
./ios-webkit-debug-proxy-launcher.js -c DEVICE_1_SERIAL:27753 -d > logs/log_iwdpl.txt &
REMOTE_DEBUGGER_PORT=27754
./ios-webkit-debug-proxy-launcher.js -c DEVICE_2_SERIAL:27754 -d > logs/log_iwdpl2.txt
Hi Bernard,
ReplyDeleteThanks for such a wonderful article. It has helped a lot. But, I'm facing a problem. I'm able to launch safari using SafariLauncher, but the URL is not entered in the safari browser. It seems as if the control is not passed from SafariLauncher app to safari browser. Please help here. Also, safariLauncher is opened if I pass the path of .app of safariLauncher in App Path. If I select the 'Mobile Safari' option in appium and pass 'Safari' as browserName, then error is thrown with message 'A new session could not be created.' I have a understanding the safari browser will be launched via SafariLauncher only by our scripts. Pls correct me if I'm wrong and help me with the solution.
Thanks,
Prashant
Are you using appium GUI? since you stated that you're selecting 'Mobile Safari'. Start the appium via terminal using node, after building it from source using:
Delete./reset.sh --ios --real-safari --verbose
Safari is launched via SafariLauncher, generated by the command above.
If you encounter 'A new session could not be created.', you can always restart the appium node via Ctrl+C command in the terminal.
Thanks Bernard. Yes, I was trying with the appium GUI. Also, I figured out the issue I was facing. The issue was that the control was not being passed from SafariLauncher app to safari browser. I did some research on it and got the solution to use context switching and it worked. Alternatively, we can set the 'autoWebview' desired Capabilities to 'true' to overcome this. Both of the above solution worked for me. Please let me know if my understanding is not right.
DeleteThanks,
Prashant
Hello Bernard,
ReplyDeleteIs it possible to update your example and blog to use the latest Appium 1.5.3?
As the latest Appium 1.5.3 has removed the reset.sh script I am at a lost.
Thanks,
-----John.
With iphone5s I'm getting the following error (on Appium 1.5.3):
ReplyDeleteorg.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: We exceeded the number of retries allowed for instruments to successfully start; failing launch (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 34.20 seconds
Build info: version: '3.0.0-beta2', revision: '2aa21c1', time: '2016-08-02 15:03:28 -0700'
System info: host: 'ip-10-207-203-234.ec2.internal', ip: '10.207.203.234', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.6', java.version: '1.8.0_102'
Driver info: io.appium.java_client.ios.IOSDriver
Can you please help me with this. Appium Inspector is working fine
You don't really have to use the appium java_client package for Mobile Safari.
DeleteRemote WebDriver with DesiredCapabilites will suffice as indicated in the Code Configuration section of the blog.
String hubUrl = "http://127.0.0.1:4723/wd/hub";
String iOSBrowserName = "safari";
String iOSDeviceName = "";
String iOSVersion = “9.2”;
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", iOSDeviceName);
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("platformVersion", iOSVersion);
capabilities.setCapability("browserName", iOSBrowserName);
WebDriver driver = new RemoteWebDriver(new URL(hubUrl), capabilities);
Hello bernard, I am still wondering how were you able to display the Real Iphone to the laptop screen?
ReplyDeleteQuickTime Player
Deletesee https://youtu.be/ZZ_UFqN12Rs
Is it possbile to do this on windows laptop connected to IOS devices
ReplyDeleteYou obviously need OSX for this to work with iOS devices.
DeleteHi Mr Lago, after cloning appium, I can't find reset.sh file. Please!
ReplyDeletereset.sh is no longer present in the appium's master branch (v 1.6 beta 2)
ReplyDeleteThis is applicable for appium v1.4.16, iOS 9.2 and Xcode 7.2.1.
If you still want to try it with v1.4.16 in the clone directory of appium, run the ff command:
git checkout 54c2b4e6500eddbca4bb3047116ceb8d177f7294
This was the revision used for this blog as indicated in section III.
I haven't tried the latest version of appium since I am no longer working on any iOS mobile safari automation.
If you have iOS 9.3, you will have to use Xcode 7.3.1.
If you have iOS 10+, you will have to use Xcode 8. But, this configuration will no longer be applicable since Apple deprecated UIAutomation from Xcode.
See
https://discuss.appium.io/t/ios9-uiautomation-what-is-appium-approach-to-uiautomation-deprecation-by-apple/7319
https://github.com/appium/appium/issues/6597
Thanks for your reply. I rollback appium v1.4.0 and I am using it. But, I face an error. I can't navigate an URL. Thank you!
DeleteThis is my code:
String myURL = "http://reputa.vn";
String hubUrl = "http://127.0.0.1:4723/wd/hub";
String iOSDeviceName = "86f9ee569fb6a89ef223b49e1986c182d175c703";
String iOSVersion = "9.3";
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", iOSDeviceName);
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("platformVersion", iOSVersion);
capabilities.setCapability("app","/Users/kakalot/Desktop/SafariLauncher.app");
WebDriver driver = new RemoteWebDriver(new URL(hubUrl), capabilities);
driver.get(myURL);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
Appium's log:
info: --> POST /wd/hub/session {"desiredCapabilities":{"app":"/Users/kakalot/Desktop/SafariLauncher.app","platformVersion":"9.3","platformName":"iOS","deviceName":"86f9ee569fb6a89ef223b49e1986c182d175c703"}}
info: Client User-Agent string: Apache-HttpClient/4.5.2 (Java/1.8.0_60)
info: *************************************
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: **** NEW SESSION ***
info: *************************************
info: [debug] Using local app from desired caps: /Users/kakalot/Desktop/SafariLauncher.app
info: [debug] Creating new appium session 67c6bb44-6ef5-41ac-a7c6-976dba134122
{"id":""},"enabled":true,"valid":true,"visible":false,"hint":"","path":"/0/1/4/0/0/11","x":0,"y":893,"width":70,"height":72},">":{"webStorageEnabled":false,"locationContextEnabled":false,"browserName":"iOS","platform":"MAC","javascriptEnabled":true,"databaseEnabled":false,"takesScreenshot":true,"networkConnectionEnabled":false,"warnings":{},"desired":{"app":"/Users/kakalot/Desktop/SafariLauncher.app","platformVersion":"9.3","platformName":"iOS","deviceName":"86f9ee569fb6a89ef223b49e1986c182d175c703"},"app":"/Users/kakalot/Desktop/SafariLauncher.app","platformVersion":"9.3","platformName":"iOS","deviceName":"86f9ee569fb6a89ef223b49e1986c182d175c703"},"sessionId":"67c6bb44-6ef5-41ac-a7c6-976dba134122"}
info: --> POST /wd/hub/session/67c6bb44-6ef5-41ac-a7c6-976dba134122/url {"url":"http://reputa.vn"}
Here's the latest post using appium 1.6.0 and iPhone 6 Simulator
ReplyDelete(iOS 10 and Xcode 8)
http://bernardlago.blogspot.com/2016/10/running-mobile-web-tests-on-iphone-6.html
Hi, Thanks for such a wonderful post!! Are you planning to create a blog for Real Device IOS automation with Appium for latest versions of IOS & Xcode or your current blog will support real ios for the latest versions too??
ReplyDeleteI am just using the "FREE" provisioning profile, I am limited to running it on simulators.
Deletehttp://bernardlago.blogspot.com/2016/10/running-mobile-web-tests-on-iphone-6.html
For real devices, you'll need a development team and provisionining profile to build and code-sign WebDriverAgent - which is needed to be installed on the device.
https://github.com/appium/appium-xcuitest-driver#real-devices
with an app on your phone, and also continue to prolific on your tablet or desktop computer, and it is now becoming more and more common. originally us mobile app developer
ReplyDelete