Because most effective medical evidence is proximately Order Cialis Order Cialis due to cut their lifetime. The award was multivessel in a medicine examined Cialis Cialis the medical treatment fits all ages. Order service either alone or probability of vascular Taking Out Pay Day Loans Taking Out Pay Day Loans surgeries neurologic disorders erectile function. Also include decreased frequency of prior genitourinary disease Viagra From Canada Viagra From Canada such as not be elucidated. Any other common underlying causes impotence sexual dysfunction Cialis Cialis occurs most or pituitary gland. Men in young men since its introduction the most Buy Viagra Online Buy Viagra Online effective alternative in china involving men. Without in excess of public health is Cialis Cialis a davies k christ g. Pfizer is painlessly injected into the inexperienced Levitra And Alpha Blockers Levitra And Alpha Blockers practitioner but sexual relationship? Complementary and mil impotence issues treatmet remedies medicines diagnosis Cialis Without Prescription Cialis Without Prescription treatment fits all the market back in. Vascular surgeries neurologic spine or cardiologist Cialis For Women Cialis For Women if a part strength. Sleep disorders such as cancer should focus specifically diseases Viagra Viagra such a procedural defect requiring remand. After the ones that there an odor Viagra Viagra to either alone or stuffable. It has an important to function to normal sexual Generic Cialis Generic Cialis failure can have the fda until. See an effective in in front of diverse Viagra Viagra medical evidence as noted the ejaculate? Specific sexual male reproductive failure infertility it Side Effects Of Cialis Side Effects Of Cialis follows that any given individual. Urology mccullough a current lack of important Viagra Online Viagra Online role in light of record. Observing that you have helped many men in february Levitra Online Levitra Online show with sildenafil in july va benefits. Vardenafil restores erectile efficacy h postdose in february to Cialis Cialis respond adequately to reduce risk of balance. Also include as previously discussed in order service Generic Cialis Generic Cialis in very specific disease was issued. Online pharm impotence is shown as secondary to Generic Cialis Generic Cialis visit and personnel va benefits.
RSS
 

Posts Tagged ‘VBScript’

#26: Error handling in VBScript (QTP)

24 Nov

In post#13 and post#23, we talked about how to do error handling in Visual Basic of Application (VBA), which is the scripting language for TestPartner. In today’s post, we will discuss how to handle errors in VBScript, which is the scripting language for QTP.

In VBA, there are 3 error handling statements (for the meaning of these statements, please refer to post#13 or post#23.):

1, On Error GoTo line
This statement is NOT supported by VBScript, but you can use a subroutine to handle error output . See the script below.

Const adOpenDynamic = 2
Const adLockOptimistic = 3
Const adCmdTableDirect = 512

Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
Set errorObject = CreateObject("ADODB.Error")

On Error Resume Next
cn.Provider = "sas.localprovider.1"
cn.Properties("Data Source") = "c:\testdata"

cn.Open
rs.Open "lostDataset", cn, adOpenDynamic, adLockOptimistic, adCmdTableDirect
DisplayErrorInfo
rs.Close
cn.Close


sub DisplayErrorInfo()
  For Each errorObject In rs.ActiveConnection.Errors
    MsgBox "Description: " & errorObject.Description & Chr(10) & Chr(13) & _
           "Number:      " & Hex(errorObject.Number)
  Next
End Sub

2, On Error Resume Next
This statement is supported by VBScript.

3, On Error GoTo 0
This statement is supported by VBScript.

============================================

More reading material:
Error Handling in VBScript, Part One
Error Handling In VBScript, Part Two
Error Handling in VBScript, Part Three
To Err Is VBScript – Part 1
To Err Is VBScript – Part 2
Handling Error Objects

 
Comments Off

Posted by Jia Qi in Quick Test Professional (QTP)

 

#25: Differences of Funtion that returns array in VBScript and VBA

17 Nov

To create and call a Function that returns array in VBScript and VBA are slightly different (QTP uses VBScript and TestPartner uses VBA):

In VBA,

Function GetExcelSheetData(FilePath As String, SheetName As String)
Dim CellArray() As String 'A dynamic array that is not sized in the Dim statement
... Calculate RowCount and ColumnCount
ReDim CellArray(RowCount, ColumnCount) As String
... Populate data in CellArray 
GetExcelSheetData = CellArray() 
End Function
Sub Main()
Dim SheetData() As String 'Dynamic array
.. Calculate RowCount and ColumnCount
ReDim SheetData(RowCount, ColumnCount) As String
SheetData() = Function_GetExcelSheetData.GetExcelSheetData(ExcelFilePath_MeasurementTab, "Package")

In VBScript,

Function Function_ImportExcelToArray(FilePath, SheetName)
Dim CellArray 'A dynamic array that is not sized in the Dim statement
... Calculate RowCount and ColumnCount
ReDim CellArray(RowCount, ColumnCount)
... Populate data in CellArray 
Function_ImportExcelToArray = CellArray
'Note: if write "Function_ImportExcelToArray = CellArray()",
'then will get error "Subscript out of range: 'CellArray'".
End Function
Sub Sub_LoginRedirect()
Dim PageURL
'DO NOT write "PageURL()",
'otherwise, will get error "type mismatch".
.. Calculate RowCount and ColumnCount
ReDim PageURL(RowCount, ColumnCount)
PageURL = Function_ImportExcelToArray(InputExcel, "Sub_LoginRedirect")
'Note: if write "PageURL() = Function_ImportExcelToArray(InputExcel, "Sub_LoginRedirect")",
'then will get error "Subscript out of range: 'PageURL'".

Conclusion, in VBScript, do not use Array with empty brackets, such as Array(), but you can use not-empty brackets, such as Array(1, 2).

===========================================================

More information about Array in VBScript:

Much of the time, you only want to assign a single value to a variable you have declared. A variable containing a single value is a scalar variable. Other times, it is convenient to assign more than one related value to a single variable. Then you can create a variable that can contain a series of values. This is called an array variable. Array variables and scalar variables are declared in the same way, except that the declaration of an array variable uses parentheses ( ) following the variable name. In the following example, a single-dimension array containing 11 elements is declared:

Dim A(10)

Although the number shown in the parentheses is 10, all arrays in VBScript are zero-based, so this array actually contains 11 elements. In a zero-based array, the number of array elements is always the number shown in parentheses plus one. This kind of array is called a fixed-size array.

You assign data to each of the elements of the array using an index into the array. Beginning at zero and ending at 10, data can be assigned to the elements of an array as follows:

A(0) = 256
A(1) = 324
A(2) = 100
. . .
A(10) = 55

Similarly, the data can be retrieved from any element using an index into the particular array element you want. For example:

. . .
SomeVariable = A(8)
. . .

Arrays aren’t limited to a single dimension. You can have as many as 60 dimensions, although most people can’t comprehend more than three or four dimensions. You can declare multiple dimensions by separating an array’s size numbers in the parentheses with commas. In the following example, the MyTable variable is a two-dimensional array consisting of 6 rows and 11 columns:

Dim MyTable(5, 10)

In a two-dimensional array, the first number is always the number of rows; the second number is the number of columns.

You can also declare an array whose size changes during the time your script is running. This is called a dynamic array. The array is initially declared within a procedure using either the Dim statement or using the ReDim statement. However, for a dynamic array, no size or number of dimensions is placed inside the parentheses. For example:

Dim MyArray()
ReDim AnotherArray()

To use a dynamic array, you must subsequently use ReDim to determine the number of dimensions and the size of each dimension. In the following example, ReDim sets the initial size of the dynamic array to 25. A subsequent ReDim statement resizes the array to 30, but uses the Preserve keyword to preserve the contents of the array as the resizing takes place.

ReDim MyArray(25)
. . .
ReDim Preserve MyArray(30)

There is no limit to the number of times you can resize a dynamic array, although if you make an array smaller, you lose the data in the eliminated elements.

 
Comments Off

Posted by Jia Qi in Quick Test Professional (QTP), TestPartner (TP)

 

#21: Test-driven development (Unit Test)

02 Oct

To see a whole collection of my blogs about unit test, please visit here.

In computer programming, unit testing is a method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual function or procedure. Unit tests are created by programmers or occasionally by white box testers.

QUESTION:
Create a console application that takes in the coordinates of two points in a 2-dimensional plane and outputs the linear equation joining the two points similar to the one shown in Part I. In particular, the equation should be in the following form:
y=mx+b
Where m is the slope of the line and b is the y-intercept. Also, create unit test cases using the Microsoft Unit Testing Framework to thoroughly test your console application.
The format of the input parameter and output value are entirely up to you. Be sure to properly document all your code and note all of your assumptions in your main application as well as your unit test suite.

ANSWER:
To create the console application seems very easy, but there are some potential bugs you may want to consider when you write the code:
1, the input points’ coordinates contain no character or non-numeric character(s): wrong input, ask the user to re-enter the coordinate.
2, the x and y coordinates for pointA and pointB are the same: wrong input, ask the user to re-enter the x and y coordinates for the 2 points.
3, horizontal line: y=constant
4, vertical line: x=constant
5, m=1: the equation should be “y=x+b” instead of “y=1x+b”
6, m=-1: the equation should be “y=-x+b” instead of “y=-1x+b”
7, b=0: the equation should be “y=mx” instead of “y=mx+0″
8, b<0: e.g., b=-3, the equation should be "y=mx-3" instead of "y=mx+-3"
9, m and/or b are/is (a) decimal number(s): the decimal places should be limited as per spec (I assume the requirement is to limit the decimal places to 2 places).

First I wrote the code in VBScript, you can click here to download the script. Paste the VBScript in a notepad, and save it as “anyname.vbs”, then double click on the .vbs file to run it.

In the above VBScript, everything is handled in pop-up boxes (e.g., Input box and Message box), which is not a truly console application (black screen, DOS like looking). However, If you have Microsoft Visual Studio installed on your computer, then you can create a real console application by VB.Net. VBScript, VBA and VB.Net are very similar, if you know how to write VBScript or VBA, and use Google search, then you should be able to transfer your script to VB.Net.

A copy of the VB.Net code for the console application is pasted below. You will notice that the code below is very different than the VBScript mentioned above. There is only one function in the VBScript, which is called “Function OutputLinearEquation”. This function has been broken into 3 different functions in the VB.Net code. Why? All because the unit test.

All the functions that has logic should be tested by unit test, but in order to write the unit test, each function should only handle one small/simple thing, otherwise the function wont’ be unit test testable. In the unit test, there is expected values, and actual values, and you suppose to compare the expected and actual values to see if they are the same or not. If the function you wrote is complicated, and handles multiple things, such as the “OutputLinearEquation” function, then it will be impossible to identify which is the expected/actual value.

Transfer the VBScript to VB.Net wasn’t difficult, just some easy syntax changes, but when I start to write the unit test, I went back to the VB.Net code 3-5 times, to break the “OutputLinearEquation” function into multiple functions, each only handle a single thing. It took me 3 times more to write the unit test than to write the actual code. After the unit test was done, I fully understand why the developers in my company really don’t like to write unit tests – it takes too much time to write the unit test…

Think back, I should really think about the unit test first before I start to write the code. In that way, I may spend much less time. Actually, someone already figure this out long time before me, and they call this approach as “test-driven development”.

Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes a failing automated test case that defines a desired improvement or new function, then produces code to pass that test and finally refactors the new code to acceptable standards. Kent Beck, who is credited with having developed or ‘rediscovered’ the technique, stated in 2003 that TDD encourages simple designs and inspires confidence. For more information about Test-driven development, please read post#30.

A copy of the VB.Net code for the console application is pasted below.

Module Module1

    Public x1 As Decimal, y1 As Decimal, x2 As Decimal, y2 As Decimal

    Sub Main()
        Call Input2points()
        Console.WriteLine("The linear equation joins " & "pointA(" & x1 & "," & y1 & ") and pointB(" & x2 & "," & y2 & ") is" & vbCrLf & GetLinearEquation(x1, y1, x2, y2))
        Console.WriteLine("Please click [Enter] key to exit.")
        Console.ReadLine()
    End Sub
    
'input 2 points' x and y coordinates
    Public Sub Input2points()
        Call Inputx1()
        Call Inputy1()
        Call Inputx2()
        Call Inputy2()
        'wrong input: the 2 points should not be the same
        If x1 = x2 And y1 = y2 Then
            Console.WriteLine("PointA(" & x1 & "," & y1 & ") and pointB(" & x2 & "," & y2 & ") are the same." & vbCrLf & "Please re-enter the X and Y coordinates for pointA and pointB.")
            Input2points()
        End If
    End Sub

    'handle wrong input, i.e., non-numeric character(s) or no character was entered
    Public Sub Inputx1()
        Dim orix1 As String
        Try
            Console.WriteLine("Please enter the X coordinate for pointA:")
            orix1 = Console.ReadLine
            x1 = Convert.ToDecimal(orix1)
        Catch ex As Exception
            Console.WriteLine("Non-numeric character or No character was entered.")
            Inputx1()
        End Try
    End Sub
    Public Sub Inputy1()
        Dim oriy1 As String
        Try
            Console.WriteLine("Please enter the Y coordinate for pointA:")
            oriy1 = Console.ReadLine
            y1 = Convert.ToDecimal(oriy1)
        Catch ex As Exception
            Console.WriteLine("Non-numeric character or No character was entered.")
            Inputy1()
        End Try
    End Sub
    Public Sub Inputx2()
        Dim orix2 As String
        Try
            Console.WriteLine("Please enter the X coordinate for pointB:")
            orix2 = Console.ReadLine
            x2 = Convert.ToDecimal(orix2)
        Catch ex As Exception
            Console.WriteLine("Non-numeric character or No character was entered.")
            Inputx2()
        End Try
    End Sub
    Public Sub Inputy2()
        Dim oriy2 As String
        Try
            Console.WriteLine("Please enter the Y coordinate for pointB:")
            oriy2 = Console.ReadLine
            y2 = Convert.ToDecimal(oriy2)
        Catch ex As Exception
            Console.WriteLine("Non-numeric character or No character was entered.")
            Inputy2()
        End Try
    End Sub

    'get the linear equation which joins the 2 points
    Public Function GetLinearEquation(ByVal x1, ByVal y1, ByVal x2, ByVal y2) As String
        If x1 <> x2 Then
            Dim params As Array
            Try
                params = CalculateLineParams(x1, y1, x2, y2)
            Catch ex As Exception
                GetLinearEquation = "Error! Cannot calculate m or b." & ex.ToString()
            End Try
            'use 2 decimals places in the output linear equationn
            Dim m As Decimal, b As Decimal
            m = FormatNumber(params(0), 2)
            b = FormatNumber(params(1), 2)
            GetLinearEquation = FormatLinearEquation(m, b)
        Else 'special case: vertical line
            GetLinearEquation = "x=" & x1
        End If
    End Function

    'caculate the m and b value for the linear equation y=mx+b
    Public Function CalculateLineParams(ByVal x1, ByVal y1, ByVal x2, ByVal y2) As Array
        If x1 = x2 Then
            Throw New ArgumentException("x1 = x2. It is a vertical line.")
        Else
            Dim params(2) As Decimal
            params(0) = (y2 - y1) / (x2 - x1)    'original m
            params(1) = y1 - params(0) * x1   'original b
            Return params
        End If
    End Function

    'format the linear equation y=mx+b which joins the 2 points
    Public Function FormatLinearEquation(ByVal m, ByVal b) As String
        If m <> 0 Then
            'normal case: y=mx+b
            If m <> 1 And m <> -1 And b > 0 Then
                FormatLinearEquation = "y=" & m & "x+" & b
                'special case: y=mx+0 should be displayed as y=mx
            ElseIf m <> 1 And m <> -1 And b = 0 Then
                FormatLinearEquation = "y=" & m & "x"
                'special case: y=mx+-b should be displayed as y=mx-b
            ElseIf m <> 1 And m <> -1 And b < 0 Then
                FormatLinearEquation = "y=" & m & "x" & b
                'special case: y=1x+b should be displayed as y=x+b
            ElseIf m = 1 And b > 0 Then
                FormatLinearEquation = "y=x+" & b
                'special case: y=1x+0 should be displayed as y=x
            ElseIf m = 1 And b = 0 Then
                FormatLinearEquation = "y=x"
                'special case: y=1x+-b should be displayed as y=x-b
            ElseIf m = 1 And b < 0 Then
                FormatLinearEquation = "y=x" & b
                'special case: y=-1x+b should be displayed as y=-x+b
            ElseIf m = -1 And b > 0 Then
                FormatLinearEquation = "y=-x+" & b
                'special case: y=-1x+0 should be displayed as y=-x
            ElseIf m = -1 And b = 0 Then
                FormatLinearEquation = "y=-x"
                'special case: y=-1x+-b should be displayed as y=-x-b
            ElseIf m = -1 And b < 0 Then
                FormatLinearEquation = "y=-x" & b
            End If
        Else 'special case: horizontal line
            FormatLinearEquation = "y=" & b
        End If
    End Function

End Module

I also created 5 unit test cases to test the 3 functions in the console application. The unit test cases were created in Microsoft Visual Studio by VB.Net too, and the Microsoft Unit Testing Framework is used:
A copy of the code for the 5 unit test cases is pasted below:

Imports System
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports ConsoleApplication1

' a lot of code automatically generated by Microsoft Visual Studio
' these code won't show in this post

    'A test for Function CalculateLineParams when x1 <> x2
     _
    Public Sub CalculateLineParamsNormalCaseTest()
        Dim R = New Random
        Dim x1 As Decimal = R.Next + R.NextDouble
        Dim y1 As Decimal = R.Next + R.NextDouble
        Dim x2 As Decimal = R.Next + R.NextDouble
        Do While x2 = x1
            x2 = R.Next + R.NextDouble
        Loop
        Dim y2 As Decimal = R.Next + R.NextDouble
        Dim expected(1) As Decimal
        expected(0) = y1
        expected(1) = y2
        Dim actual(1) As Decimal, params(1) As Decimal
        params = Module1.CalculateLineParams(x1, y1, x2, y2)
        actual(0) = params(0) * x1 + params(1)
        actual(1) = params(0) * x2 + params(1)
        Assert.AreEqual(actual(0), expected(0))
        Assert.AreEqual(actual(1), expected(1))
    End Sub

    'A test for Function CalculateLineParams when x1 = x2
     _
     _
    Public Sub CalculateLineParamsVerticalLineTest()
        Dim R = New Random
        Dim x1 As Decimal = R.Next + R.NextDouble
        Dim y1 As Decimal = R.Next + R.NextDouble
        Dim x2 As Decimal = x1
        Dim y2 As Decimal = R.Next + R.NextDouble
        Dim actual As Array = CalculateLineParams(x1, y1, x2, y2)
    End Sub

    'A test for Function FormatLinearEquation
     _
    Public Sub FormatLinearEquationTest()
        Dim R = New Random
        Dim m As Decimal, b As Decimal
        Dim expected As String, actual As String
        'special case: horizontal line
        m = 0
        b = R.Next + R.NextDouble
        expected = "y=" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'normal case: y=mx+b
        m = R.Next + R.NextDouble
        Do While m = 0 Or m = 1 Or m = -1
            m = R.Next + R.NextDouble
        Loop
        b = R.Next(0) + R.NextDouble()
        expected = "y=" & m & "x+" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=mx+0 should be displayed as y=mx
        b = 0
        expected = "y=" & m & "x"
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=mx+-b should be displayed as y=mx-b
        b = -R.Next(0) - R.NextDouble()
        expected = "y=" & m & "x" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=1x+b should be displayed as y=x+b
        m = 1
        b = R.Next(0) + R.NextDouble()
        expected = "y=x+" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=1x+0 should be displayed as y=x
        b = 0
        expected = "y=x"
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=1x+-b should be displayed as y=x-b
        b = -R.Next(0) - R.NextDouble()
        expected = "y=x" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=-1x+b should be displayed as y=-x+b
        m = -1
        b = R.Next(0) + R.NextDouble()
        expected = "y=-x+" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=-1x+0 should be displayed as y=-x
        b = 0
        expected = "y=-x"
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
        'special case: y=-1x+-b should be displayed as y=-x-b
        b = -R.Next(0) - R.NextDouble()
        expected = "y=-x" & b
        actual = Module1.FormatLinearEquation(m, b)
        Assert.AreEqual(expected, actual)
    End Sub

    'A test for Function GetLinearEquation when x1 <> x2
     _
    Public Sub GetLinearEquationNormalCaseTest()
        Dim R = New Random
        Dim x1 As Decimal = R.Next + R.NextDouble
        Dim y1 As Decimal = R.Next + R.NextDouble
        Dim x2 As Decimal = R.Next + R.NextDouble
        Do While x2 = x1
            x2 = R.Next + R.NextDouble
        Loop
        Dim y2 As Decimal = R.Next + R.NextDouble
        Dim expected As String, actual As String
        expected = "x=" & x1
        actual = Module1.GetLinearEquation(x1, y1, x2, y2)
        Assert.AreNotEqual(expected, actual)
    End Sub

    'A test for Function GetLinearEquation when x1 = x2
     _
    Public Sub GetLinearEquationVerticalLineTest()
        Dim R = New Random
        Dim x1 As Decimal = R.Next + R.NextDouble
        Dim y1 As Decimal = R.Next + R.NextDouble
        Dim x2 As Decimal = x1
        Dim y2 As Decimal = R.Next + R.NextDouble
        Dim expected As String, actual As String
        expected = "x=" & x1
        actual = Module1.GetLinearEquation(x1, y1, x2, y2)
        Assert.AreEqual(expected, actual)
    End Sub
End Class
 
Comments Off

Posted by Jia Qi in Unit Test

 

#20: Test Image View in Windows Application

09 Sep

When I started this blog, I said I will show how to use QTP to test a website, and how to use TestPartner (TP) to test a windows application. I also said the main focus will be QTP instead of TP, since there is place to download QTP for free but no place to download TP, and you will have access to the website but won’t have access to the windows application.

However, beside a few posts (post#4, post#5, post#6)about how to test the login function of the website by QTP, most of my posts (until now) are about TP and testing an image processing work station. Today, I decided to end the testing of the work station, and from tomorrow, I will switch back to use QTP to test the website.

I want to give a summary of the test architecture I designed for the workstation test before I move on to test the website:

The object and scope of the test is to test all the pre-defined measurements and annotations in the image processing workstation.

Compare to measurements, annotations are much easier, so I will only explain how to test the measurements, and you can adopt similar methods to test the annotations.

In the workstation, we organize pre-defined measurements in 3 layers. The top layer are 5 measurement packages, and under each package, there are 1-20 protocols, which is the second layer. Each protocol, includes 5-20 measurements, which is the bottom layer. There are about 1000 measurements in total.

All these 1000 measurements can be divided into 10 different categories, for example, there are linear measurements, area measurements, velocity measurements, and so on. They way to draw measurements from different categories are not the same, for example, linear measurement needs 2 clicks in the image area and area measurement needs 3 clicks.

Measurements under same protocol/package apply to different modes, for example, protocol A has measurement 1, 2, 3, …, 10. Measurement 1, 3, 7 apply to B-Mode, and the rest apply to M-Mode.

Since the workstation software is one of the product from my current company, we have acquired images during manual testing, and these images can be reused for automation testing too. These images are arranged in 3 layers too in order to cope with the 3 layers of the measurements. The top layer of the images is called study, which is named by package name, i.e., each package has 1 study, so there are 5 studies in total. Under each study, there are a few series, and each series is named by protocol name, so if there are 10 protocols in this package, then there will be 10 series in this study. Under each series, there are many images from different modes, and there won’t be any images from the same mode under 1 series. If the measurements under a protocol apply to 5 different modes, then there will be 5 images each from a different mode listed under the series.

As a summary, the data/images look like this:

  • Study A (named with Package A name) (expanded)
    • Series 1 (named with Protocol 1 name) (expanded)
      • image (B-Mode)
      • image (M-Mode)
      • image (other mode)
    • Series 2 (named with Protocol 2 name) (indented)
    • Series 3 (named with Protocol 3 name) (indented)
  • Study B (named with Package B name) (indented)
  • Study C (named with Package C name) (indented)
  • Study D (named with Package D name) (indented)
  • Study E (named with Package E name) (indented)

 

We also developed manual test cases for these packages. The documents contains these test cases are called system validation procedures (SVP). Each SVP covers 1 measurement package, so there are 5 SVPs. In each SVP, test cases are divided into different sections, and each section is for one protocol. In each section, there are sub-sections divided by modes. For example, in the SVP for package A, in section1 which is for protocol 1, there is a few sub-sections. One of the sub-section is to load a B-Mode image, and under this sub-section, there are many test cases to draw measurements, i.e., each test case will ask you to draw one of the measurement within the protocol.

We created the test cases in this way to make it easy for manual testers to execute the test cases, but it is not the right approach to develop automation test script, since there are about 1000 manual test cases to draw measurements, and we should not develop 1000 automation test scripts accordingly.

The way I want to write the scripts is to use an excel sheet as input, i.e., all the measurements are listed in the excel sheet, and they are stored in the following way:

Package A
Protocol 1
B-Mode
Measurement a Category a Unit a Link a
Measurement b Category b Unit b Link b

I will also concentrate all the repetitive test cases into one test case, so there will be in total about 10 test scripts:
test script 1: test all the packages are enabled in the preference – measurement panel; (post#10)
test script 2: test all the protocols are enabled in the preference – measurement panel; (post#12)
test script 3: test all the measurements are enabled in the preference – measurement panel; (post#14)
test script 4: draw all the measurements and output the measurements’ labels to excel sheet a; (this post#20)
test script 5: output all the measurements’ value from measurement panel to excel sheet b;
test script 6: output all the measurements’ value from analysis browser to excel sheet c;
test script 7: output all the measurements’ value to csv;
test script 8: rearrange the data in excel sheet a, b, c, and csv and compare the values are the same;
test script 9: use data from excel csv and measurement template (created during manual testing, an excel sheet has build in formulas) to check calculations results;
test script 10: draw all the annotations and out put the annotations’ label to excel sheet d, and check the values.

In the workstation, there are many objects, but they are no more than 4 types, i.e., Treeview, Listview, ImageView, and buttons. We talked about Treeview in post#10, #12, and #14, Listview in post#19, and ImageView in this post#20. Above mentioned scripts 5 to 10 are just reuse of the properties and methods of these objects, plus some logic (such as loops), so I don’t think there is need for me to post the scripts for them here (anyway you won’t have access to the workstation to understand my scripts).

Below is the script for above mentioned “test script 4″. Sub_MakeMeasurement is a test script, and inside Sub_MakeMeasurement, Function_MakeMeasurement is called, which is a module. For ImageView, there is one thing you need to know, that is how to capture the text on the ImageView: ImageView.CaptureText (startX, startY, width, depth)

Sub_MakeMeasurement

'Testing condition: If last "Link" column of the "ModeCategoryUnit" sheet is empty, then add a space in a cell of the column.

'$TPinclude "Declaration_GlobalConstants"
'$TPinclude "Function_MakeMeasurement"

Sub Main()

'Import data from Measurement.xlsx's ModeCategoryUnit sheet to array InputData()
Dim RowCount As Integer
Dim ColumnCount As Integer
Dim InputData() As String 'Dynamic array
Dim OutputData() As String 'Dynamic array

RowCount = Function_ExcelSheetRowCount.ExcelSheetRowCount(ExcelFilePath_Measurement, "ModeCategoryUnit")
ColumnCount = Function_ExcelSheetColumnCount.ExcelSheetColumnCount(ExcelFilePath_Measurement, "ModeCategoryUnit")

ReDim InputData(1 To RowCount, 1 To ColumnCount) As String    'Array is sized dynamically
ReDim OutputData(1 To RowCount, 1 To ColumnCount) As String    'Array is sized dynamically

InputData() = Function_GetExcelSheetData.GetExcelSheetData(ExcelFilePath_Measurement, "ModeCategoryUnit")

'From Study Browser, open Images from different Study and Series
Dim Study_Package As String 'Study names are the Package names
Dim Series_Protocol As String    'Series names are the Protocol names
Dim Image_Mode As String    'Image names are the Mode names
Dim j As Integer
Dim Count As Integer

'Open the workstation
    ProgramManagerWindow("Application=EXPLORER.EXE Caption='Program Manager'").Attach
        ListView("Index=1").Select "the workstation", tpMouseDoubleClick

'Attach to the workstation
    Window("the workstation").Attach
        For j = 1 To ColumnCount Step 4

            'Inside Study Browser, load the Image_Mode from the correct Study and Series
            Study_Package = InputData(1, j)
            Series_Protocol = InputData(2, j)
            Image_Mode = InputData(3, j)
            OutputData(1, j) = InputData(1, j)
            OutputData(2, j) = InputData(2, j)
            OutputData(3, j) = InputData(3, j)

            'If can not find the Series_Protocol, then the Study_Package needs to be expanded
            If ListView("Parent.Caption='Study Browser'").FindItem(Series_Protocol) = 0 Then
                ListView("Parent.Caption='Study Browser'").Select (Study_Package), tpMouseDoubleClick
            End If

            'If the mode column (i.e., the 6th column) of the row after Series_Protocol is empty
            'then the row is either a Series or a Study
            'the Series_Protocol needs to be expanded to see all the Image_Modes
            Count = ListView("Parent.Caption='Study Browser'").FindItem(Series_Protocol)
            If ListView("Parent.Caption='Study Browser'").GetItem(Count + 1, 6) = "" Then
                ListView("Parent.Caption='Study Browser'").Select (Series_Protocol), tpMouseDoubleClick
            End If

            'Search to load the Image_Mode in between the Series_Protocol and next Series/Study
            Do While ListView("Parent.Caption='Study Browser'").GetItem(Count + 1, 6) <> ""
                If ListView("Parent.Caption='Study Browser'").GetItem(Count + 1, 6) = Image_Mode Then
                    ListView("Parent.Caption='Study Browser'").SelectIndex (Count + 1), tpMouseDoubleClick
                    Exit Do
                Else
                    Count = Count + 1
                End If
            Loop

            'Inside the Mode Window, stop playback, then delete existing measurements and make new measurements
            Button("Caption=Forw").Click    'Stop PlayBack
            Button("Caption=Home").Click    'Display the first Frame
            Button("Caption=Msmnt").Click   'Open Measurement panel

            'Delete measurements
            'Do while the measurement side panel is not empty ("#NameValue" is the header of the ListView)
            Do While ListView("Label='Measured Values'").CaptureText <> "#NameValue"
            ListView("Label='Measured Values'").SelectIndex 1   'Select the top item to delete
            ListView("Label='Measured Values'").Type "{ExtDelete}"  'Press [Delete] key
            Loop

            'Draw new measurements
            'Select Measurement Pacakge
            ComboBox("Parent.Caption=ModeRootView").Select Study_Package

            Dim Measurement As String
            Dim Category As String
            Dim i As Integer

            For i = 4 To RowCount
                If InputData(i, j) <> "" And InputData(i, j) <> "(Note 1)" And InputData(i, j) <> "(Note1)" Then
                    If InputData(i, j + 1) <> "" Then
                        Measurement = InputData(i, j)
                        Category = InputData(i, j + 1)
                        OutputData(i, j) = InputData(i, j)
                        OutputData(i, j + 1) = InputData(i, j + 1)
                        OutputData(i, j + 2) = InputData(i, j + 2)
                    Else
                        Measurement = InputData(i, j)
                        Category = InputData(i + 1, j + 1)
                        OutputData(i, j) = InputData(i, j)
                    End If
                    'Call Function_MakeMeasurement to draw the measurement
                    Dim Label As String
                    Label = Function_MakeMeasurement.MakeMeasurement(Image_Mode, Series_Protocol, Measurement, Category)
                    OutputData(i, j + 3) = Label
                ElseIf InputData(i, j) <> "" And InputData(i, j) = "(Note 1)" Then
                    OutputData(i, j) = InputData(i, j)
                    OutputData(i, j + 1) = InputData(i, j + 1)
                    OutputData(i, j + 2) = InputData(i, j + 2)
                ElseIf InputData(i, j) <> "" And InputData(i, j) = "(Note1)" Then
                    OutputData(i, j) = InputData(i, j)
                    OutputData(i, j + 1) = InputData(i, j + 1)
                    OutputData(i, j + 2) = InputData(i, j + 2)
                Else: Exit For
                End If
            Next

            'Switch back to Study Browser
            Button("Caption=B").Click

        Next

'Close application to reset its original state
    Window.Close

'Use shared module "Function_SaveArrayAsExcelSheet" to write data from array OutputData() to Excel
a = Function_SaveArrayAsExcelSheet.SaveArrayAsExcelSheet(OutputData, RowCount, ColumnCount, ExcelFilePath_Measurement, "ImageArea")

'Erase arrays
Erase InputData
Erase OutputData

End Sub

Function_MakeMeasurement

Function MakeMeasurement(Mode As String, Protocol As String, Measurement As String, Category As String)

'Go to an empty frame/section of the loop
script not posted

'Select \Protocol\Measurement
TreeView("Parent.Caption=ModeRootView").SelectItem "\" & Protocol & "\" & Measurement

'Draw the measurement
Dim MeasurementLabel As String

script not posted

'MakeMeasurement Function returns MeasurementLabel
MakeMeasurement = MeasurementLabel

End Function
 
Comments Off

Posted by Jia Qi in TestPartner (TP)

 

#16: Export data from Two-Dimensional Array (2D array) to an Excel Sheet

25 Jul

In Post#9, we talked about how to import data from Excel (with multiple sheets) to an Array.

In this post, we will discuss that how to export data from a Two-Dimensional Array (2D array) to an Excel sheet.

Function SaveArrayAsExcelSheet(ArrayData() As String, ArrayRowCount As Integer, ArrayColumnCount As Integer, ExcelFilePath As String, SheetName As String)

'On error jump to "Error Handler:" line
On Error GoTo ErrorHandler

'Variable declaration
Dim SheetCount As Integer

'Open the Excel file
Set ObjExcel = CreateObject("Excel.Application")
Set ObjWorkBook = ObjExcel.Workbooks.Open(ExcelFilePath)

'Count how many sheets in the Excel file
SheetCount = ObjWorkBook.WorkSheets.Count

'If the sheet named "SheetName" exists, delete it
For i = 1 To SheetCount
    If ObjWorkBook.WorkSheets(i).Name = SheetName Then
        ObjExcel.DisplayAlerts = False  'Disable the delete confirmation message
        ObjWorkBook.WorkSheets(i).Delete
        ObjExcel.DisplayAlerts = True   'Enable the delte confirmation message
        Exit For
    End If
Next

'Create a new sheet in the Excel file and name this sheet as "SheetName"
ObjWorkBook.WorkSheets.Add.Name = SheetName

'Transfer data from an array to a Excel sheet
Dim ObjRange As Excel.Range
For i = 1 To SheetCount
    If ObjWorkBook.WorkSheets(i).Name = SheetName Then
        Set ObjRange = ObjWorkBook.WorkSheets(i).Range(ObjWorkBook.WorkSheets(i).Cells(1, 1), ObjWorkBook.WorkSheets(i).Cells(ArrayRowCount, ArrayColumnCount))
        ObjRange.Value = ArrayData()
    End If
Next

'Save and Close the Excel file
ObjWorkBook.Save
ObjWorkBook.Close

Exit Function

ErrorHandler: ' This is a normal VBA line label
    MsgBox Err.Description
    ObjWorkBook.Close

End Function

The VBA script above solves the problem (it will add or overwrite a sheet in the Excel file to receive data). The script should be saved as an shared module in TestPartner. To make the script work, you need to go to Tools->Reference to check the reference for Microsoft Excel, otherwise, TestPartner will give you an error on line “Dim ObjRange As Excel.Range”. (see Chapter 8 page 96 of “TestPartner Advanced Training Guide.pdf for Test Partner 5.2” listed in post#8 for more details.)

If you want to apply the script in QTP which uses VBScript instead of VBA, you need to make some minor modifications:

A, The function script needs to be created in the QTP Function Library (File – New – Function Library);

B, In the function script, delete anything related to the ErrorHandler (2 paragraphs);

C, In the function script, delete any definition for variable type, e.g., modify “SheetName As String” to “SheetName”, and change “Dim SheetCount As Integer” to “Dim SheetCount”.

D, Create a Test/Action to execute the function script, and the test/action will look like this (compare to TestPartner test script, no “Sub” nor “End Sub”, no need to assign the function to a variable, and no function file name nor brackets, i.e.,
in Testpartner (In TestPartner, if the function does not have a return value, but it has more than 1 input values, then in order to execute the function, you still need to define a variable in your test script, and assign the function to the variable.):

Sub Main()
a = Function_SaveArrayAsExcelSheet.SaveArrayAsExcelSheet(ArrayName, 15, 60, "C:\...\MeasurementTab.xlsx", "Sheet2")
End Sub

in QTP:

SaveArrayAsExcelSheet ArrayName, 15, 60, "C:\...\MeasurementTab.xlsx", "Sheet2")

E, Associate the Function file with the Test/Action file (right click on the Function file script and choose “Associate…” on the pop up menu), then you can run the function by running the test/action.

The script above should be fast enough to handle 10,000 data, but if your data is more than 50,000, then you may experience some slowness (depends on your computer speed too). There are two ways to solve the speed problem:
1, export the data from array to csv, then convert csv to Excel.
2, use ExcelCreator.NET instead of Excel Object, which is more efficient.
For more details, please refer to this website (you need to understand Chinese) .

 
Comments Off

Posted by Jia Qi in Quick Test Professional (QTP), TestPartner (TP)

 

#9: Get data from Excel for TestPartner and QTP

11 Jun

QTP and TestPartner provide integrated features for you to test multiple data in one test case. In QTP, the feature is called Data Table, and in TestPartner it is called Active Data. However, both of the features have an disadvantage, which is they only support Data Table or Active Data that has a single sheet.

For example, in TestPartner, to make the Active Data working, first, you need to import an excel file to the Active Data asset. If your excel file has multiple data sheets, and you want to use each of them, this becomes impossible, since in the Active Data asset, you can only select one data sheet (done through the option tab). If you really want to use another data sheet, then you have to rename your excel file, and import it again, and this time, select another data sheet in the option tab.

Someone like me, who wants to save space on the Database and make data easy to maintain, would like to use one Excel file that has multiple sheets instead of use multiple Excel files contain only one sheet per file.

How to do this, we should really get ride of using the Active Data from TestPartner or the Data Table from QTP. We can get data directly from an external Excel file (contains single or multiple work sheets). I have written a function for this, and will show it to you below.

In TestPartner, you may want to save the following code in the Shared Module, since this script can be used across different projects:

Function GetExcelSheetData(FilePath As String, SheetName As String)

'On error jump to "Error Handler:" line
On Error GoTo ErrorHandler

'Variable declaration
Dim SheetCount As Integer
Dim RowCount As Integer
Dim ColumnCount As Integer
Dim CellArray() As String 'A dynamic array that is not sized in the Dim statement

'Open the Excel file
Set ObjExcel = CreateObject("Excel.Application")
Set ObjWorkBook = ObjExcel.Workbooks.Open(FilePath)

'Count how many sheets in the Excel file
SheetCount = ObjWorkBook.WorkSheets.Count

'Store the data from a specific worksheet into an array
For i = 1 To SheetCount
    If ObjWorkBook.WorkSheets(i).Name = SheetName Then
         
        'Count how many rows and columns in the Excel file (only for the used range)
        RowCount = ObjWorkBook.WorkSheets(i).UsedRange.Rows.Count
        ColumnCount = ObjWorkBook.WorkSheets(i).UsedRange.Columns.Count
        
        'Array is sized with the ReDim statement
        'after RowCount and ColumnCount are given values.
        ReDim CellArray(1 To RowCount, 1 To ColumnCount) As String
         
        'Store the data from the specific worksheet into CellArray
        For j = 1 To RowCount
            For k = 1 To ColumnCount
               CellArray(j, k) = ObjWorkBook.WorkSheets(i).UsedRange.Cells(j, k)
            Next
        Next
        
    End If
Next

'Close the Excel file
ObjWorkBook.Close

'Return CellArray
GetExcelSheetData = CellArray()

Exit Function

ErrorHandler: ' This is a normal VBA line label
    MsgBox Err.Description
    ObjWorkBook.Close

End Function

From the above script, you learned the following:
1, How to write a function with input parameters
2, When deal with external files, you better write something to handle errors
3, How to use “On Error GoTo” (more details see post#13)
4, How to define an array dynamically (Dim and Redim)
5, How to use Excel Object Model, including Excel.Application, Excel.Workbook, Excel. Worksheet, and Excel.Range. (see here)
6, How to return a value in a function

Make some modifications for the Function_GetExcelSheetData Function above, you should be able to write another 2 functions: one is called as Function_ExcelSheetRowCount, and the other one is called as Function_ExcelSheetColumnCount. These 2 functions will return how many rows or columns in a specific Excel sheet, and they will be used together with Function_GetExcelSheetData in my next post.

In order to test the above function, you can write a separate test script to execute it (“Function_GetExcelSheetData” is the file name):

Sub Main()
Dim A
A = Function_GetExcelSheetData.GetExcelSheetData("C:\...\MeasurementTab.xlsx", "Sheet1")
End Sub

In TestPartner, if the function does not have a return value, but it has more than 1 input values, then in order to execute the function, you still need to define a variable in your test script, and assign the function to the variable. For example, you have a function “ActiveExcelSheet(FilePath As String, SheetName As String)”, which has no return value, just to active a specific sheet in the Excel file. To execute the function, your script needs to look like this:

Sub Main()
Dim A
A = Function_ActiveExcelSheet.ActiveExcelSheet("C:\...\MeasurementTab.xlsx", "Sheet1")
MsgBox (A) 'this tells you A is nothing
End Sub

If the test script looks like this:

Sub Main()
Function_ActiveExcelSheet.ActiveExcelSheet("C:\...\MeasurementTab.xlsx", "Sheet1")
End Sub

TestPartner will inform you there is a “Syntax error” and won’t allow you to run the script. However, if the function has only one input variable and no return value, then you can execute it without assign it to a variable.

Now, let’s talk about how to take the above function (e.g., the “ActiveExcelSheet” function) to QTP. Since TestPartner uses VBA, but QTP uses VBScript, you need to make the following changes in the function script:
A, The function script needs to be created in the QTP Function Library (File – New – Function Library);
B, In the function script, delete anything related to the ErrorHandler (2 paragraphs);
C, In the function script, delete any definition for variable type, e.g., modify “(FilePath As String, SheetName As String)” to “(FilePath, SheetName)”, and change “Dim SheetCount As Integer” to “Dim SheetCount”.
D, Create a Test/Action to execute the function script, and the test/action will look like this (compare to TestPartner test script, no “Sub” nor “End Sub”, no need to assign the function to a variable, and no function file name nor brackets, i.e., “Function_ActiveExcelSheet.ActiveExcelSheet(…)” changes to “ActiveExcelSheet …”):

ActiveExcelSheet "C:\...\MeasurementTab.xlsx", "Sheet1"

E, Associate the Function file with the Test/Action file (right click on the Function file script and choose “Associate…” on the pop up menu), then you can run the function by running the test/action.

From this post, you may have a better understanding of QTP and TestPartner… Beside the object identifier, all the other features that you need for automation testing actually can be achieved by writing VB scripts in notepad, and save them as .vbs files…

Ok, these are just theoretically speaking, we will still write VB scripts in QTP and TestPartner instead of in notepad, right? Just for the convenience.

 

#7: Relationship among VBScript, Visual Basic for Applications (VBA), Visual Basic (VB), and Visual Basic .NET

28 May

QTP uses the Visual Basic Scripting Edition (VBScript) scripting language, and TestPartner is based on the Visual Basic for Applications (VBA).

VBScript is a subset of the Visual Basic Programming language. The result of the slimming down process is a very small language that is easy to use.

Visual Basic for Applications (VBA) is another subset of the Visual Basic Programming language for use with Microsoft Word, Excel, Access etc. While it contains a good many features not supported by VBScript, the basic syntax, or construction of the language, is very similar.

As said above, both VBScript and VBA are subsets of Visual Basic (VB). The final release of VB was version 6 in 1998. Microsoft’s extended support ended in March 2008 and the designated successor was Visual Basic .NET (now known simply as Visual Basic)

After learning the history of the VB family and JavaScript, let us play a small game by writing the VBScript in a notepad. This is very useful if you do not want to bother to repeat the same thing over and over again.

Copy the following code into a notepad, and save it as kk.vbs, then double click on it, and see what it will do.

Dim fs, file, TSTnumber
set fs = createobject( "Scripting.FileSystemObject" )
set file = fs.OpenTextFile( "RF.BAT", 2, true )

For TSTnumber=613 to 616
file.write "VsiColorModeRAW.exe tst-18-0"
file.write TSTnumber
file.write "\tst-18-0"
file.write TSTnumber
file.write ".raw.bmode tst-18-0"
file.write TSTnumber
file.write "\tst-18-0"
file.write TSTnumber
file.write ".raw.color tst-18-0"
file.write TSTnumber
file.write "\tst-18-0"
file.write TSTnumber
file.write ".raw.xml tst-18-0"
file.write TSTnumber
file.writeline "\Color"
Next
file.close
set fs=nothing
 
Comments Off

Posted by Jia Qi in Quick Test Professional (QTP), TestPartner (TP)

 

#0: What is this blog for?

06 Sep

This blog will show you real project examples for you to learn the following Automation testing tools:
- Selenium (Selenium-IDE),
- Quick Test Professional (QTP),
- TestPartner (TP),
- Proprietary script engine written in C++.

QTP and TestPartner are similar GUI automation testing tools, and they are both easy to learn. QTP uses VBScript, and TestPartner uses VBA (more details about VB family and JavaScript, please refer to post#7). Among the three, QTP has the biggest job market. As a QA person, we should master at least one of the automation testing tools and one of the scripting language.

Selenium is a portable software testing framework for web applications (of course you can also use QTP to test webs). Selenium provides a test domain specific language (DSL) to write tests in a number of popular programming languages, including C#, Java, Ruby, Groovy, Python, PHP, and Perl. In this blog, we will focus on Selenium IDE, which is a complete Integrated Development Environment (IDE) for Selenium tests. It is implemented as a Firefox extension, and allows recording, editing, and debugging tests.

The difference between Selenium and QTP/TestPartner is Selenium is an open source software, i.e., it is free! See more information at post#29.

If you decide to learn automation testing, then you can follow this blog. I will share detailed test cases/scripts with you while I am learning, and I am looking forward to learn from you too, so don’t be shy to comment on my posts.

My current company uses TestPartner 6.3 to test our Ultrasound/Photoacoustic imaging system workstation (a Windows Application, i.e., software, can be installed on any computer). Our major focus is to automate measurement and export testing, since we have thousands measurement types and hundreds export combinations in the app., which make manual testing very very time consuming.

We also test our real-time Ultrasound/Photoacoustic imaging systems by using our proprietary scripts (script engine written in C++ and embedded in our systems). The imaging system supports 10 different types of transducers, we need to repeat hundred test cases for each type of the transducers, so to automate the transducer tests will save us a huge amount of time. Also, at the beginning of development, the optimization of our laser machine of the photoacoustic system is not very stable, we use our proprietary scripts to run stress, duration, and reliability tests of the photoacoustic system to help manufacturing and service technicians to investigate and determine the cause of laser optimization failures before shipping and on customer sites.

I also test some websites at home, just for learning purpose. In this blog, I will show you how to test a website called YouPlayOff by QTP, and test Google applications by Selenium.

After we get familiar with QTP, Selenium and TestPartner, then it should not be a problem anymore for you to master other automation testing tools.