How to make locust load scripts run in sequence? - performance

I'm trying to automate the following scenario with locust:
Login to application (put it in on_start, so it will login all the sessions first) and get token value from response of login call.
Create an organization
Create a user.
I need these calls to be executed in the order shown.
However, if I add #task for the 2nd and 3rd steps, it will pick these calls randomly, which causes my code to break.
Any suggestions?

Use Locust's TaskSequence class:
class SequentialTasks(TaskSequence):
def on_start(self):
# login to application and get token value from response of login call
#seq_task(1) # the first thing to do
#task(n) # do it n times
def create_org(self):
# create org
#seq_task(2) # the second thing to do
#task(n) # do it n times
def create_user(self):
# create user

You can just do it all in a single task. There is no limit to a single HTTP call within a single task (you could even put it all in on_start if you want to).
class MyTaskSet(TaskSet):
def on_start(self):
// do login
self.token = ...
#task
def create_task(self):
// create org
self.client.post(...)
// crete user
self.client.pos(...)

Related

How to use the variable in one action to another action

In the ruby controller, I have two methods in the same controller.
class NotificationsController < ApplicationController
def first
variable_one = xxxx
end
def second
// do something
end
end
I want to use the variable one in the method first, and use it in the method two. I tried to assign the variable one to a session hash. session[:variable_one] = variable_one, and access it in the method two. But it turns out the session[:variable_one] in the method two is nil. These two methods don't have the corresponding views, so I cannot add a link_to and pass parameters. The method one cannot be set as before_action as well.
Could you please have some suggestions on this problem? Thanks so much.
The issue that session is stored via cookie, and therefore it is specific to one device. So, you will have one session between the rails app and your frontend, and another session betweeen the rails app and Twilio (probably the Twilio session will reset between each request). Basically, they're totally separate contexts.
Possibly you could figure out how to pass the information along via Twilio - see https://www.twilio.com/docs/voice/how-share-information-between-your-applications - but as a general-purpose workaround, you could just store the column on the database.
First, make a migration to add the column:
add_column :users, :my_variable, :string
Set this value in the first endpoint:
def first
current_user.update my_variable: "xxxx"
end
Then read it from the second:
def second
# first you would need to load the user, then you can read the value:
my_variable = current_user.my_variable
# you could set the db value to nil here if you wanted
current_user.update my_varible: nil
end

unable to reference object/instance variable in separate ruby file for automation test

Ruby Newbie here! I am re-writing automated unit tests. The problem is that there are too many 'test users' that get changed and used by others. So the goal is to make a list of test users for each repository, and have them referenced in a specific file rather than hard-coding the email/password logins. I am unable to figure out how to have:
1. the .feature file with the test
2. the steps.rb with the steps for the test
3. a final user.rb file that holds class/instance variables (I don't care which I use, it just has to be able to be referenced by all the tests I will be re-writing).
I've tried referencing the email/password details from the steps.rb file in these ways:
* Then('User enters \”([^\”]*)\”$”')
* Then('User enters ')
* Then('User enters '/valid_user_email>')
I've tried defining the email/password in user.rb in these ways:
* #valid_user_email = 'user#url.com'
* puts 'valid_user_email' = 'user#url.com'
* = 'user#url.com'
Currently the login.feature file is:
Feature: Login and Logout of MySE
Scenario: Login and Logout of MySE
Given I enter the email address of an existing account
Then User enters valid_user_email in the email field
The login_steps.rb file looks like:
Given('I enter the email address of an existing account') do
visit "user/profiles"
expect(page).to have_content('Welcome')
end
Then('User enters valid_user_email in the email field') do
fill_in 'user_login', with: #valid_user_email
click_on('Next')
end
And finally, the user.rb file looks like:
class Credentials
def valid_user_email
#valid_user_email = "user#url.com"
end
def valid_user_password
puts "Testttttt01"
end
end

Passing parameter in "Examples:" table of "Scenario Outline:" in a feature file

Here as you can see I am trying fetch a value from .yml file located in config/environments in Examples: table.
But instead of fetching it is sending the value as it is?
Is it possible to pass parameter like this? If Yes, how?
If not, which Ruby or Cucumber feature/concept refrains user to do so and why?
Feature: Verify login of all test users
I want to verify all test users can login.
Scenario Outline: Login as different users on the website
Given I am on login page
When I enter "<username>" and password
Then I click Login button
And I see "<user>" successfully logged in
Examples:
|user|username|
|testuser1|#{FigNewton.test1_email}|
|testuser2|FigNewton.test2_email|
First of all this is a pretty poor feature, better would be
Scenario: Test Users can login
Given there are some test users
When the test users login
Then all test users should be logged in
or something like that. Features are for stating what you want to do and why, not how you do things.
IF you do the above then all the programming will be done in the step definitions. This will allow you do do whatever you want.
You can implement this quite easily e.g
Given 'there are some test users' do
#test_users = create_test_users
end
When 'the test users login' do
#login_results = login_each(#test_users)
end
Then 'all test users should be logged in' do
expect(check_for_errors(#login_results).count).to eql 0
end
then implement the methods you need in a step helper e.g
module TestUsersLoginStepHelper
def create_test_users
...
def login_each(users)
users.each do
...
...
end
World TestUsersLoginStepHelper
By putting all the work in the step definitions, you make your live much easier, as you can use the full power of ruby to do what you need
Answer to query1:
You can parametrize via Examples: table but not directly passing value using FigNewton gem because it is a .feature file not a Ruby .rb file.
Answer to query2:
How you do it:
Parametrize and Loop it on username and in you steps definition mention what to do when particular user name found. By this you can easily parametrize.
Examples:
|user|username|
|testuser1|test1|
|testuser2|test2|
Step definition
When(/^I enter "([^"]*)" and password$/) do |username|
case username
when 'test1'
on(LoginPage).user_email = FigNewton.test1_email
when 'test'
on(LoginPage).user_email = FigNewton.test2_email
end
....
....
end
You can use this DDD scenario in project whenever its needed - by using this we do not need to create multiple test cases, it will fetch data value from Example outline.
Feature file : Test case
Scenario Outline: Login to application
When I enter "username>" and "password>"
Then I click Login button
And I see user successfully logged in
Examples:
|username|password|
|abc#gmail.com|Test1234!|
|abc#yahoo.com|Test1234!|
Step definition:
When(/^I enter "([^"])" and "([^"])"$/) do |username,password|
sleep 20
on(Login).email_edit_text_element.send_keys username
on(Login).password_edit_text_element.send_keys password
end
Then(/^I click Login button$/) do
sleep 20
on(Login).login_button_element.click
end
Then(/^I see user successfully logged in$/) do
expect(on(Login).account_bg_cover_element.displayed?).to be_truthy
puts 'Login Success'
end
In ruby file, you have created methods, you are calling that methods in step definition.
It will work. make sure about the name of parameter you are passing.

Page objects in watir splash -- how to ensure that the proper page object is instantiated

I am using the Watir Splash framework to test a web application, and I have setup two page classes. The first is the "Login" page which is detailed here:
module App
module Page
class Login < WatirSplash::Page::Base
url "http://[removed].com"
def login_btn
modify button(:id => 'btnLogin'), :click => lambda {redirect_to VehicleSelection}
end
The other page class is the "Vehicle Selection" page. I have used the modify method as shown in the documentation here to ensure that the vehicle selection page object is available for RSpec after a successful login.
But what happens if the login failed? I have some test cases that deliberately feed incorrect information into the login form to ensure that the authentication is working properly. RSpec would need the methods defined in the "Login" class to access the correct elements to complete the test case. In this case, the way that I have specified the method a "VehicleSeleciton" object will be returned regardless. (or so it appears)
Any help is appreciated. Also, I'm open to other suggestions for testing frameworks, especially if there is more example code for me to reference.
Below are a couple of approaches I have tried. I was not using the WatirSplash framework, but the same concepts applied (though the attempted WatirSplash example code might not be 100% accurate).
Solution 1: Do return page objects
My personal preference is to not have page objects returning page objects. Instead, I find it easier to read/work with explicit initializations of each page object within the test. Alister Scott discussed this in his blog.
Your tests would then look like:
#For login successful tests
page = App::Page::Login.new
page.login_btn.click
page = App::Page::VehicleSelection.new #The VehicleSelection page is explicitly initialized
page.validate_page #or whatever you want to do with the page
#For login failed tests
page = App::Page::Login.new
page.login_btn.click
page.validate_page #or whatever you want to do with the page
Solution 2: Create multiple methods for login
Another solution, would be to create two login methods - one for successful login and one for unsuccessful login.
The page object could be:
module App
module Page
class Login < WatirSplash::Page::Base
url "http://[removed].com"
def login(user, password)
#Do whatever code to input name and password and then click the button
#Then redirect to the VehicleSelection page since that is where you will want to go most often
redirect_to VehicleSelection
end
def login_failed(user, password)
login(user, password)
#Return the Login page (instead of the VehicleSelection page).
redirect_to Login
end
end
end
end
With the tests being:
#For login successful tests
login_page = App::Page::Login.new
vehicle_page = login_page.login(user, password)
vehicle_page.validate_page #or whatever you want to do with the Vehicle Selection page
#For login failed tests
login_page = App::Page::Login.new
login_page.login_failed(user, password)
login_page.validate_page #or whatever you want to do with the Login page
Solution 3: Make the button know where it is going
Another solution, would be to have the login button know which page to redirect to.
The page object could be:
module App
module Page
class Login < WatirSplash::Page::Base
url "http://[removed].com"
def login_btn(login_successful=true)
if login_successful
modify button(:id => 'btnLogin'), :click => lambda {redirect_to VehicleSelection}
else
modify button(:id => 'btnLogin'), :click => lambda {redirect_to Login}
end
end
end
end
end
With the tests being:
#For login successful tests
login_page= App::Page::Login.new
vehicle_page = login_page.login_btn.click
vehicle_page.validate_page #or whatever you want to do with the Vehicle Selection page
#For login failed tests
login_page= App::Page::Login.new
login_page.login_btn(false).click
login_page.validate_page #or whatever you want to do with the Login page
Thanks for trying out my gem WatirSplash. I would have written something in the lines of solution #2 - e.g. create two separate methods for successful login and failed login. Using #modify is not needed in either method, like Justin did.
Also, i'd suggest you to use my other gem test-page instead, which is more or less the same, as Page Objects in WatirSplash, but it is extracted into separate gem - WatirSplash will be deprecated in the long term due to all of its parts being exctracted into separate gems giving better control of which functionality is needed in each project.

Devise: Is it possible to NOT send a confirmation email in specific cases ? (even when confirmable is active)

Here is my situation, I use devise to allow users to create account on
my site and manage their authentication.
During the registration process I allow customers to change some
options, leading to an actually different account being created but
still based on the same core user resource.
I would like to choose not to send a confirmation email for some of
those account types. I don't care if the account do not get confirmed
and user cannot log in, that's ok, no pb with that.
How would I go about doing that ?
Thanks,
Alex
Actually it's quite easy once I dig a little deeper.
Just override one method in your User model (or whatever you are using):
# Callback to overwrite if confirmation is required or not.
def confirmation_required?
!confirmed?
end
Put your conditions and job's done !
Alex
If you just want to skip sending the email but not doing confirmation, use:
# Skips sending the confirmation/reconfirmation notification email after_create/after_update. Unlike
# #skip_confirmation!, record still requires confirmation.
#user.skip_confirmation_notification!
If you don't want to call this in your model with a callback overwrite this method:
def send_confirmation_notification?
false
end
You can also simply add the following line of code in your controller before creating the new user:
#user.skip_confirmation!
I don't know if Devise added this after the other answers were submitted, but the code for this is right there in confirmable.rb:
# If you don't want confirmation to be sent on create, neither a code
# to be generated, call skip_confirmation!
def skip_confirmation!
self.confirmed_at = Time.now
end
I was able to do something similar with the functions:
registrations_controller.rb
def build_resource(*args)
super
if session[:omniauth] # TODO -- what about the case where they have a session, but are not logged in?
#user.apply_omniauth(session[:omniauth])
#user.mark_as_confirmed # we don't need to confirm the account if they are using external authentication
# #user.valid?
end
end
And then in my user model:
user.rb
def mark_as_confirmed
self.confirmation_token = nil
self.confirmed_at = Time.now
end

Resources