ruby cucumber - step undefined message but step exists in step_definitions - ruby

I'm currently getting an unusual error message in that during the run of my BDD scripts, I get the following response when running through the command line:
Feature: As a user I want to purchase a mobile on a monthly plan
#ACQ_Test_01
Scenario: Buy a pay monthly phone
Given I am on the Store Homepage
When I click on the Mobile Phones roundel link
And I select a "Apple" "Iphone 6s"
-->And I select the "1GB+AYCE min" price plan<--
Then I can complete my order
1 scenario (1 undefined)
5 steps (1 skipped, 1 undefined, 3 passed)
0m0.130s
(The one in arrows is the one highlighted in my command line as being undefined)
However, in my .rb script under step_definitions folder, I have the following:
Given (/^I am on the Store Homepage$/) do
**CONTENT-HERE**
end
When (/^I click on the Mobile Phones roundel link$/) do
**CONTENT-HERE**
end
When (/^I select a "Apple" "Iphone 6s"$/) do
**CONTENT-HERE**
end
When (/^I select the "1GB+AYCE min" price plan$/) do
**CONTENT-HERE**
end
Then (/^I can complete my order$/) do
**CONTENT-HERE**
end
I'm not sure why this cucumber script is missing out a step, but it's infuriating me to no end. Can anyone help?
EDIT: Off the back of that, if anyone can also answer why it's not showing me the snippets that it's expecting, that'd be great.

You should not be creating a step for each plan.
When (/^I select the "([^"]*)" price plan$/) do |plan|
case plan
when "1GB+AYCE min"
# do something
end
end

You're getting a missing step-def error because your regex isn't matching your text.
What you want is:
When (/^I select the "1GB\+AYCE min" price plan$/) do
Which will match the literal character + rather than B one or more times.
Remember, ruby-cucumber uses regular expression syntax rather than literal strings to match step-defs.

Related

Create multiple selection options and go back options on ruby cli app

I am trying to build a ruby CLI application and I want my user to select from a certain amount of options that I provide him with.
Remember: This is not a ruby on rails app and there is no views or anything. It is one file of ruby code that I intend to create which shall be responsive to whatever the user types.
When a user runs the script. He should be able to see 3 options and should be able to select them and each of these should have different implications.
A very simple approach without any additional gem might be:
puts "Choose an option"
puts "1 – Option 1"
puts "2 – Option 2"
# ...
case gets.chomp.to_i
when 1
puts "run code for option 1"
when 2
puts "run code for option 2"
# ...
else
puts "invalid option"
end

Is there anyway I can run the same test case but with different values everytime?

I have a single test case to test a particular scenario in a particular environment everyday, this is automatically done by a jenkins job.
Scenario Outline: Verify a user can book
Given I navigate to the "xxxxx" Page
And I set the "Location" field with "<location>" value
And I click on the "Search" button on "xxxxx" page
Then I verify the "Results" page is displayed
Examples:
| location |
|Boston |
I need to internally have a list of 20 locations and everytime the test case is executed it changes the location some how, can be ramdon or in any order, but always changing.
I'm using cucumber, capybara and of course ruby
Thoughts please?
Cucumber has a lot of limitations in terms of being used as a programming language. It's easier to do this kind of thing if you move it into a ruby file (cucumber files aren't ruby).
One option would be to make a single step that calls these other steps internally. Some people might say it's better to call methods rather than steps from inside other steps, but if you already have your cases written as steps than this will be quicker to do it this way, because you don't have to rewrite the code into methods. It is a good idea to write test code in methods and then call them from steps, by the way, rather than putting all the logic in the test cases.
Cucumber file:
Scenario Outline: Verify a user can book
Given I navigate to the "xxxxx" Page
Then the search bar works
Ruby file:
Then /the search bar works/ do
locations = ["Boston", "Berkeley"].shuffle
locations.each do |location|
step %{I set the "Location" field with "#{location}" value}
step %{I click on the "Search" button on "xxxxx" page}
step %{I verify the "Results" page is displayed}
end
end
Another reason this could be considered nonidiomatic is because it's packing too much into a single test case. However I'm not sure a good way to get around this other than simply copy-pasting the original step definitions in the cucumber file with different hard-coded values.
It's possible
locations = ["Boston", ...]
day_of_the_month = Date.new(2001,2,3).mday
today_location = locations[(day_of_the_month - 1) % locations.count]
I use - 1 in the third line since #mday returns integer from 1 to 31.

Cucumber and Capybara : How to wait for next page to load. After I click on submit button,Test case is failing and not able to find element

How to wait for next page to load. After I click on submit button(Basic Registration flow), Test case is failing and not able to find element. I'm quite new to this, first time using cucumber and capybara.
I have given 10 seconds in default wait time, is there any way to explicitly wait for that element using capybara.
Error :
Scenario: Register with valid credentials # features/Job_seeker_Registration.feature:6
Given I am on "/register" # features/step_definitions/web_steps.rb:2
Unable to find field "#jobseekerName"
When I have entered "Seeker1" into the "jobseekerName" field # features/step_definitions/web_steps.rb:6
Unable to find field "#jobseekerMobileOrEmail"
When I have entered "7812125899" into the "jobseekerMobileOrEmail" field # features/step_definitions/web_steps.rb:6
Then I wait for 1 seconds # features/step_definitions/web_steps.rb:33
When I pick "Driver" from "field-desiredcategory" # features/step_definitions/web_steps.rb:16
Unable to find field "#jobseekerPassword"
When I have entered "4679" into the "jobseekerPassword" field # features/step_definitions/web_steps.rb:6
And I click on "jobSeekerRegister" # features/step_definitions/web_steps.rb:11
Then I wait for 40 seconds # features/step_definitions/web_steps.rb:33
Then I should see "verificationButton" # features/step_definitions/web_steps.rb:25
expected to find text "verificationButton" in "SEARCH JOBS SEARCH CANDIDATES LOOKING TO HIRE? (RSpec::Expectations::ExpectationNotMetError)
features/Job_seeker_Registration.feature:15:in `Then I should see "verificationButton"'
And I click on "Seeker 1" # features/step_definitions/web_steps.rb:11
And I click on "Edit my Profile" # features/step_definitions/web_steps.rb:11
Then I wait for 1 seconds # features/step_definitions/web_steps.rb:33
HTML screenshot: ./screenshot/screenshot.html
Image screenshot: ./screenshot/screenshot.png
Failing Scenarios:
cucumber features/Job_seeker_Registration.feature:6 # Scenario: Register with valid credentials
1 scenario (1 failed)
12 steps (1 failed, 3 skipped, 8 passed)
0m55.271s
Code:
Then /^I should see "(.*?)"$/ do |text|
page.should have_content(text)
end
Then /^I should see title "(.*?)"$/ do |text|
page.should have_title?(text)
end
Given /^I wait for (\d+) seconds?$/ do |n|
sleep(n.to_i)
end
You probably need to adjust how you're testing for the presence of the element. If you're doing it correctly, Capybara will wait until the element appears.
For example:
# this noes not wait until the element exists
first(".active").click
but if you use find
# this this waits until an element with the class "active" is found
find(".active").click
Thoughtbot have a great article giving more examples on this.

Cucumber transform to exclude cucumber table

I wanted a transform in my cucumber framework where whenever I give 'test test', I should get test_test in my step def.
I wrote a transform as below :
SPACE_TO_UNDERSCORE = Transform /^([^"]* [^"]*)$/ do |string|
string.tr!(" ", "_")
end
Which makes my step :
And the user selects yes to "dual nationality" on "edit user" details page
to
And(/^the user selects yes to "([^"]*)" on "([^"]*)" details page$/) do |field,page|
# field is now dual_nationality
# page is now edit_user
end
it works but the only problem is it also captures the cucumber tables steps like
below and converts the table to table:case_number string. table is Cucumber::MultilineArgument::DataTable if i don't use the transform. so obviously the transform is affecting the table if it matches its contents.
Is there a way to do that in transform where you can exclude table content ?
When the user loads a url with below case details
| case number |
| 154745 |
When(/^the user loads a url with below case details$/) do |table|
#table => "table:case_number"
end
I'd suggest not writing scenario steps like this and avoiding transforms. Your step explain 'HOW' the user says they are a dual national. It has no need to do this. Consider:
Given the user has dual nationality
Given I am a dual national
When the user confirms their dual nationality
When I confirm my dual nationality
There are of course many other ways to word this.
All these steps require no transforms, and no regex's and can easily be implemented by doing something like
find_by_css('#dual_national').set(true)
Assuming you have a dual_national checkbox.
In general every time you put detail in your scenarios about "HOW" you do things you just make live harder for yourself. There is no need to use tables, transforms or even (most of the time) regex's when using Cucumber

Listing contents of Array Printing at Incorrect Time (Opening Array from Marshall)

Ruby Newbie here. I am working on a landlord application for class.
The idea is to be able to do certain functions that a landlord would be able to do to manage their properties. To accomplish this, I have a main menu method, which functions like this:
def main_menu
puts "Please choose an option from the following menu:"
puts " 1. List All Apartments"
puts " 2. View Apartment Details"
puts " 3. Add an Apartment"
puts " 4. Add a Tenant"
puts " 5. Evict a Tenant"
puts " 6. Quit"
input = gets.chomp
case input
when "1"
list
when "2"
view(select_apt)
when "3"
add
when "4"
tenant(select_apt)
when "5"
evict(select_apt)
when "6"
File.open('listing.txt', 'w') {|file| file.truncate(0) }
File.open('listing.txt', 'w') {|file| file.write(Marshal.dump($array))}
else
puts "I'm sorry, that's not a valid option.\n\n"
main_menu
end
end
The purpose of the two lines in the quit option (6) is to be able to retrieve the array which contains each of the apartment objects. The global apartment array, $array, is created at the beginning of the program using:
$array = Marshal.load(File.binread('listing.txt'))
Originally, I was using a built in array to test, and everything was working the way I expected it to. Now, however, every function works with the exception of the List method:
def list
puts "You have the following apartments:\n"
$array.count.times do |i|
if $array[i].renters.empty?
print "#{$array[i].address}: is #{$array[i].sqft} square feet, has #{$array[i].num_beds} bedrooms and #{$array[i].num_baths} bathrooms. The monthly rent is $#{$array[i].monthly_rent}. \n\n"
else
print "#{($array[i].address)}: "
print "#{view_tenants(i)}"
end
end
main_menu
end
When I call the list method by selecting 1 at the main menu, it will only list the 1st apartment. Weirdly enough, when I attempt to exit, using "6", the program instead prints out info about the apartments, one by one. The output of the terminal is displayed here:
Please choose an option from the following menu:
1. List All Apartments
2. View Apartment Details
3. Add an Apartment
4. Add a Tenant
5. Evict a Tenant
6. Quit
6
500Jane Street: Nicole is the sole tenant at this apartment.
Please choose an option from the following menu:
1. List All Apartments
2. View Apartment Details
3. Add an Apartment
4. Add a Tenant
5. Evict a Tenant
6. Quit
6
5001776, Floor 8: The renters living at the apartment are Jessica, and Jamie.
Please choose an option from the following menu:
1. List All Apartments
2. View Apartment Details
3. Add an Apartment
4. Add a Tenant
5. Evict a Tenant
6. Quit
6
500Please choose an option from the following menu:
1. List All Apartments
2. View Apartment Details
3. Add an Apartment
4. Add a Tenant
5. Evict a Tenant
6. Quit
6
Brandons-MacBook: Brandon $
Everything worked how I expected it to when I manually set an array equal to what I wanted it to be. Also, if I select the "View Apartment Details" option, it correctly lists out all of my current apartments(so that I can select one). It is only the "List All Apartments" option that gives me trouble. It is my first time using Marshall, so please let me know if I am doing something incorrectly. If necessary, I can provide more code.
Thanks in advance!
I don't know exactly whats causing the problem.
However, don't use globals in ruby, unless the variable represents the state of the program itself.
Read more here http://ruby.about.com/od/variables/a/Global-Variables.htm.
Try changing your global variable to an instance variable #array.
This variable is now seen throughout your class. Or even better a Constant.
If you have more than one instance of your class you could use a class variable ##array.
Now this variable can be seen by many instances of this class.
Note, ruby programmers try to avoid using class variables.
Also don't do array.count.times. Do each or each_with_index.

Resources