_ruby
Example
Before we get started we'll need to download a copy of BrowserMob Proxy. Once we have that, we'll want to include our requisite libraries:
selenium-webdriver
to control the browserbrowsermob/proxy
to configure/use BrowserMob Proxytyphoeus
to replay HTTP requests
After that, we can create methods to configure the proxy server (configure_proxy
), set the browser profile to use the proxy server (browser_profile
), pull these together so the test will have a working browser that uses the proxy server (setup
), and tear things down after running the test (teardown
).
# filename: load.rb
require 'selenium-webdriver'
require 'browsermob/proxy'
require 'typhoeus'
def configure_proxy
proxy_binary = BrowserMob::Proxy::Server.new('./browsermob-proxy/bin/browsermob-proxy')
proxy_binary.start
proxy_binary.create_proxy
end
def browser_profile
browser_profile = Selenium::WebDriver::Firefox::Profile.new
browser_profile.proxy = @proxy.selenium_proxy
browser_profile
end
def setup
@proxy = configure_proxy
@driver = Selenium::WebDriver.for :firefox, profile: browser_profile
end
def teardown
@driver.quit
@proxy.close
end
Next we'll want to tell the proxy server to capture traffic and return a payload (a.k.a. a HTTP Archive, or HAR). For easier debugging later, we will want to add some error handling to output the results from each HTTP request that's replayed (error_handling
).
def capture_traffic
@proxy.new_har
yield
@proxy.har
end
def error_handling(request)
request.on_complete do |response|
if response.success?
puts "success"
elsif response.timed_out?
puts "got a time out"
elsif response.code == 0
# Could not get an http response, something's wrong.
puts response.return_message
else
# Received a non-successful http response.
puts "HTTP request failed: " + response.code.to_s
end
end
end
Now for the meat of the issue -- replaying the requests.
def replay(http_requests, number_of_replays, debug = false)
requests = []
http_requests.entries.each do |entry|
requests << Typhoeus::Request.new(
entry.request.url,
method: entry.request.method.downcase.to_sym)
end
start_time = Time.now
puts "Start time: #{start_time}"
threads = []
number_of_replays.times do
threads << Thread.new do
requests.each do |request|
error_handling request if debug
request.run
end
end
end
threads.each {|thread| thread.join }
finish_time = Time.now
puts "Finish time: #{finish_time}"
puts "#{number_of_replays} runs completed in #{finish_time - start_time} seconds"
end
We start by iterating through each of the entries in the HAR payload, creating a new request for Typhoeus to use -- storing them all in an array.
After printing the current time to the terminal, we create a new thread and execute all Typhoeus HTTP requests within it (outputting the error handling for each request if a debug parameter is passed in). This gets repeated based on the number of times specified when replay
is called.
After the threads run and terminate, we output the current time, and then list the total time run time along with the number of replays attempted.
We can now pull all of this together by implementing a simple run
method.
def run
setup
http_requests = capture_traffic { yield }
teardown
replay(http_requests, 100)
end
If we wanted to see the debug output, we would pass in true
as a third parameter like so:
replay(http_requests, 100, true)
Now that everything's wired up, we can drop our Selenium actions into a run block.
run do
@driver.get 'http://the-internet.herokuapp.com/dynamic_loading/2'
@driver.find_element(css: '#start button').click
Selenium::WebDriver::Wait.new(timeout: 8).until do
@driver.find_element(css: '#finish')
end
end
If we run this script without debugging turned on, then we should see something like this:
Start time: 2014-04-30 14:22:33 -0400
Finish time: 2014-04-30 14:23:10 -0400
100 runs completed in 37.575052 seconds
Expected Behavior
- Load a browser
- Visit the page and complete the actions specified while capturing the HTTP requests
- Close the browser and shutdown the proxy server
- Replay the HTTP requests generated by Selenium 100 times in parallel
Summary
Hopefully this was helpful in helping you figure out how to do load testing.
Happy Testing!