Mobile Software Test Automation: Updating Calabash gems and dependencies

Over the past few months we have gone from creating a project, to implementation in an iOS and android project, to some useful advanced methods.  By now, there is likely an updated Calabash gem with new features and bug fixes that we will want to take advantage of.  So let's get started.

Updating Calabash-Android gem

If you took my advice in the early stages of the project and decided to manage dependencies with bundler, this is where it will pay off.  Updating the calabash-android gem and dependencies is extremely simple.  First, we will need to find the calabash-android repo on GitHub and look for the latest stable version.  It may also be a good idea to view the change-log for this project so you know what to expect.  There have been changes in the past that required a good size refactor for depreciated methods and such, so don't blindly update and hope it always works out.  Now that we know what version we are updating to, open up the Gemfile document in your project folder.  For the 'calabash-android' gem, update the version number to the version you desire, and hit save.  Once this is done, open up your terminal, navigate to your project folder, and run:

$ bundle update

The output should look something like this:


That's all there is to it!  It may be a good idea to run a smoke test to make sure that the update didn't have some unintended consequences before relying on it in a CI environment.  Now we can safely assume that for minor version updates, there likely won't be any breaking changes, so if you want to avoid this hassle for updating minor versions, update your gemfile like this:

gem 'calabash-android', '~> 0.5.14'

This is essentially saying, update all the minor versions (the 3rd number), but not the major versions.  Basically, greater than or equal to 0.5.14 and less than 0.6.0.

Updating Calabash-ios gem

If you remember, setting up the iOS project was a little bit more involved, and as such, there are a few more steps required to update the gem as well.

update the gemfile

The first step is to update the gemfile with appropriate version as we did for android.  Then, in the terminal, inside your project folder, run:

$ bundle update

download the calabash framework

Next, in the terminal, navigate to the directory where your existing calabash.framework is located.  Depending on how you set everything up, it will likely be inside your iOS project's folder.  First, go ahead and check the current calabash version and make note of the result.  In the iOS project directory, run:

$ calabash-ios version

Then, you will want to download the framework with the following command:

$ calabash-ios download

You will see a message asking if you want to delete the current framework and replace with the latest matching version.  Type "y" to proceed.  It will look something like this:


Now, go ahead and check the calabash-ios version again.  It should be the version you specified in the gemfile. 

clean the project and remove old builds

Next, open up your iOS project in Xcode and do a deep clean of the project.  This can be accomplished by going to the "Product" dropdown, hold the option (alt) key and select "Clean Build Folder", or you could use the shortcut keys "shift + option + command + k". 

You will also want to remove the old app builds from physical devices and simulators.  You will have to remove the app builds from physical devices manually, or with some third party tools that we will discuss when we get into the CI discussion.  Resetting the simulators is easy, by running:

$ calabash-ios sim reset

rebuild the project and verify server version

Now it's time to rebuild the project.  To make it easier to verify that the latest version of calabash server is embedded into your app, go ahead and rebuild to a simulator.  With the app running in the simulator, type the following in the terminal:

$ curl http://localhost:37265/version

You will get a JSON response that includes the version number.  Check this against the version that you downloaded to make sure that it is properly embedded.  Alternatively, with the newer versions of calabash-ios, you could also view the console target output in Xcode when you built the app to see the calabsh version.  

Wrapping up

You're all set!  Hopefully this was a fairly painless exercise in updating the calabash gems.  Next week we will work through structuring our project with tags, which leads up to a multi-part series on setting up a Jenkins CI server and integrating our test suite into it.

Mobile Software Test Automation: Interacting with objects for iOS

Last week we went through a few different touch methods for android.  You will remember one important concept is that any element you can find via query, you can interact with via the gesture methods we will discuss today.  Now we will jump into the same for iOS as the methods differ slightly.  There will be a little bit of crossover, mostly in the predefined steps.  So let's get started.

Touch Methods

You all should remember the basic touch method from when we developed page support for the sample calculator iOS app:

touch("UIButton text:'9'")

That will get you through a basic app, like a calculator, but we know that there are a lot more ways users interact with smartphones these days.

Double Tap

Using the double tap gesture will look the same as android. Here it is:

double_tap("UIButton marked:'Save'")

Long Press

Here is where we start to deviate a bit.  Although this had been a gesture android had been using for a while, it was recently added to iOS, hence a little bit different name: touch and hold. Here is an example:

touch_hold(uiquery, options = {})

Here, the uiquery is the same query string we use to locate any object on the screen.  You will notice that there is also an options hash.  This is actually available on most touch methods, but they mainly only accept an :x and :y key that offsets the touch based off those values.  The options hash for touch and hold also accepts a duration parameter.  The default duration is 3 seconds, so if you need more than that, you will need to use this option.  Here is an example from the Calabash iOS API:

touch_hold("webView css:'input'", duration:10, offset:{x: -40})

Two Finger Tap

Here is a touch method that we have for android, but it's use is not as widespread. Here is the implementation:

two_finger_tap("UILabel {text CONTAINS[c] 'sample text'}")

Tap Mark

Here is one useful touch method that I didn't mention for android, but they are used the same way.  Basically, in any instance where you use the query string "* marked:'something'", you can use this as a quicker way of defining it:

This is equivalent to touch("* marked:'#{label}'")

Wait Tap

This method actually removes a huge chunk of code, and wraps it all into one.  In the past, you may have had to wait for an element to appear, then wait for animation to complete, and then touch the object.  Now, all you have to do is wait tap:

wait_tap(uiquery, options = {})

The options hash here, allows for the usual offset, but also timeout, which is the number of seconds it waits for an element to appear (default 3), and frequency, which is the polling frequency for checking if the view is present (default 0.2).

Touch by Coordinates

At first, I wasn't sure I wanted to even mention this, because it should only be used out of absolute desperation.  But I will confess, on a previous project, I had to use this because we were using a legacy tab controller which wrapped the whole tab bar in an object, and calculated the touch coordinates to determine where you actually pressed.  Terrible, i know, but it's how it used to be done long ago.  It was very fragile, and tests failed if I used a phone with a bigger screen.  Anyways, you have been warned...

tap_point(x, y)

That wraps up the touch methods I feel are useful.  I did skip over a few, so if you are interested, you can see them all in the Calabash iOS API


Just like last week, remember that you can only interact with an element that's in view.  For the most part, the center of the object has to be in view for you to interact with it.  So here's how we can expose those elements:

Basic Swiping

Here are the predefined swipe steps that you can use by simply adding them to your .feature file. 

When I swipe up
Then I swipe down
And I swipe right
Then I swipe left

These will work great so long as the scroll view you are wanting to swipe is the first one on the screen.  Otherwise, we will need to make a custom step.

Advanced Swiping

An example of when this would be useful is when performing the swipe to delete gesture, which is common on most iOS messaging apps.  

In my opinion, the best option for swiping on a scroll view is to use the swipe method.  It will accept in the options hash, an offset, uiquery, and force, which gives you just about everything you will need.  The only disadvantage is that this isn't reliable for some scroll views on simulators below 9.0. But it works great on physical devices and simulators >= 9.0.  Here is an example:

swipe(dir, options = {})
swipe(:left, offset:{x:10,y:50}, query:"UITableViewCell", force:strong)

In this method, the first parameter is the direction, and can accept left, right, up, or down.  It can be passed an options hash that includes an x,y offset, uiquery, and force.  You know all about the offset and uiquery already.  The force option allows for strong, normal, and light, with the default being normal.  The force is not perpendicular pressure on the screen, but length of the swipe.

Another option would be to use the scroll method, and scrolls half the frame size:

scroll(uiquery, direction)
scroll("UITableView", :down)

One important thing to note about scroll is, it is implemented under the hood differently from the swipe method.  This is important because this method can actually do things that a real user cannot, so I would use this with caution. 

Wrapping up

This finishes our section on advanced gestures.  We have come a long way, but there is still so much more to cover!  Next week we will go over how to update calabash gems and dependencies, as well as updating that gem in the iOS project.  We will them move onto using tags, and then integration into a CI process.  See you next week!