Loadrunner Batch Scheduler – Excel Version #3

I’ll be honest, I’m surprised at how quickly this has come together. I didn’t even know if I could make it work when I began, and I’ve managed to fit it in with doing full time performance testing and living life as an international contractor.

It’s not “finished” but then nothing ever really is in AutomationSolutions-world. There is scope to extend beyond the 15 or 16 runs it currently caters for. I can make that ticker a bit less intrusive too I expect. But the fact is that it works… and it works rather well.

It’s not the prettiest spreadsheet in the world, and there are other features I’d like to add to allow for user configuration. But they’re my changes. You’re going to have to ask nicely for them. Or you can use v1.0, the basic scheduler. Which is provided here:

LR_Batch_Scheduler

It’s taken a little over a week to build that and roll it out in Belgium, we’re using it this evening for the next cycle of tests. If there’s no update on this following that, you’d be safe to assume that it works as reliably as I think it does.

I hope it’s usage is fairly self-explanatory since I haven’t prepared any sort of documentation yet, and I’m not likely to unless someone screams.

Loadrunner Batch Scheduler – Excel Version #2

From the previous post, it should be possible to see that the next_tick function which counts the time is our trigger for execution.
Specifically this loop and if combination:

For i = 0 To UBound(ArrTimes)
If [A1].Value = ArrTimes(i) Then
Application.StatusBar = "Running test id: " & Range("A" & i + 6).Value

End If
Next i

Since I first wrote that last week, I’ve added a field to state that a run has been “done”. And I’ve built in a little tolerance by checking if the current time is greater than the execution start time – stored as ArrTime(n).

I’ve also borrowed some code from VBA Express to terminate a running process. Now I’m not terminating the process, I’m just checking if WLRun.exe aka the controller is running.

So the latest code looks like this:

For i = 0 To UBound(ArrTimes)
If [A1].Value >= ArrTimes(i) And Range("F" & i + 6) <> "DONE" Then

'Check if LR is already running
strTerminateThis = "wlrun.exe" 'Process to terminate,

Set objWMIcimv2 = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\.\root\cimv2") 'Connect to CIMV2 Namespace

Set objList = objWMIcimv2.ExecQuery _
("select * from win32_process where name='" & strTerminateThis & "'") 'Find the process to terminate

If objList.Count = 0 Then 'If 0 then process isn't running
Application.StatusBar = "Running test id: " & Range("A" & i + 6).Value
Range("F" & i + 6) = "DONE"
Call StartTest(Range("B" & i + 6).Value, Range("C" & i + 6).Value)

Else

Application.StatusBar = "Loadrunner Controller is still running"

End If

End If
Next i

I’ve just replaced the existing section with that, but I’ll post the full deliverable at some point (when it’s finished 🙂 )

I’ve also defined the module to call the controller.

Sub StartTest(Scenario_Path, Results_Path)

'Wlrun.exe -Run -TestPath scenario.lrs -ResultName res_folder
strCommand1 = Range("D1").Value 'Path to WLRun.exe
strCommand2 = Scenario_Path
strCommand3 = Results_Path

strCommand = strCommand1 & " -Run - TestPath " & strCommand2 & " -ResultName " & strCommand3
MsgBox (strCommand)
'Shell (strCommand)

End Sub

At the moment it just message_boxes the command string for testing purposes.

So now, we have:

A time-based system within Excel which will run a defined scenario at the appropriate time. I haven’t figured out yet what I’d like to do if WLRun is still running, but it’s coming together and I think that’s the last thing. I think I’ll add a minute on to all future runs to delay the system.

I also added an autoschedule function, mostly for testing purposes. I’ll document that in a future post, it’s not really important.

Loadrunner Batch Scheduler – Excel Version

I’ve made a start on the Loadrunner Batch Scheduler – There is still a long long way to go, but the basis of the underlying code and the basic design is done, I guess.

The Dashboard

LRBS_Excel_190613

The Code

The code below implements a timer – showing the current time in cell A1.

Pushing the start button fires StartBtn_Click, which reads our run variables into an array, and starts the timer.
StopBtn_Click stops the timer.
Then there is next_tick which checks our array of times against the current time. If it takes longer than a second to parse the array I suppose it’s possible to not fire the code, but I’m only allowing for 14 runs at the moment.

I’ll look to build 10 seconds of tolerance into it at some point, but then it will need to know that it’s executed on the 1st second so as not to try to fire on the 9 subsequent ones. (A “done” flag essentially).


Dim ArrTimes(14)

Dim StopTimer As Boolean
Dim SchdTime As Date
Dim Etime As Date
Const OneSec As Date = 1 / 86400#

Sub StopBtn_Click()
StopTimer = True
Etime = Now
[A1].Value = Time()
End Sub

Sub StartBtn_Click()

StopTimer = False
SchdTime = Now()
[A1].Value = Format(Etime, "hh:mm:ss")
Application.OnTime SchdTime + OneSec, "Sheet1.NextTick"

For i = 0 To 13
RangeObject = "D" & i + 6
If Range(RangeObject).Value <> "" Then
ArrTimes(i) = Range(RangeObject).Value
End If

Next i

End Sub

Sub NextTick()
If StopTimer Then
'Don't reschedule update
Else
[A1].Value = Format(Etime, "hh:mm:ss")
SchdTime = SchdTime + OneSec
Application.OnTime SchdTime, "Sheet1.NextTick"
Etime = Now + OneSec

For i = 0 To UBound(ArrTimes)
If [A1].Value = ArrTimes(i) Then
Application.StatusBar = "Running test id: " & Range("A" & i + 6).Value

End If
Next i
End If

End Sub

I should add by way of a disclaimer, I have absolutely no idea if this is going to work at all, let alone reliably, at this point. But It’s a promising start in my opinion. Oh, and I do indent my code in the IDE, but WordPress or this theme, wipe that out. My code is pretty, honestly.

Loadrunner misses extra resources

Recently, I’ve encountered an issue with an AUT where it crashes VUgen during the generation stage of a recording session. Now I’m a big fan of record-edit-playback. I find the recording and generation logs hugely useful and I find that recording is the easiest and quickest way to get a view of the application.
I call it record-edit-playback because the recording isn’t enough on it’s own for me to use as a performing performance test. But as a foundation, it’s fine. And they rarely playback immediately in any case. Session ID’s are designed to prevent that kind of thing.

The logs in particular are great for helping you find and construct parameter-capturing code for session ids, and identifying user variables that you may want to emulate.

My process for recording is very simple though I haven’t documented it here before so I will now:

  • Record the script once
  • Save it as Scriptname_DATE_RAW
  • Save it again as Scriptname_DATE_WIP (work in progress).

That means you can always roll back if you need to. The WIP copy is the working document until it’s finished when it becomes Scriptname_DATE_FINAL. At that point I hive it off to the controller as well as my local repository. I don’t like cluttering up the controller with WIP versions. And I don’t like the controller pulling scripts across the network, I just think it’s poor practice.

But I digress.

As a solution to the fact I couldn’t record the script, I used Fiddler as a proxy to capture the urls I visited when manually executing the script in Firefox. Over on the DevDiary there’s an article about this, but the point I wanted to make was this. Loadrunner doesn’t capture everything that’s on a page. Fiddler output was about 40 lines for the homepage, a Loadrunner visit to just the homepage was capturing 10 lines of resources (I managed to get LR to do that before it died again).

It seems that if a resource (for example a .css) contains sub-resources Fiddler will see that but Loadrunner won’t. I don’t know if that is by accident or design. I don’t know if it’s implied that LR is geettng them but not explicit in the results and the logs. I intend to find out in due course but it makes me wonder how I’ve not seen this before in 15 years of performance testing. Maybe it’s specific to this project, I could believe that, we are uniquely complicated from what I’ve seen. But what if it’s not. How many issues could have been avoided if I’d seen a bottleneck on one of those resources – maybe an underperforming java-script for example? It’s all academic now anyway but it’s certainly something I’ll look out for in the future. And as an aside, maybe Loadrunners recording engine isn’t as good as I’ve always thought it to be? Interesting times. In Belgium…

Dev Diary

There’s a link to the dev diary over there on the right, currently amongst the links to hosts and wordpress themes. I’ll be adding more relevant content as I find it.

I’ve added a few days of diary regarding test stubs, vbs and vb6. It’s coming along nicely.

The dev diary will be much more informal that the main AS.Org site, this one is going to remain as my more professional aspect.

UPDATE:

The first working version of the Loadrunner Batch Schedule (Excel version) is now available on Dev.

Loadrunner to interact with a VB6 Application as a test stub

So, following on from the previous article / rant…

I managed to re-build the excel spreadsheet & macro functionality within VB6. I’d provide more details but it’s largely bespoke and unlikely to aid anyone, including me, in the future.

The app makes a call to openssl in order to generate, encrypt and/or decrypt a user certificate.
It’s all called from the command line, and that was interesting to build and a pain to test.

In any case, for reference, to build an application in VB6 without any forms:

Go to project properties (for the entire project, not just a module) and select startup object as a sub – in my case SUB MAIN.

Define SUB MAIN as a standard module and either call all your code within it, or add you code within it directly.


Public Sub Main()

'Store command line arguments in this array
Dim sArgs() As String
Dim iLoop As Integer

'Assuming that the arguments passed from
'command line will have space in between,
'you can also use comma or otehr things...
sArgs = Split(Command$, " ")
For iLoop = 0 To UBound(sArgs)
'this will print the command line
'arguments that are passed from the command line
'MsgBox iLoop & "-" & sArgs(iLoop)
Next

'This is an example of the call, vb'd for testing
'Call MobileLogon("ECEEEJBUHEJUASDMCTBUFSFBEPIVEGAYDCFSDRAD", "pO5uDaWU", "C:\Temp\0057525949_____________UDID__EXCEL__TEST_MattLea0101.pem", "0057525949")

'This is the real thing.
Call MobileLogon(sArgs(0), sArgs(1), sArgs(2), sArgs(3))

End Sub

Testing is a pain because once you’ve made the executable, it only accepts the command line variables passed in (sArgs). So you end up putting a duplicated call in with hard-coded values – like the above.
And then you forget, make the executable and run it. It works – of course – because it’s using the hard coded variables.
And then you have to fire up the IDE, fix it, recompile, rebuild and retest.

And if you’re using loadrunner and the system command to test this, it can take a while:

The call:

strcpy(commandstring, lr_eval_string("C:\\Matt\\TestStubATE{vUserID}.exe "));
strcat(commandstring, lr_eval_string(" {sessionId}"));
strcat(commandstring, lr_eval_string(" {randomSalt}"));
strcat(commandstring, lr_eval_string(" {path_to_certificate}"));
strcat(commandstring, lr_eval_string(" {IngID}"));

lr_log_message(commandstring);

rc = system(commandstring);

This particular script uses a certificate generated by OpenSSL from Loadrunner. Only the certificate was missing a newline / carriage return, line feed. Easy enough to fix in code I thought. Well in C in Loadrunner it was a pain – seriously I spend half my life battling with string manipulations in C, why isn’t there a mid function, an instring, a substring function etc? And don’t get me started with StrTok.
So I built that in VBS:


Const ForReading=1
Const ForWriting=2

Set args = Wscript.Arguments 'Command line arguments

For Each arg In args
' Wscript.Echo arg 'For debugging
strFile = arg
Next

' Call edit_pem_file_workaround("0057525949_____________UDID__EXCEL__TEST_MattLea0101.pem")

Set objFSO = CreateObject("Scripting.FileSystemObject")
' folder = "c:\temp\"
'strFile = "0057525949_____________UDID__EXCEL__TEST_MattLea0101.pem"

filePath = strFile

Set myFile = objFSO.OpenTextFile(filePath, ForReading, True)
Set myTemp= objFSO.OpenTextFile(filePath & ".tmp", ForWriting, True)

Do While Not myFile.AtEndofStream
myLine = myFile.ReadLine

If InStr(myLine, "DEK-Info:") Then
myLine = myLine & vbCrLf
End If

myTemp.WriteLine myLine
Loop
myFile.Close
myTemp.Close
objFSO.DeleteFile(filePath)
objFSO.MoveFile filePath&".tmp", filePath


It looks for a line with DEK-Info on it and appends a new line onto it.
LR calls that in much the same way:

strcpy(commandstring, "C:\\Matt\\TestStub_Repo\\EditPemFile.vbs ");
strcat(commandstring, buffer);
system(commandstring);

Buffer contains the path to the certificate file.

So 2 test stubs to workaround issues identified, no great problem there. Except the vb6 one is an executable, and I have no idea how threadsafe or reliable that’s going to be. It’s command line only so the memory and cpu footprint is minimal but better safe than sorry. Especially when performance testing so I created another VBS to copy the teststubAte executable and rename it an teststubAteN.exe where N will represent the vUser ID within the injector.
I find out tomorrow if that works when my POC for this project is built.

Is it sad that I’ve enjoyed the complexity of all this? It’s not. Is it going to be annoying when someone tells me it was all unnecessary, that I could have done it another better way. Well, yes, it will be. IF it happens.