How to run multiple ruby scripts? - ruby

Is there a way to call a ruby script a within another ruby script b? I have a ruby script which performs the website login (login.rb) and another script order_create.rb. I want to call login.rb first and then execute order_create.rb next. Please suggest.
Order_Created.rb:-
##order_data = YAML.load(File.open'C:\Users\order_details.yaml') def fill_order_form(order_data)
fill_in 'Firstname', :with => order_data['firstname']
fill_in 'Lastname', :with => order_data['lastname']
fill_in 'ZIP', :with => order_data['zip']
click_button 'Continue'
end
order_detail.yaml :-
firstname: "Order"
lastname: "Test"
zip: "90341"
login.rb:-
require './order_create.rb'
def login
#login code here
fill_order_form(##order_data)
end
Error on running login.rb :- undefined method `fill_order_form' for #<#<Class:0x3e344e0>:0x4248ba0>

A similar (although different) question already been answered at : Running another ruby script from a ruby script
You can include the script that you want to call in your script with:
require './b.rb' #if b.rb is in the same directory
and call it with:
b(args)
for your example, you can do the following:
login.rb
require './order_create.rb'
def login
#login code here
order_create()
end
Assuming that your create_order.rb contains def create_order()

Even though you can execute any shell command using backticks or %x
`ruby yourscript.rb`
%x(ruby yourscript.rb)
In this case it isn't good idea, since you have conventional ways of solving this, create third script, say login_and_order.rb and put following code inside:
require_relative 'login.rb'
require_relative 'order_create.rb'
# run your methods from both scripts in sequence you need
# or if they are just set of commands, nothing else needed

Related

Thor - command line option not recognized in method

I have to use this command to run my ruby program:
$ruby filename.rb NAME --from="People" --yell
And I have the script like this:
require 'thor'
class CLI < Thor
desc "hello NAME", "say hello to NAME"
method_option :from, :required => true
method_option :yell, :type => :boolean
def self.hello(name)
output = []
output << "from: #{options[:from]}" if options[:from]
output << "Hello #{name}"
output = output.join("\n")
puts options[:yell] ? output.upcase : output
end
end
CLI.hello(ARGV)
When I run the code, I get the following output:
c:\RubyWorkplace\Assignment1>ruby testing.rb Jay --from="Ray"
FROM: #<THOR::OPTION:0X000000031D7998>
HELLO ["JAY", "--FROM=RAY"]
c:\RubyWorkplace\Assignment1>ruby testing.rb Jay --from="Ray" --yell
FROM: #<THOR::OPTION:0X0000000321E528>
HELLO ["JAY", "--FROM=RAY", "--YELL"]
It looks like :yell always works no matter I specify it or not, and options are all read as name input in the hello method.
I found and tried many ways from online tutorials but the problem wasn't solved. Please tell me what has been gone wrong. Thank you!
The problem is caused by I am calling CLI.hello ARGV in the script. when the program runs, it will call hello method and recognize all command line inputs as hello's parameter, which is an array.
One of the ways to fix this problem is making hello public by removing self, the call the script by start method.
require 'thor'
class CLI < Thor
desc "hello NAME", "say hello to NAME"
method_option :from, :required => true
method_option :yell, :type => :boolean
def hello(name)
#do something
end
end
CLI.start ARGV

Using RSpec to test user input with gets

I'm new to Unit Testing using RSpec and Ruby and I have a question on how to test if my code is using the gets method, but without prompting for user input.
Here is the code I'm trying to test. Nothing crazy here, just a simple one liner.
my_file.rb
My_name = gets
Here's my spec.
require 'stringio'
def capture_name
$stdin.gets.chomp
end
describe 'capture_name' do
before do
$stdin = StringIO.new("John Doe\n")
end
after do
$stdin = STDIN
end
it "should be 'John Doe'" do
expect(capture_name).to be == 'John Doe'
require_relative 'my_file.rb'
end
end
Now this spec works, but when I run the code it prompts for user input. I don't want it to do that. I want to simply test if the gets method is being called and possibly mock the user input. Not to sure how to achieve this in RSpec. In Python I would utilize unittest.mock is there a similar method in RSpec?
Thanks in advance!
Here's how you could stub gets with your return value.
require 'rspec'
RSpec.describe do
describe 'capture_name' do
it 'returns foo as input' do
allow($stdin).to receive(:gets).and_return('foo')
name = $stdin.gets
expect(name).to eq('food')
end
end
end
Failures:
1) should eq "food"
Failure/Error: expect(name).to eq('food')
expected: "food"
got: "foo"
(compared using ==)
To test if something is being called (such as a function) you can use expect($stdin).to receive(:gets).with('foo') to ensure it is being called (once) with the right args. The expectation line in this scenario has to go before name = $stdin.gets.

Factory_girl/Capybara and Cucumber

In my Rails projects I normally use factory_girl to build/create users in my app. I want to know if I can use factory_girl when using Cucumber, Capybara to test the user interaction with my app. There is no database to save them to, I am only looking to store their credentials
I can have many users so wanted to create factories for each user (unless there is a better way of doing this with Cucumber).
Within my support folder could I create a factories folder and then a .rb file holding each user.
FactoryGirl.define do
factory :user_1 do
username "username"
password "password"
end
end
Within my env.rb file I am requiring Factory Girl but this is not enough
require 'factory_girl'
As if in my feature I try
Then(/^I will enter my credentials$/) do
fill_in 'username', :with => user_1.email
fill_in 'password', :with => user_2.password
click_button 'login-button'
end
I get
uninitialized constant user_1
I also have a feeling that if this is to work I need a before hook that will build the factory user but I'm unsure on the whole setup at the moment.
Does anyone use factory_girl in this way or, as I mentioned earlier, is there a better way to do this?
You should be able to do seething like this
Given(/^I will enter my credentials$/) do
#user = user = FactoryGirl.create(:user)
end
you can read more on this question https://stackoverflow.com/a/16841999/4421094 it was really helpful
Thanks to #MarshallCap for the answer, I had come up with a workable solution and wanted to share, maybe its right or maybe there is a better way but this is what I have ended up doing, if this helps someone else then great.
Firstly I created a class for my factory_users
class Users
FactoryGirl.define do
factory :user_1, :class => :users do |u|
u.skip_create
u.username "username1"
u.password "password"
end
end
FactoryGirl.define do
factory :user_2, :class => :users do |u|
u.skip_create
u.username "username2"
u.password "password2"
end
end
end
require factory_girl in env.rb
require 'factory_girl'
And within my login script within step_definitions assigned an instance variable a hash of the users attributes
Then(/^I will enter my credentials$/) do
#user = FactoryGirl.attributes_for(:user_1)
fill_in 'username', :with => #user[:username]
end

how to run capybara commands once, then run some tests

I have the given testing code:
describe 'A new user', js: true do
before do
#new_user = Fabricate.build(:user)
end
it 'should sign up' do
#login code
visit '/'
click_link 'Login'
fill_in 'user[email]', :with => #new_user.email
fill_in 'user[password]', :with => #new_user.password
click_button 'Login now'
#login code end
page.should have_content("Hello #{#new_user.first_name}!")
current_path.should == dashboard_path
end
it 'should receive a confirmation mail' do
#same login code again
visit '/'
click_link 'Login'
fill_in 'user[email]', :with => #new_user.email
fill_in 'user[password]', :with => #new_user.password
click_button 'Login now'
mail = ActionMailer::Base.deliveries.last
assert_equal #new_user.email, mail['to'].to_s
end
end
Now I want to add more tests.
To avoid code doubling, how can I run the capybara login code once before all tests?
One solution would be to put the login code in the before method. Another would be to create a method do_login, put the code in it and run every test like this:
it 'should do something after login' do
do_login
#test code here
end
But for both solutions, the code is run for every test and thats not what I want. Putting the login code in a before(:all) doesn't work, too.
How can I run some capybara code once and then do all the tests after this?
You can't run capybara code once and then run all the tests. You always start from scratch. Your proposed solution with before(:each) or helper method is the only posibility. (It's possible to run some ruby before(:all) e.g. create objects outside the transaction check here but not Capybara)
To speed up your specs you can test login feature in separate spec and then somehow stub the authentication but it depends on your implementation.
If you are using Devise check devise wiki: https://github.com/plataformatec/devise/wiki/How-To:-Controllers-tests-with-Rails-3-(and-rspec)

In Ruby, how do you execute rspec code from a string rather than from a file?

I am trying to execute rspec code passed in to a Ruby process as a string. How can I execute rspec from within a Ruby process rather than from the commandline and capture the results?
# Ruby code
code = '
#solution
class User
def in_role?(role)
true
end
end
#Tests to pass
describe User do
it "should be in any roles assigned to it" do
user = User.new
user.should be_in_role("assigned role")
end
end
'
# spec code
# numExamples = examples
# numFailures = failures
Is there any reason you should get the code as a string in first place? If you want to have access to the data rspec produces, you can try using a custom RSpec formatter

Resources