Mobile Software Test Automation: Running the project on iOS

Last week we finished getting everything set up for the iOS project, so now we are ready to run the project for iOS.  I recommend you use a physical device to run tests on, and you can find my reasons for that here.  In the past, there was the issue of paying to be set up as an apple developer if you wanted to run on a physical device, but with Apple's changes to how they charge for developers, you can get everything you need for free so long as you don't submit to the app store.  Also, those of you developing for a company will likely already be added to the developer profile for your app.  However, just in case, I'll show you how to run these tests on both a physical device and on a simulator.  

Running the project on a physical device

Device Setup

I know you are ready to jump in, but there are a few things we need to do, in order to make sure this will work.  First, plug in your device to the computer.  If this is the first time connecting this device to your computer, you will have to click that you trust the computer and all that jazz.  After that, make sure that your phone and computer are connected to the same wifi network.  On the device, go to Settings, Wi-Fi, click the blue information circle, and write down your IP Address.  Go back to the Settings menu, and scroll down to the Developer menu item.  Make sure that "Enable UI Automation" is turned on.  That's all we have to do on the device.  I'll recap in bullet points for those of you that skip to the action items:

  • Connect Device
  • Make sure that device and computer are on the same Wi-Fi
  • Get IP Address from device
  • Make sure that "Enable UI Automation" is turned on in the Settings > Developer menu item

Load app onto device

Now, you will want to launch Xcode and build the calabash scheme onto your device.  For those of you using the sample calculator app from last week, there shouldn't be any issues, so don't worry. But if this is for an app from your company, you will have to make sure that your device UDID is in the provisioning profile, which is managed on the apple developer portal in the member center.  Also, make sure your team is correctly set, and under the build settings menu, in the code signing section, make sure you are using the correct provisioning profile.  If you can build the app on a simulator, but can't get it on a device, it is almost certain you have a provisioning profile issue.  

Stick with it, but you may have to get a teammate involved to get everything set up in the member center.  As a side note, when I was first setting this up for my company, I had many of the issues I just mentioned.  Once they were fixed, it still didn't work, and I was perplexed.  Turns out, the bundle identifier/provisioning profile combo I was using wasn't set up to allow debugging (something most apps turn off for release profiles for good reason).  Since we couldn't change that, I ended up using a dev bundle id/provisioning profile for a beta version, so don't be afraid to get creative if you have to.  

Anyways, getting back to and run the app on your device. Make sure you have the appropriate -Calabash scheme selected, and pointed to the connected device, then hit the play button.

Once the app is on your phone, hit the stop button to kill the app.  

Get the UDID of the device

Since you already have Xcode up, go ahead and press Shift Command 2 on your computer. You can also navigate to the Window menu tab, and click the Devices menu item.  What you are looking for is the Device Identifier, or UDID.  So select your device from the side menu, and you should see the Identifier labeled near the top.  It should look like this:

Configure cucumber.yml file

You should already have this file in your project, since we created it when running the android project, but if not, you will need to create one either via Sublime text, or using the nano text editor in the terminal, which we learned how to do a while back.  Either way, we need to add the following lines to it:

ios: PLATFORM=ios APP_BUNDLE_PATH=calculator-ios-app/Calculator-Calabash-1.0 BUNDLE_ID=com.mglagola.Calculator-Calabash DEVICE_ENDPOINT= DEVICE_TARGET=your_device_UDID_here -r features/support -r features/ios/support -r features/ios/helpers -r features/step_definitions -r features/ios/pages

Note that there are no returns in this code. Everything should be on one line in your cucumber.yml file, but has been formatted above.  Also, you are welcome to specify the APP_BUNDLE_PATH, DEVICE_ENDPOINT, and DEVICE_TARGET environment variables on the command line at run time, but it's easier to do it here.  Also note that the APP_BUNDLE_PATH is the path to you .app file, relative to your project folder (where you run the project from in the terminal), and also make sure you include the port number 37265 after your IP Address.  I know I didn't explain this much when we ran the Android project, but the cucumber.yml file is basically a cucumber profile, which we are accessing using the -p command at runtime, followed by the environment, and is how the code knows which files to compile (since we have matching page support files for both platforms).

(Actually) running the project

Now is the time to watch all our hard work in action. Simply go to the terminal, cd into your project folder, and type the command:

$ bundle exec cucumber -p ios

You should be able to see the project run on your device, and you will also see the cucumber running in the terminal. The output should look like this:

If you have gotten this far, Great Job!  You now have automated an app for iOS and android, both running on actual devices.  This is no small feat, so go ahead and give yourself a pat on the back.

Running the project in the simulator

For those of you wanting to run the project on the simulator, the changes aren't all that different from what we had for a physical device.  First, launch Xcode and build the app to a simulator of your choice.  Then kill the app by pressing the stop button, just like we did when running on a physical device.  You can now close the simulator.  It is launched when we run the project.  But if it is left up, it will close it out before relaunching, so it doesn't really matter if you close it out or not.

Updating the cucumber.yml file (again)

Go ahead and make another profile named ios_sim.  You could also make changes to the ios profile, but this is easier in my opinion.  Remove the APP_BUNDLE_PATH and DEVICE_ENDPOINT variables all together. Also, change DEVICE_TARGET to match either your simulator name, or the UDID of the simulator.  In the end, it should look like this:

ios_sim: PLATFORM=ios BUNDLE_ID=com.mglagola.Calculator-Calabash DEVICE_TARGET='iPhone 6s (9.2)' -r features/support -r features/ios/support -r features/ios/helpers -r features/step_definitions -r features/ios/pages


Finally, you will need to put the .xcodeproj file in your project folder.  This is because the .app file was not built with the simulator architecture and thus, won't work on the sim.  Anyways, it's now time to run the project.  In the terminal, cd into the project directory and run:

$ bundle exec calabash -p ios_sim should see the simulator launch, and the tests running on the simulator and in the command line.  

Wrapping up and next steps

Great job today.  You really should feel proud of yourself for coming this far.  But we aren't slowing down.  Now that you have the basics under your belt, I will be going though some more advanced topics over the next few weeks.  Starting next week with some wait helper steps, then more advanced queries, performing swipes and other more advanced touch methods, updating calabash gems and dependencies, using tags, integrating automation into an existing build server/CI process, and so much more, so stay tuned!

Mobile Software Test Automation: Creating iOS page support

Now it's time to start coding page support for the iOS project.  Do you remember when we did this for Android?  There are a few more setup steps before we can get to the irb console, so lets get started.

Moving the app to the project folder

Since we built and ran the iOS app last week, an application file was created for that build. This is essentially the packaged app that will be loaded onto the device.  This can be found in a couple locations.  The easiest way to find this is to open in finder from Xcode. In the leftmost navigator pane, select the project navigator icon and then select the calabash product from the projects dropdown.  Then in the utilities pane on the right side, you will see the full path, with an arrow icon.  Click this to open finder to this location.  Or, you could open finder to this location from the terminal using open followed by the filepath, or simply navigate to this folder manually through finder.  

Now that you have this app file, copy it and paste it inside your project folder.  I like to put this in a separate folder so it is organized.  Once done, your project folder should look something like the image below.  I added the build number 1.0 to the end of the app name to differentiate it from different builds.  Although not important for this sample, it is for the apps you will be automating.

Starting up the irb console

This is a little more cumbersome than starting up the Android console, mainly because we need to set some environment variables to run.  Some of these are not required when running in the simulator, but they are when we get to running on a physical device, which is why I am trying to get you in the habit of including them.  So for starters, here are the variables we need:

DEVICE_TARGET='iPhone 6s (9.2)'

The APP_BUNDLE_PATH variable is the location of the .app file with relation to your project folder.  You could have skipped the step of moving the app to your project folder and specified the long path that is auto-generated, but that can get confusing when you start getting a lot of builds, which is why we did it this way.  The BUNDLE_ID variable is the bundle identifier of your app, and is found in the editor portion of Xcode, at the top of the general tab.  We only have one, so this may not be needed, but when you have a couple different apps on the phone for different environments, this is a must.  The DEVICE_TARGET variable is the name of the simulator, or the UDID of the physical device.  Yours may look a little different from mine, depending on the device/simulator version you are running on.  Also, there is the DEVICE_ENDPOINT variable, which is the ip address of the physical device.  It is not needed for a simulator, but is for a physical device, and follows the format shown above.  You can find your ip address on your physical device by going to settings, WIFI, and selecting the more information icon next to the network you are connected to.

So to start the console, first launch the terminal, cd into your project folder, and then type the following, changing the variables as needed for your situation.

$ APP_BUNDLE_PATH=calculator-ios-app/ BUNDLE_ID=com.mglagola.Calculator-Calabash DEVICE_TARGET='iPhone 6s (9.2)' bundle exec calabash-ios console

Press enter and you should see something like this:

Now, type in the familiar (hopefully) command: 


After pressing enter, your terminal should look like the following, and the simulator should open, and the app launched:

Page Support for iOS

Since we already went through the console locator techniques for Android, I won't revisit those again, since they are exactly the same.  The easiest way to make sure we don't miss any methods is to create a new file under the iOS pages folder with the same name we used for Android (landingPage.rb) and copy the page file we created for Android, and paste this into the newly created iOS page.  You will need to change the first two lines to match the following:

require 'calabash-cucumber/ibase'
class LandingPage < Calabash::IBase

Now find the needed elements, which for our test are only the trait and button definitions.  When you are done, the iOS page file named landingPage.rb should look like this:

You will notice that most of this page is the same as its Android counterpart.  Since there are some minor differences between these apps, I also had to make some changes to the calabash_steps.rb file.  In short, those changes are determining which platform is being run, and will either execute code (Android, for the ad popup), or do nothing (iOS, since no ad popup is present).  We will go more into these types of things later on, but for now, you can see it in action below, with the changes boxed in red:

Now we are done coding page support for the iOS app!  Good job getting this far!  Next week we will walk through running the test on a simulator, as well as on a physical device. See you next week.