cucumber step_definitions Q on style/approach on I should see - ruby-on-rails-3

I'd like to get opinions from others with more experience on writing Cucumber step definitions.
My initial intention was to verify that a particular link was present in one scenario and
verify that it wasn't present in another scenario.
So I have the following two steps. In my naivety I thought I could use the '!find_link(...)'.
In the end I decided to use exceptions.
I'd like to solicit feedback on two aspects:
1. the approach I've taken on using the exceptions within the step_definition
2. is it meaningful to expect to explicitly look for links in the rendered page?
As I finished up work last night I couldn't help thinking "why didn't I simply use:
I should not see 'Sign up'?" and this morning it dawned on me that 'Sign up' could be included in a paragraph on the page somewhere.
Here are the steps, thanks in advance...
Then /^I should see link: ?"([^"]*)"$/ do |link|
find_link("#{link}")
end
Then /^I should not see link: ?"([^"]*)"$/ do |link|
# !find_link("#{link}") - commented out because it won't fail if link is present
begin
find_link("#{link}")
raise FindException
rescue Capybara::ElementNotFound
end
end

'Then' step definitions definition should always contain an assertion, e.g. should if using RSpec or assert if using Test::Unit.
So if want you want to verify a specific URL isn't present, it would be better to do:
should_not have_link(link)
However, it would probably be better to re-write the step as:
Then I should not see a sign-up option
And in the step definition, rather than checking for a URL, you could check for a link with a particular class:
should_not have_css('a.signup')

Related

Using a rails model in Capybara tests

I set up a project where all I have to do is display a set of records from an SQLlite3 database. I have a table in that database, and I want the root page to display all the records in the database. I have this working, but now I want to set up a Capybara test to make sure that the page has the first and last record from the table on the page.
require 'rails_helper'
describe "seeing record from scotlands model " do
specify "I can see a list of all charities" do
visit "/"
expect(page).to have_content "#table.first_record"
end
end
However, the above provides no link to the model so I cannot access it. How do I get a link to the table from the test file?
Do you generally try to access real data from tests? I've always learned to keep those things separate.
I like to work with Rspec and Capybara. Here is something simple and straight forward that should accomplish what you've discussed:
require 'rails_helper'
feature "user sees all scotlands records" do
scenario "successfully" do
charity1 = Charity.create(name: name1, info: info1)
charity2 = Charity.create(name: name2, info: info2)
charity3 = Charity.create(name: name3, info: info3)
visit root_path
expect(page).to have_content(charity1.name)
expect(page).to have_content(charity1.info)
expect(page).to have_content(charity2.name)
expect(page).to have_content(charity2.info)
expect(page).to have_content(charity3.name)
expect(page).to have_content(charity3.info)
end
end
I actually usually work with FactoryGirl also. In this case it'd make things easier because you could use create_list and make as many records as you'd like with just one line of code.

Can we list all the scenarios which fall under a Cucumber tag

I have three-four Cucumber tags (say #smoke, #testing, #test) which are randomly put on scenarios and feature files. Now, I need to list all the scenarios which fall only under smoke. Can someone please suggest a way to do this
You can use the dryRun=true option in CucumberOptions with tag filters in your runner to get the list of scenarios in the report. This option will not execute your features but will list them out plus check if the steps have the appropriate glue code.
#CucumberOptions(plugin={"pretty", "html:report"}, tags={"#smoke"},
snippets=SnippetType.CAMELCASE,
glue="....", features="src/test/resources/features", dryRun=true)
Make sure you add the correct path of your glue code. Also the features should point to the top directory containing the feature files.
The above should list out the any scenario containing the #smoke tag in the html report.
But if you are looking for scenario list with only #smoke tag and not the others use this filter (tags="#smoke","~#testing","~#test").
Point of caution, if you have Scenario Outlines they will be repeated by the number of scenarios in the examples table.
You can write your own filter to print what you would run but run nothing.
require 'cucumber/core/filter'
# put inside features/support/
class PrintOnlyCukeFilter < Cucumber::Core::Filter.new
def test_case(test_case)
puts test_case.location.to_s
end
end
AfterConfiguration do |config|
config.filters << PrintOnlyCukeFilter.new
end
Put the file in features/support.
To print only file names you can see this gist.

Rails 5 after removal of assigns function for controller tests

I used assert_template and assigns extensively before Rails 5 in my controllers tests. For example to test that a link in the view is correct:
assert_select ".left-off-canvas-menu ul li a[href=?]", event_all_items_path(assigns(:event)), "Back to all items"
I figured that assert_template was not difficult to get rid of.
However, I don't know how to replace test cases like the one above.
I know about the gem to include those functions, but I'd like to try without them. So alternatives would be:
Would you make a case to keep the assigns function or would you say it is meant to be hard coded?

How do we test a Rails Model which does not have an equivalent table in the backend using RSpec

I have a Moderator model which basically queries web site related stat results from other models.
An e.g. of displayed stats could be the total number of users belonging to a particular area out of many areas in a city. Limiting the number of such records to a fixed number. For this, the body defined within the Moderator model makes use of an Area model.
Since the queries are not using anything from the same model, but actually from other models, there wasn't a need for me to have a table migration wrt this model.
I basically am now trying to test the defined methods in the Moderator model using Rspec.
What I am basically trying to test is that a call to the method should return success, this I am doing through:-
subject.send(:method_name)
response.should be_success
I'm getting a common error for all such defined methods saying that database_name.table_name does not exist. Well , this is true but how should is it really making a difference?, and how to get a work around for this to just test a simple use case of calling a method successfully in the above context.
Thanks.
Try something like this
describe Moderator do
it "should do something" do
moderator = Moderator.new
moderator.something.should == "do"
end
end
This assumes that you have a method something on Moderator and that it returns the string "do".
I think the RSpec Book provides great information and examples if you want to get more in-depth with your rspec.
Well,
The below line code did work for me:-
Model_name.method_name.should_not be_nil

using Selenium: how to use output from one test as input to another test

I'm a Selenium n00b... it's clear how easy it is to run a test and verify a particular response, but how can I take a value from one response and use it in the next test?
an example might be a contact creation form...
type in name/email and click submit
response arrives with new ContactID
grab the ContactID that was returned and put it into "get" textbox and click "submit"
response arrives with contact details
verfy the name/email match the first set
how might I go about doing this in Selenium?
And now something completely different:
Now I understand when you say "test", you mean a single assertion within one test case. So you want to use a value returned from a request as input for another request in the same test case.
Assuming you use selenium ide: To do this, use one of the "store..." commands in selenium ide and store the value into a variable. The contactID can be found using a matching selector with the storeText command. For example:
command: storeText
target: selector for element containing contactId
value: contactId
Then, use variable substitution and the type command to insert that text somewhere else.
command: type
target: selector for target input box
value: ${contactId}
Hope this helps :)
(This answer is still correct I think if you interpret "test" as "test case". For another, totally different answer see below.)
You don't do this. Each test should be independent from all other tests. For your second test, just repeat the steps in the first test. This way, you can reproduce test success and failures in a reliable way.
If you have many tests which all start from a certain application state which requires many steps to reach, just write a private helper method to reach that state.
The alternative: All steps you describe can be put into a single test. There is no reason not to have several asserts in one test.