rubycalabashpageobjectscalabash-ioscalabash-android

Non helpfull error message Calabash with page objects pattern


I'm currently using Calabash framework to automate functional testing for a native Android and IOS application. During my time studying it, I stumbled upon this example project from Xamarin that uses page objects design pattern which I find to be much better to organize the code in a Selenium fashion.

I have made a few adjustments to the original project, adding a file called page_utils.rb in the support directory of the calabash project structure. This file has this method:

def change_page(next_page)
  sleep 2

  puts "current page is #{current_page_name} changing to #{next_page}"

  @current_page = page(next_page).await(PAGE_TRANSITION_PARAMETERS)

  sleep 1

  capture_screenshot

  @current_page.assert_info_present
end

So in my custom steps implementation, when I want to change the page, I trigger the event that changes the page in the UI and update the reference for Calabash calling this method, in example:

@current_page.click_to_home_page
change_page(HomePage)

PAGE_TRANSITION_PARAMETERS is a hash with parameters such as timeout:

PAGE_TRANSITION_PARAMETERS = {
  timeout: 10,
  screenshot_on_error: true
}

Just so happens to be that whenever I have a timeout waiting for any element in any screen during a test run, I get a generic error message such as:

Timeout waiting for elements: * id:'btn_ok' (Calabash::Android::WaitHelpers::WaitError)
./features/support/utils/page_utils.rb:14:in `change_page'
./features/step_definitions/login_steps.rb:49:in `/^I enter my valid credentials$/'
features/04_support_and_settings.feature:9:in `And I enter my valid credentials'

btn_ok is the id defined for the trait of the first screen in my application, I don't understand why this keeps popping up even in steps ahead of that screen, masking the real problem. Can anyone help getting rid of this annoyance? Makes really hard debugging test failures, specially on the test cloud.


Solution

  • welcome to Calabash!

    As you might be aware, you'll get a Timeout waiting for elements: exception when you attempt to query/wait for an element which can't be found on the screen. When you call page.await(opts), it is actually calling wait_for_elements_exist([trait], opts), which means in your case that after 10 seconds of waiting, the view with id btn_ok can't be found on the screen.

    What is assert_info_present ? Does it call wait_for_element_exists or something similar? More importantly, what method is actually being called in page_utils.rb:14 ?

    And does your app actually return to the home screen when you invoke click_to_home_page ?

    Unfortunately it's difficult to diagnose the issue without some more info, but I'll throw out a few suggestions:

    My first guess without seeing your application or your step definitions is that @current_page.click_to_home_page is taking longer than 10 seconds to actually bring the home page back. If that's the case, simply try increasing the timeout (or remove it altogether, since the default is 30 seconds. See source).

    My second guess is that the element with id btn_ok is not actually visible on screen when your app returns to the home screen. If that's the case, you could try changing the trait definition from * id:'btn_ok' to all * id:'btn_ok' (the all operator will include views that aren't actually visible on screen). Again, I have no idea what your app looks like so it's hard to say.

    My third guess is it's something related to assert_info_present, but it's hard to say without seeing the step defs.

    On an unrelated note, I apologize if our sample code is a bit outdated, but at the time of writing we generally don't encourage the use of @current_page to keep track of a page. Calabash was written in a more or less stateless manner and we generally encourage step definitions to avoid using state wherever possible.

    Hope this helps! Best of luck.