Skip to main content

_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 browser
  • browsermob/proxy to configure/use BrowserMob Proxy
  • typhoeus 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!