Watir Powered LoadRunner Scripts

Here’s an idea… Ever been in a LoadRunner contract where you’ve got a ton of scripts to write for business transactions that have many many design steps?

Even worse, have you had to write those scripts against a development environment with an unstable code base and shocking performance? Sound familiar? Ever felt the frustration of re-recording manual test cases back into LoadRunner in said environments. Why wouldn’t you just automate the script recording process?


Well if you’re in a LoadRunner shop there’s probably a QTP license floating around. However there’s a great alternative with Ruby, specifically Web Application Testing In Ruby.

The gist is that you setup your manual test case using a watir script, then re-record your LoadRunner scripts using those watir scripts as the driver. The benefits are many:

1. Reduce user input errors when recording the LoadRunner scripts.
2. Have a consistent way of re-recording LoadRunner scripts based on the same input delivered by the watir script.
3. Diffing for correlation becomes easier because of consistency between multiple recordings of the same script.
4. Watir scripts are easier to maintain than LoadRunner scripts.
5. You can incorporate other Ruby gems into your watir scripts to assist with repetitive tasks during recording. For example, I copy transaction names to the clipboard between each step so I can easily paste them into transaction start timers.
6. Watir scripts can double as a smoke test which you can run in parallel with load tests that use only virtual users.
7. Watir scripts (and sampling response time from a real browser) will incorporate other factors such as client render time. Something which vusers really can’t do.

Downside is that you need to do a little more preparation than you might have to if you’re just following a manual test case. Once you have a framework for creating your watir script, this becomes easier. I figure it takes me about 1 hour to script up an end to end transaction that might have around 30 sub transactions (or design steps).

So what do you need to get started?

Firstly to install watir, follow these instructions here.

Come up with a framework for driving your manual test cases. There’s plenty of examples out there on how to make bullet proof frameworks driven from a variety of sources. Alister shares some good tips here.

Here’s a simple framework to get you started.

I have a helpers class that fires up the browser (attaches to the window that LoadRunner spawns) and some common methods for starting/stopping transaction timers and writing out information to a logfile. It looks like this.
helpers.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
require 'rubygems'
require 'watir'
require 'logger'
require 'win32/clipboard'
require 'dl'
require 'win32/sound'
include Win32
 
logfile = 'C:\temp\output.log'
@log = Logger.new(logfile, 'daily')
@log.info("\nNew test started at " + Time.now.to_s)
@log.datetime_format = "%H:%M:%S"
 
# if I want each step to start on the minute
# useful when tracing back through profile logs
# on the target server
@staggered = false
 
# pause after each step to prompt you to
# stop a transaction time or start a new one
@pause = false
 
# setup a clipboard object to copy transaction names to
@clipboard ||= Win32::Clipboard
 
# setup my browser object and attach to a running browser
# spawned by the loadrunner recording engine
@b ||=Watir::IE.attach(:title, /FOOBAR/)
 
# alternatively start a new browser
#~ @b ||=Watir::Browser.new
@b.visible = true
@b.speed = :fast
@b.bring_to_front
 
# display a simple message box with a dodgy sound
# to grab your attention
def message_box(txt, title=APP_TITLE, buttons=0)
  5.upto(10) { |i| Sound.beep(i*1000,30) }
  user32 = DL.dlopen('user32')
  msgbox = user32['MessageBoxA', 'ILSSI']
  r, rs = msgbox.call(0, txt, title, buttons)
  return r
end
 
# a start timer method
def timer_start
 
  # figure out how long to sleep if staggered start is true
  now = DateTime.now
  diff = 60 - now.sec
  sleep diff if @staggered
 
  # empty clipboard and copy current transaction name to it
  @clipboard.empty()
  @clipboard.set_data(@t)
 
  # prompt you to start a new transaction if pause is true
  message_box(@t, "Start Transaction", 0) if @pause
 
  @start_time = Time.now
end
 
# end timer method
def timer_end
  @end_time = Time.now
 
  # prompt you to stpo end a transaction if pause is true
  message_box(@t, "End Transaction", 0) if @pause
 
  # figure out elapsed time
  @elapsed_time = (@end_time - @start_time) * 1000
  tab = "\t"
 
  # write it all to you logger
  @log.info(@start_time.to_f.to_s + tab + @end_time.to_f.to_s  + tab \
  + tab + @start_time.to_s + tab + sprintf('%-60s', @t) + tab + sprintf('%10s', @elapsed_time.to_s) )
end
 
# a simple sync method to wait for text on a scren
def sync(text)
  Watir::Waiter.wait_until{ @b.text.include?(text) }
end

Now your manual test case in ruby should look pretty simple. I typically rely on things like the :name, :text or :id attributes of html elements depending on how the application was written by the developers. The manual test case will look something like this.
001_test_case.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
require 'helpers.rb'
 
begin
 
  @t = "INIT"
  timer_start
  @b.goto('https://foobar/wps/myportal')
  timer_end
 
  @t = "LOGIN"
  timer_start
  @b.text_field(:name, "username").set("yoohoo")
  @b.text_field(:name, "password").set("foobar")
  @b.button(:index, 1).click
  timer_end
 
  @t = "FOOBAR_03a_03_Tab"
  timer_start
  @b.link(:text, /FOOBAR/).click
  timer_end
 
  @t = "FOOBAR_03a_04_FOOBAR_Tab"
  timer_start
  @b.link(:text, /FOOBAR/).click
  sync("New FOOBAR")
  timer_end
 
  @t = "FOOBAR_03a_27_Record_Notes"
  @b.text_field(:id, "PC_7_C5L40JR2001F002J5MT98S28H6__L_8_0_1_0_14_1_1").set("Justification")
  timer_start
  @b.button(:text, /Save/).click
  timer_end
 
  @t = "FOOBAR_03a_28_Save_And_Foobaz"
  timer_start
  @b.link(:text, /Save & Foobaz/).click
  timer_end
 
  # etc ...
 
rescue Exception => e
  @log.error(@start_time.to_i.to_s + "\t" + sprintf('%-60s', @trans) + "\tError\n" + e)
end

Running this test case will output a log file to C:\temp\output.log that looks like this.

New test started at Thu Oct 08 20:37:48 +1100 2009
1254994670.936  1254994671.576          Thu Oct 08 20:37:50 +1100 2009  INIT                                                                 640.0
1254994671.576  1254994678.233          Thu Oct 08 20:37:51 +1100 2009  LOGIN                                                               6657.0
1254994678.233  1254994694.123          Thu Oct 08 20:37:58 +1100 2009  FOOBAR_03a_03_Tab                                          15890.0
1254994694.123  1254994696.014          Thu Oct 08 20:38:14 +1100 2009  FOOBAR_03a_04_FOOBAR_Tab                                      1891.0
1254994717.171  1254994727.608          Thu Oct 08 20:38:37 +1100 2009  FOOBAR_03a_05_Enter_FOOBAR_Type                              10437.0
1254994729.28   1254994743.499          Thu Oct 08 20:38:49 +1100 2009  FOOBAR_03a_06_Search_for_Primary_Person                      14219.0
1254994748.093  1254994767.265          Thu Oct 08 20:39:08 +1100 2009  FOOBAR_03a_07_Associate_Primary_Person                       19172.0
1254994767.265  1254994780.796          Thu Oct 08 20:39:27 +1100 2009  FOOBAR_03a_08_Enter_Primary_Person_Address_Details           13531.0
1254994780.796  1254994818.765          Thu Oct 08 20:39:40 +1100 2009  FOOBAR_03a_09_Enter_Primary_Person_Doc_Details        37969.0
1254994818.765  1254994835.906          Thu Oct 08 20:40:18 +1100 2009  FOOBAR_03a_16_Add_PoC _Link                                     17141.0
1254994838.828  1254994843.515          Thu Oct 08 20:40:38 +1100 2009  FOOBAR_03a_17_Add_PoC                                            4687.0
1254994852.078  1254994855.469          Thu Oct 08 20:40:52 +1100 2009  FOOBAR_03a_18_Search_Agent                                       3391.0
1254994855.469  1254994859.203          Thu Oct 08 20:40:55 +1100 2009  FOOBAR_03a_19_View_Agent                                         3734.0
1254994863.953  1254994876.203          Thu Oct 08 20:41:03 +1100 2009  FOOBAR_03a_20_Associate_Agent                                   12250.0
1254994876.203  1254994879.484          Thu Oct 08 20:41:16 +1100 2009  FOOBAR_03a_21_Add_Payment_Link                                   3281.0
1254994894.094  1254994894.703          Thu Oct 08 20:41:34 +1100 2009  FOOBAR_03a_22_Record_Payment_Details                              609.0
1254995196.611  1254995196.611          Thu Oct 08 20:46:36 +1100 2009  SAP                                                                    0.0
1254995202.486  1254995258.517          Thu Oct 08 20:46:42 +1100 2009  FOOBAR_03a_25_ Run Validity Assessment                          56031.0
1254995267.736  1254995280.017          Thu Oct 08 20:47:47 +1100 2009  FOOBAR_03a_27_Record_Notes                                      12281.0
1254995280.017  1254995346.579          Thu Oct 08 20:48:00 +1100 2009  FOOBAR_03a_28_Save_And_Foobaz                                    66562.0

Which gives you things like start and stop times, elapsed times and action names to help you debug things further down the track.

All up I think it’s a pretty neat solution for re-re-re-recording LoadRunner scripts (or your tool of choice) you inevitably face in fast changing environments. Whilst writing this post I had a script ticking away in the background recording some 3000+ LoadRunner events. YMMV.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">