For freedom!!!! to install and uninstall the app whenever I want!

Guys,

I have been working with my colleague @snevesbarros on implementing a more flexible functionality of controlling install/uninstall process of the app for real device. Our goal was to have a stable appium server running independently with possibility to: 
* deploy app to a real device as determined by the test (e.g. as part of the before class)
* delete app from a real device as determined by the test (e.g. as part of the after class)
* provide concise feedback to the test around (un)installation (and any error that might have occurred)

The biggest advantages compared to the existing solution in appium are:
* Both solutions can live side by side in appium (e.g. node-idevice
 and fruistrap) 
* Appium does not have to start with specified \*.ipa file (UDID is enough to run server, the rest is done from Java on webdriver side)
* \*.zip, \*.ipa and \*.app files are accepted to proceed with installation
Using the bundleID the user can uninstall app or check if the app exists on the device.
* This solution can also be applied to Android (additional changes required as we only focussed on iOS).

To get this functionality you need to have <a href="https://github.com/tborys/fruitstrap">this</a> version of fruitstrap  installed on your machine in directory /usr/bin/ . 
We can look to see if this can be installed automatically using e.g. grunt.

We have also added an example of the changes made to a local web driver to add the 3 additional methods to call the end points.

Below are example logs from a simple test which uninstalls the app if exists on the device, installs latest version and launches the app.

testNG

[TestNG] Running:
  /private/var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/testng-eclipse-63914994/testng-customsuite.xml

2013-06-20 17:00:43 REPORTER [INFO] Thread [1] - Info - Information: [Finished loading properties from file [/test.properties]]
 - ##### - Starting Test [correctLoginTest] Thread [1] - ###### - 
2013-06-20 17:00:44 REPORTER [INFO] Thread [1] - Info - Information: [Found the app with bundleID: my.bundleID]
2013-06-20 17:00:44 REPORTER [INFO] Thread [1] - Info - Information: [Successfully removed [my.bundleID] from device with udid [xxxxxxxxxxxxxxxa6749a675e0b853afe9]]
2013-06-20 17:00:57 REPORTER [INFO] Thread [1] - Info - Information: [Successfully unzipped and installed [http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/Jackpotjoy.app] to device with udid [xxxxxxxxxxxxxxxa6749a675e0b853afe9]]
2013-06-20 17:01:21 REPORTER [INFO] Thread [1] - Info - Information: [webDriver instantiated using: Browser [iPad4], Hostname [127.0.0.1], Port [4723]]
 - ##### - Ended Test [correctLoginTest] Thread [1] - ###### - 

2013-06-20 17:01:23 REPORTER [INFO] Thread [1] - Info - Information: [Clear all properties has finished.]
PASSED: correctLoginTest

===============================================
    Default test
    Tests run: 1, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@7776cad3: 2 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@571a75a2: 38 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@6542bece: 14 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@5ff06dc3: 3 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@1f8b81e3: 28 ms 

Appium

/usr/local/bin/node server.js -U xxxxxxxxxxxxxxx6749a675e0b853afe9
info: Welcome to Appium v0.7.3 (REV 2801ddd41520f41945b0e985f19f3d56a67129c4)
info: Appium REST http interface listener started on 0.0.0.0:4723
info: socket.io started
debug: Appium request initiated at /wd/hub/app/installed
debug: Request received with params: {"bundleId":"my.bundleID"}
info: Sending command to terminal to terminal [fruitstrap isInstalled --id xxxxxxxxxxxxxxx6749a675e0b853afe9 --bundle my.bundleID]
info: stdout: [....] Waiting for iOS device to be connected
found device id
[  0%] Found device (xxxxxxxxxxxxxxx6749a675e0b853afe9), beginning check
App is installed!
[100%] Check completed my.bundleID
 
info: child process exited with code 0
info: Responding to client with success: {"status":0,"value":true}
POST /wd/hub/app/installed 200 430ms - 34
debug: Appium request initiated at /wd/hub/app/uninstall
debug: Request received with params: {"bundleId":"com.gamesys.jackpotjoy"}
info: Sending command to terminal to terminal [fruitstrap uninstall --id xxxxxxxxxxxxxxx6749a675e0b853afe9 --bundle my.bundleID]
info: stdout: [....] Waiting for iOS device to be connected
found device id
[  0%] Found device (xxxxxxxxxxxxxxx6749a675e0b853afe9), beginning uninstall
[ 50%] TakingInstallLock
[ 75%] RemovingApplication
[ 95%] GeneratingApplicationMap
[100%] uninstalled package my.bundleID
 
info: child process exited with code 0
info: Responding to client with success: {"status":0,"value":"Successfully removed [my.bundleID] from device with udid [xxxxxxxxxxxxxxx6749a675e0b853afe9]"}
POST /wd/hub/app/uninstall 200 393ms - 142
debug: Appium request initiated at /wd/hub/app/install
debug: Request received with params: {"appPath":"http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/myAPP.zip"}
info: http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/myAPP.zip downloaded to /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/appium-app113520-69786-fvli1f.zip
info: Unzipping /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/appium-app113520-69786-fvli1f.zip
info: Testing zip archive: /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/appium-app113520-69786-fvli1f.zip
info: Zip archive tested clean
info: Unzip successful
info: Sending command to terminal to terminal [fruitstrap install --id xxxxxxxxxxxxxxx6749a675e0b853afe9 --bundle /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/Payload/myApp.app]
info: stdout: [....] Waiting for iOS device to be connected
found device id
[  0%] Found device (xxxxxxxxxxxxxxx6749a675e0b853afe9), beginning install
[  5%] Copying /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/Payload/myApp.app to device
####COPYING FILES #####
[ 52%] CreatingStagingDirectory
[ 57%] ExtractingPackage
[ 60%] InspectingPackage
[ 60%] TakingInstallLock
[ 65%] PreflightingApplication
[ 65%] InstallingEmbeddedProfile
[ 70%] VerifyingApplication
[ 75%] CreatingContainer
[ 80%] InstallingApplication
[ 85%] PostflightingApplication
[ 90%] SandboxingApplication
[ 95%] GeneratingApplicationMap
[100%] Installed package /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/Payload/myApp.app
 
info: child process exited with code 0
info: Responding to client with success: {"status":0,"value":"Successfully unzipped and installed [http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/myAPP.zip] to device with udid [xxxxxxxxxxxxxxx6749a675e0b853afe9]"}
POST /wd/hub/app/install 200 13032ms - 290
debug: Appium request initiated at /wd/hub/session
debug: Request received with params: {"desiredCapabilities":{"platform":"MAC","app":"http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/myAPP.zip","acceptSslCerts":true,"browserName":"iPad4","version":"6.1.3"}}
info: Using downloadable app from desiredCaps: http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/myAPP.zip
info: http://myIPserver:8082/job/nightly-build-environments/lastSuccessfulBuild/artifact/build/myAPP.zip downloaded to /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/appium-app113520-69786-153jarz.zip
info: Unzipping /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/appium-app113520-69786-153jarz.zip
info: Testing zip archive: /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/appium-app113520-69786-153jarz.zip
info: Zip archive tested clean
info: Unzip successful
info: Using extracted app: /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/Payload/myApp.app
info: Creating new appium session 3d0b1b71-4bcc-4c42-bcc8-5dc373626998
info: Cleaned up instruments socket /tmp/instruments_sock
info: Not setting device type since we're connected to a device
debug: No device id or app, not installing to real device.
debug: Creating instruments
info: instruments is: /Applications/Xcode.app/Contents/Developer/usr/bin/instruments
info: [INSTSERVER] Instruments socket server started at /tmp/instruments_sock
info: Attempting to run app on real device with UDID xxxxxxxxxxxxxxx6749a675e0b853afe9
info: Spawning instruments with command: /Applications/Xcode.app/Contents/Developer/usr/bin/instruments -t /Users/USER/appium/app/uiauto/Automation.tracetemplate -w xxxxxxxxxxxxxxx6749a675e0b853afe9 /var/folders/jr/d3hgxz6d4rqdhwdls1bcmgh471mf1z/T/Payload/myApp.app -e UIASCRIPT /Users/USER/appium/app/uiauto/bootstrap.js -e UIARESULTSPATH /tmp/184856ca-fe0e-4a7d-a75e-b8ff832c9fa8
info: And extra without-delay env: {}
info: 
 2013-06-20 16:01:06 +0000 Default: Instruments shell user: USER
info: 
 2013-06-20 16:01:18 +0000 Default: Found node in Appium.app
debug: Sending command to instruments: au.bundleId()
info: [INSTSERVER] Instruments is ready to receive commands
info: Instruments launched. Starting poll loop for new commands.
info: Pushing command to appium work queue: "au.bundleId()"
info: [INSTSERVER] Socket data received (15 bytes)
info: [INSTSERVER] Socket data being routed for 'cmd' event
info: [INSTSERVER] Sending command to instruments: au.bundleId()
info: 
 2013-06-20 16:01:22 +0000 Default: Got new command 0 from instruments: au.bundleId()
info: 
 2013-06-20 16:01:22 +0000 Default: Result is not protocol compliant, wrapping
info: [INSTSERVER] Socket data received (70 bytes)
info: [INSTSERVER] Socket data being routed for 'cmd' event
info: [INSTSERVER] Got result from instruments: {"status":0,"value":"com.gamesys.jackpotjoy"}
info: Bundle ID for open app is my.bundleID
info: Setting initial orientation to PORTRAIT
info: Pushing command to appium work queue: "au.setScreenOrientation('PORTRAIT')"
info: [INSTSERVER] Sending command to instruments: au.setScreenOrientation('PORTRAIT')
debug: Sending command to instruments: au.setScreenOrientation('PORTRAIT')
info: 
 2013-06-20 16:01:23 +0000 Default: Got new command 1 from instruments: au.setScreenOrientation('PORTRAIT')
info: [INSTSERVER] Socket data received (56 bytes)
info: [INSTSERVER] Socket data being routed for 'cmd' event
info: [INSTSERVER] Got result from instruments: {"status":0,"value":"PORTRAIT"}
info: Appium session started with sessionId 3d0b1b71-4bcc-4c42-bcc8-5dc373626998
POST /wd/hub/session 303 23871ms - 9
debug: Appium request initiated at /wd/hub/session/3d0b1b71-4bcc-4c42-bcc8-5dc373626998
info: Responding to client with success: {"status":0,"value":{"version":"6.0","webStorageEnabled":false,"locationContextEnabled":false,"browserName":"iOS","platform":"MAC","javascriptEnabled":true,"databaseEnabled":false,"takesScreenshot":true},"sessionId":"3d0b1b71-4bcc-4c42-bcc8-5dc373626998"}
GET /wd/hub/session/3d0b1b71-4bcc-4c42-bcc8-5dc373626998 200 2ms - 319
debug: Appium request initiated at /wd/hub/session/3d0b1b71-4bcc-4c42-bcc8-5dc373626998/timeouts/implicit_wait
debug: Request received with params: {"ms":5000}
info: Set iOS implicit wait to 5000ms
info: Responding to client with success: {"status":0,"value":null,"sessionId":"3d0b1b71-4bcc-4c42-bcc8-5dc373626998"}
POST /wd/hub/session/3d0b1b71-4bcc-4c42-bcc8-5dc373626998/timeouts/implicit_wait 200 1ms - 89
debug: Appium request initiated at /wd/hub/session/3d0b1b71-4bcc-4c42-bcc8-5dc373626998
info: Shutting down appium session...
info: 
 2013-06-20 16:01:23 +0000 Debug: target.setDeviceOrientation("1")
       2013-06-20 16:01:21 +0000 Stopped: Script was stopped by the user
Instruments Trace Complete (Duration : 20.314917s; Output : /Users/USER/appium/instrumentscli0.trace)
 
info: [INSTSERVER] Instruments exited with code 0
info: Deleting plists for bundle: my.bundleID
info: [INSTSERVER] Socket closed forcibly due to exit
info: [INSTSERVER] Instruments socket server closed
info: No plist files found to remove
info: Deleted tracedir we heard about from instruments (/Users/USER/appium/instrumentscli0.trace)
info: Clearing out appium devices
info: Responding to client with success: {"status":0,"value":null,"sessionId":"3d0b1b71-4bcc-4c42-bcc8-5dc373626998"}
DELETE /wd/hub/session/3d0b1b71-4bcc-4c42-bcc8-5dc373626998 200 1375ms - 89