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.
