2

I am in the process of switching from capybara-webkit to poltergeist/phantomjs. I'm experiencing a timing problem and I've determined which line of code needs warmup time, but I can't determine why this is or how to solve it.

I have a 225 line spec file with a couple dozen tests. On any given test run, 1 or 2 of them will consistently fail. It can be any of them, it's not consistent.

This before block applies to all the tests. I've annotated the code to explain the situation.

before do
  # --> Create several objects using factory girl
  # --> stub some methods 

  visit root_path
  # sleep 0.5 here always fixes the problem. sleeping before this line does not.

  find("a#sign-in-link").click
  within "form#new_session" do
    fill_in 'user[email]', with: user.email
    fill_in 'user[password]', with: user.password
  end
  click_button "Sign in"

  # On the specs which fail, this is the line which fails.
  # Capybara::ElementNotFound: Unable to find link "People"
  click_link "People"
end

click_button "Sign in" results in a page load. So one might imagine that the problem has something to do with this page not having time to load. save_screenshot or save_and_open_page directly after signing in shows that the authentication was in fact not successful (which agrees with the failure message).

This would suggest that the problem is because in some cases the test data doesn't have time to load. However, why would the sleep have to come after visit root_path? Even if it were the case that some aspect of my test data needed to be "warmed up" by visiting a page (which is not the case as far as I can imagine), there is nothing in my root path that would load this data. It would be more likely to happen when submitting the sign in form.

What might be causing this?

More info

Using this code I tried putting wait_for_ajax_completion after visit root_path, still got a failure.

Then on a whim, I tried putting it before click_button "Sign in" -- this consistently increases the number of failures (but not to a consistent number, it still varies with each run).

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
John Bachir
  • 22,495
  • 29
  • 154
  • 227
  • 1
    Is it the same problem as in this question? http://stackoverflow.com/questions/23554882/why-does-adding-sleep-1-in-an-after-hook-cause-this-rspec-capybara-test-to-pas/23555725 – Dave Schweisguth Jun 02 '14 at 22:48
  • Good thinking, but it seems like it is not. Using [this code](https://gist.github.com/jjb/b04a7385cc058a18d1a3) I tried putting `wait_for_ajax_completion` after `visit root_path`, still got a failure. (btw, the asker of that question is my coworker :-D) – John Bachir Jun 03 '14 at 00:55
  • @DaveSchweisguth see "More info" in my question for some more tantalizing observations – John Bachir Jun 03 '14 at 01:24
  • Such a treat, these multithreaded tests. Have you established whether the problem occurs if you only have one example in the spec file? If it did you'd have something smaller to work on. If not, you'd know it's interference between tests. Either way, I'd be adding logging and studying logs when a test succeeds or fails. – Dave Schweisguth Jun 03 '14 at 17:24
  • I've never been able to get it to fail with a single example, I've been working under the assumption that this is because of a mere probability factor, not because of tests interacting with one another. I'll ponder how they might interact with one another and try to put in more logging. – John Bachir Jun 03 '14 at 17:42
  • Also, look for HTTP 500 responses, and maybe other error statuses, in your Rails test log that shouldn't be there. I've seen 500 responses to AJAX break @javascript scenarios even if the scenarios weren't testing the result of that AJAX. – Dave Schweisguth Jun 08 '14 at 17:31
  • 1
    yeah... intermittent failures - doncha love em? I've found a lot of these for capybara/phantomjs. Firstly: the issue is that there's a race condition on whether the page has loaded or not before clicking one of the links. I have yet to figure out why it sometimes waits and sometimes doesn't (even after reading the docs). I've found that you can improve your chances of it waiting properly if you do an `expect(page).to have_content()` where whatever is the thing you're about to click on. `sleep` just increases the runway of the race condition. – Taryn East Aug 11 '14 at 04:45

0 Answers0