0

My environment: Xcode: 7.2.1 Simulator: iOS iPad Air 9.1 Calabash: 0.17.1

Currently, I'm having an issue with my iOS application not touching buttons correctly after I background my application. Here are the general cucumber steps where the issue happens:

When I send the app to the background for 2 seconds
And I skip logging in to MyApp
And I wait and wait
And I should see "Speed"
And I wait for 10 seconds
And I touch "Speed"

Here is the code for the sending the app to background step:

Given /^I send the app to the background for ([\d\.]+) second(?:s)?$/ do |num_seconds|
  num_seconds = num_seconds.to_f
  send_app_to_background(num_seconds)
end

Basically the touching hits a snag only after I send the app to background. If I take that step out, Calabash touches the button like expected. I included the step where it sees "Speed", just to make sure that Calabash can actually see the button, which it could, since it goes green for that step, as well as the waiting step. But on touching "Speed", Calabash goes into a state where it keeps trying to touch it, but since it doesn't, it hangs on that step indefinitely. I suspect this may be either be a Calabash or UIAutomation bug (https://github.com/calabash/calabash-ios/issues/836), since everything works as expected until or unless I send my app to background, but I wanted to be 100% sure, in case I'm doing something wrong that I'm not seeing.

Does anyone have any ideas as to what the issue may be?

Update:

According to https://groups.google.com/forum/#!topic/calabash-ios/NZAmTp6ckrk, sending app to background is still unimplemented, and when I check the code for send_app_to_background, it does look like it:

def send_app_to_background(secs)
  raise 'Not implemented when running without instruments / UIA'
end

Does anyone have a way to work around this for their tests? Running this on a physical device is not an option for me, it has to be done with a simulator.

Update:

Following https://github.com/calabash/calabash-ios/issues/556, I changed sending the app to background code to follow a workaround:

Given /^I send the app to the background for ([\d\.]+) second(?:s)?$/ do |num_seconds|
  num_seconds = num_seconds.to_f
  uia_send_app_to_background(num_seconds)
end

And the implementation of uia_send_app_to_background is:

def uia_send_app_to_background(secs)
  #uia_handle_command(:deactivate, secs)
  #Temporary workaround: https://github.com/calabash/calabash-ios/issues/556
  js_deactivate = %Q[var x = target.deactivateAppForDuration(#{secs}); var MAX_RETRY=5, retry_count = 0; while (!x && retry_count < MAX_RETRY) { x = target.deactivateAppForDuration(#{secs}); retry_count += 1}; x]
  uia(js_deactivate)
end

However, for me, this workaround doesn't seem to work. The app gets pushed to the background, but never goes back to foreground. When I stop that step in irb after a few minutes of waiting, I get this error:

When I send the app to the background for 2 seconds        # features/step_definitions/common.rb:91
  Could not parse response ''; the app has probably crashed (RuntimeError)
  ./features/step_definitions/common.rb:93:in `/^I send the app to the background for ([\d\.]+) second(?:s)?$/'
  features/display_mapping_units_from_2630.feature:216:in `When I send the app to the background for 2 seconds'

Update

I tried these workaround steps, but touching after backgrounding still doesn't work, and I also tried this on 8.4 simulator, where it doesn't work either, which makes me suspect even more it's an Xcode 7+ issue that needs to be resolved:

When(/^I background the app$/) do
  open_app_via_simctl("com.apple.mobilesafari")
  sleep(2)
end

When(/^I launch the app$/) do
  open_app_via_simctl("com.me.MyApp-cal")
  sleep(2)
end

Steps:

And I background the app
And I wait
And I launch the app
And I wait
And I should see "Button1"
And I wait for 10 seconds
And I touch "Button1"

Calabash succeeds in seeing Button1, but when it tries to touch Button1, in 9.1 simulator, Calabash hangs indefinitely, trying to find the button, and in 8.4 simulator, I get an error right away that Calabash can't find the view "Button1".

irradio
  • 53
  • 7
  • How many seconds pass before "I should see "Speed"" is triggered? – Lasse Feb 15 '16 at 07:06
  • 4 seconds.. but I tried a 10 second wait too, and it doesn't help. – irradio Feb 15 '16 at 13:23
  • 1
    Maybe have a look at this thread: https://github.com/calabash/calabash-ios/issues/836 – Christopher Fuentes Feb 15 '16 at 22:15
  • Would you mind posting your Gemfile contents? – Christopher Fuentes Feb 15 '16 at 22:21
  • @ChristopherFuentes I saw that 836 issue, actually mentioned it in this thread.. it's one of the main reasons I think that functionality is just broken.. I was hoping that my later workarounds might work around those issues, but so far no luck. – irradio Feb 16 '16 at 03:48
  • @ChristopherFuentes sure: gem "cocoapods", "0.38.2" gem "run_loop", "2.0.3" gem "rspec", "2.14" gem "app-cucumber", :git => 'git@githubext.mycompany.com:companyApps/app.git', :tag => '0.45.1' gem "xcpretty" gem "calabash-cucumber" – irradio Feb 16 '16 at 03:50

1 Answers1

2

Issue #836 was closed fixed in November. The Google forum post from 2013 and issue #556 is from 2014. Anything later than a couple months ago should be treated with suspicion.

Don't call the uia_send_app_to_background, that API is broken (by Apple). In general stick with the non-UIA API (don't call uia_* methods unless absolutely necessary).

Update Calabash to latest released version (0.18.1 as of today) and try your tests again.

$ be calabash-ios console
> start_test_server_in_background

# Can touch before background
> touch("view marked:'my view'")

> send_app_to_background(1)

# Can touch after resuming from background
> touch("view marked:'my view'")

The solutions below will not work. Your app will go to the background if you open another app. However, if you open your app with simctl, instruments will no longer have a connection to the application and gestures will fail.

When(/^I background the app$/) do
  open_app_via_simctl("com.apple.mobilesafari")
  sleep(2)
end

When(/^I launch the app$/) do
  open_app_via_simctl("com.me.MyApp-cal")
  sleep(2)
end
jmoody
  • 2,480
  • 1
  • 16
  • 22
  • Ahh, okay.. that's kind of what I was expecting. Essentially then, backgrounding is just not fully functional, as you have to reinstall the app after you put it in background, since in most cases you'd want to perform gestures after backgrounding your app, not just verifying that elements exist. Thanks for your help, jmoody! – irradio Feb 23 '16 at 15:49
  • No. That is not correct. Backgrounding is implemented. – jmoody Feb 24 '16 at 15:47
  • Oh, well right, backgrounding is implemented.. but if you call relaunch or start_test_server_in_background (which I need to do since I need gestures to work), isn't that the same thing as just reinstalling and opening the app? So the behavior is different from a real device's when you're backgrounding and foregrounding the app – irradio Feb 24 '16 at 18:39
  • We are not communicating well. Can you try to reproduce in this repo: https://github.com/calabash/ios-smoke-test-app/tree/master/CalSmokeApp Background should work and gestures should work after returning from background. I don't understand your set up. – jmoody Feb 25 '16 at 09:50
  • I just ran a test to see if we can perform gestures after resuming from background. We can. – jmoody Feb 29 '16 at 17:40
  • Added a Cucumber test to demonstrate that this working. https://github.com/calabash/calabash-ios-server/commit/b9dd15f1b892392057bb462b61d2bbd0ec11d35c – jmoody Feb 29 '16 at 18:12
  • reread what you edited and your new comments, I will try both the smoke test, and my tests again.. I upgraded to 0.18.1 this past weekend, so possibly that fixed something.. – irradio Feb 29 '16 at 20:16
  • reran my tests, i sort of divided them up to try to find a root cause, and backgrounding and gestures successfully work now. the issue is that if i relaunch the app in the same scenario before i background, then gestures don't work.. when i took out relaunching the app before i background and then touch some stuff, then all works as expected.. is this a calabash defect that may need to be resolved? – irradio Mar 07 '16 at 22:14
  • How are you relaunching? If you are relaunching with simctl, gestures will never work. You must allow Calabash to tell the instruments program to launch your app. This creates the connection to UIAutomation which is how gestures are performed. I don't believe that this is a defect in Calabash. Can you mark my answer as correct? – jmoody Mar 08 '16 at 10:07
  • Here's my relaunch def: When(/^I relaunch the app$/) do calabash_exit options = { :uia_strategy => :shared_element } @calabash_launcher.relaunch(options) end – irradio Mar 08 '16 at 15:22
  • Where do I put in 'instruments' or 'xcrun instruments' or whatnot? Does that go somewhere in my definition? I've marked your answer as correct. – irradio Mar 08 '16 at 15:41
  • That is the correct way to relaunch, but I don't understand the use case. When you relaunch, Calabash loses its connection to http server in your app which will cause an HTTP timeout I think. I don't think we can support relaunching the app in the middle of a Scenario. We can (and do) support sending the app to the background. This discussion is getting long. I think you should open a new question and describe exactly what you are trying to do. We have demonstrated that backgrounding works and that you can perform gestures after return from the background state. – jmoody Mar 08 '16 at 18:43