开发者

Cucumber test redirect

Have found some advice: http://openmonkey.com/articles/2009/03/cucumber-steps-for-testing-page-urls-and-redirects

I have added the above methods to my web steps definitons, have written my feature, ran it and got an error about nil objects. After some investigation, I have noticed, I ha开发者_JAVA百科ve no response and request objects, they are nil

From web_steps.rb:

Then /^I should be on the (.+?) page$/ do |page_name|
  request.request_uri.should == send("#{page_name.downcase.gsub(' ','_')}_path")
  response.should be_success
end

Then /^I should be redirected to the (.+?) page$/ do |page_name|
  request.headers['HTTP_REFERER'].should_not be_nil
  request.headers['HTTP_REFERER'].should_not == request.request_uri
  Then "I should be on the #{page_name} page"
end

The request and response objects are nil, why ?


Are you using WebRat or Capybara as your driver within Cucumber? You can tell by looking at features/support/env.rb. I'm using Capybara, so mine includes these lines:

  require 'capybara/rails'
  require 'capybara/cucumber'
  require 'capybara/session'

The default used to be WebRat but switched recently to Capybara, so a lot of the code from older examples on the web doesn't work properly. Assuming you're using Capybara too...

request.request_uri - You want current_url instead. It returns the full URL of the page your driver is on. This is less useful than getting just the path, so I use this helper:

def current_path
  URI.parse(current_url).path
end

response.should be_success - One of the biggest frustrations with working with Capybara (and to a certain extent, Cucumber) is that it is downright zealous about only interacting with what the user can see. You can't test for response codes using Capybara. Instead, you should test user-visible responses. Redirects are easy to test; just assert what page you should be on. 403s are a little tricker. In my application, that's a page where the title is "Access Denied," so I just test for that:

within('head title') { page.should_not have_content('Access Denied') }

Here's how I'd write a scenario to test a link that is supposed to redirect sometimes and not supposed to redirect at other times:

Scenario: It redirects
  Given it should redirect
  When  I click "sometimes redirecting link"
  Then  I should be on the "redirected_to" page

Scenario: It does not redirect
  Given it shouldn't redirect
  When  I click "sometimes redirecting link"
  Then  <assert about what should have happened>


You can test the response code like this:

Then /^I should get a response with status (\d+)$/ do |status|
  page.driver.status_code.should == status.to_i
end


It does sometime make sense to use cucumber for this kinda thing, but its best avoided.

Can you not use a controller spec?


I see this is an old question, but I want to add my answer, may be someone find it helpful. Cucumber is an end-to-end acceptance (or integration as many call it) test framework, it means that when using it, you should not care about the intermediate states, but the beginning of a request (i.e. from where the request is initiated: click on a button or link, navigation from the address bar and so on), and the final result (i.e. what the user will see on the page when the load completed).

What you need here is a Controller spec, that is better to be specified by Rspec, which will give you better access to intermediates states in the action level. An example can be:

describe AController do
  #specify the action where you expect a redirect
  describe 'GET action' do # or POST action
    get :action # or post with post params if the request expected to be a form submition
    expect(response).to be_redirect 
  end
end


Generally it is not recommended to test current url, response codes and headers in cucumber. I would advice you to write more low level test for this purpose: functional controller test or request specs

To answer your question:

Then /^I should be on the (.+?) page$/ do |page_name|
  expect(current_url).to eq send("#{page_name.downcase.gsub(' ','_')}_path")
end

Then /^I should be redirected to the (.+?) page$/ do |page_name|
  expect(current_url).to eq send("#{page_name.downcase.gsub(' ','_')}_path")
end

Capybara performs redirects automatically


I just had to test the same thing and came up with the following for Cabybara 1.1.2

Then /^I should be on the (.*) page$/ do |page_name|
  object = instance_variable_get("@#{page_name}")
  page.current_path.should == send("#{page_name.downcase.gsub(' ','_')}_path", object)
  page.status_code.should == 200
end

Then /^I should be redirected to the (.*) page$/ do |page_name|
  page.driver.request.env['HTTP_REFERER'].should_not be_nil
  page.driver.request.env['HTTP_REFERER'].should_not == page.current_url
  step %Q(I should be on the #{page_name} page)
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜