Seamless Migration from Micro Focus UFT to Rapise (Part 2)

November 4th, 2019 by Adam Sandman

software development

Many organizations are looking to update their software testing processes and tools, with an industry-wide move away from some of the older, monolithic legacy suites from vendors such as Micro Focus (formerly HP, and Mercury Interactive before that) to more modern tools. This second article in the blog series, provides a deeper insight into the new UFT migration and conversion framework that has been developed by Inflectra to help our customers more easily migrate from UFT to Rapise.

In the previous article, we discussed how the migration framework can migrate over each of the following three components of a typical UFT test script:

  1. Object Repository

  2. VBscript to JavaScript

  3. Test Data

In this article we get into the nuts and bolts of how the convertor actually does its magic.

Conversion

The converter is taking a .vbs file as the input and produces an equivalent .js script.

The converter is configurable through a rules file. Each rule defines the source and target conversion patterns. The converter patterns are defined in the .md files and more may be added to configure particular project translations.

Default rules already built into the converter cover general language constructs and are sufficient for basic scripts. You may define more complex patterns to cover expressions and statements that needs more high level conversions.

I.e. the pattern matcher may catch both:

WpfWindow(<wnd:literal>).<objType:idName>(<obj:literal>).<method:idName> <argsCall>

Then the matched pattern can be used to generate the appropriate JavaScript:

SeS(<wnd>+"_<objType>_"+<obj>).Do<method>(<argsCall>)

In this case objType:idName is matching any List, Button, etc. while the 1st call should still be WpfWindow.

Exceptions

VBScript has two unique language features that have no direct mapping to JavaScript, i.e.:

On Error GoTo 0
On Error Resume Next 

These constructs are marked in output .js files as comments, i.e.:

// On ErrorGoTo0
// On ErrorResumeNext 

It is recommended to go through such generated code and fix the actual lines that may produce exceptions, i.e.:

On Error Resume Next
fso.CreateFolder "C:\Temp"
fso.DeleteFile "C:\Temp\ExcelExamples.xls"
... 

In this example each line may throw an exception and we need to proceed to the execution of the next line. So we need to wrap it like that:

try{ fso.CreateFolder("C:\\Temp"); }catch(_ex_){}
try{ fso.DeleteFile("C:\\Temp\\ExcelExamples.xls"); }catch(_ex_){} 

Method vs Property

a = File.ReadLine

Gets converted to:

a = File.ReadLine;

Although it is a method, and JavaScript requires calling it as a method. The fix is to either change it in source VBScript to an equivalent form:

a = File.ReadLine()

Or fix it directly in JavaScript:

a = File.ReadLine();

Loop Step

Standard For-Next loop:

For Ind = 1 to 20
...
Next 

Gets converted to:

for(var Ind=0;Ind<=20;Ind++)
{
  ...
}

However, if loop parameters are not known in the beginning, we cannot say if the loop end condition is <= or >= because it depends on which of From or To is bigger. Similarly, we don't know the loop step when it is not specified, because we don't know if it is ascending or descending. So in the case when From and To are not known at the same time, we use the built-in functions LoopCond and LoopStep to find it in the runtime:

For Ind = Start to Top
...
Next Ind 
for (var Ind = Start; LoopCond(Ind, Start, Top); Ind = LoopStep(Ind, Start, Top))
{
...
} 

If you want the generated code to be more clear, you will need to provide a hint to converter by adding a Step:

For Ind = Start to Top Step 1
...
Next Ind 

Array Iterator

In VBScript you may go through the array elements using For Each as follows:

For Each El in ArrayValues
  ...
Next 

The trick here is that the equivalent construction in JavaScript behaves differently. While in VBScript it goes through array values, in JavaScript it goes through indices. So we use a slightly modified construction involving MakeForEachSet function to use the values instead.

for(var el in MakeForEachSet(ArrayValues))
{
  ...
} 

ByRef

VBScript has ByRef feature for making writeable function params:

Function GetNextToken (ByRef sFormat, realVal)
  GetNextToken = "Old Value: " & sFormat
  sFormat = sFormat & realVal
End Function

Dim nt, fmt
fmt = "SB"
nt = GetNextToken( fmt, nt ) 

Such parameters converts to a bit cumbersome but correct construct using _byref_ variable at the function call and refArgs single object argument inside the function:

function GetNextToken(refArgs)
{
  refArgs.fnResult = "";
  refArgs.fnResult = "Old Value: " + refArgs.sFormat;
  refArgs.sFormat = refArgs.sFormat + refArgs.realVal;
  return refArgs
}

var nt, fmt;
fmt = "SB";
nt = (_byref_ = GetNextToken(
{
  sFormat: fmt,
  realVal: nt }), fmt = _byref_.sFormat, _byref_.fnResult); 

Default Value (Cell)

Here is a snippet accessing and comparing Excel cells:

Value1 = sheet1.Cells(r, c)
Value2 = sheet2.Cells(r, c)
If Value1 <> Value2 Then
  ...
End If 

This snippet gets translated to:

Value1 = sheet1.Cells(r, c);
Value2 = sheet2.Cells(r, c);

if( Value1 != Value2 )
{
  ...
} 

Which looks similar, but works differently from the VBScript part. This is because the VBScript default behavior when doing a comparison is to compare by value. I.e. it actually works as follows:

...
If Value1.Value <> Value2.Value
...
End If 

VBScript runtime checks the presence of of the default value in the given cell, and uses it for comparison. While JavaScript has no such built in logic, so the correct equivalent of the given code is the following:

...
if( Value1.Value != Value2.Value)
{
  ...
} 

Function Return Value

A VBScript function return value is assigned as follows:

Function GetNextValue
  GetNextValue = LastValue + 1
End Function 

So the function statement, when used inside function body works as variable holding return value. Since JavaScript holds functions as variables, assigning something to GetNextValue would hide the function definition.

So the converter replaces each occurrence of a function name with local variable fnResult.

One more feature of VB is that the function return value is assumed to be defined. To ensure maximum compatibility we also assign fnResult to default value "" (empty string).

Each time there is an Exit Function statement, the converter inserts return fnResult; :

function GetNextValue()
{
  var fnResult = "";
  fnResult = LastValue + 1;
  return fnResult;
} 

Built In Functions

VBScript has plenty of built in functions Len, Mid, InStr, CStr, MsgBox, and so on.

Some of these functions define built it constants, such as vbTab, vbRed, vbTextCompare.

A full list of functions, constants and keywords is available, for example, here: https://ss64.com/vb/

We define a supplementary file VBSFunctions.js that contains definitions of all builtin functions and should be included before running any converted .js file.

Next Steps

If you are interested in having a consultation from our engagement specialists regarding how you can migrate from UFT to Rapise, please contact us today to get more information and setup a consultation.

Spira Helps You Deliver Quality Software, Faster and with Lower Risk.

Get Started with Spira for Free

And if you have any questions, please email or call us at +1 (202) 558-6885

Free Trial