0% found this document useful (0 votes)
40 views29 pages

As A General Guideline For Quality Center: Working With Workflow

This document provides guidelines for working with workflows in Quality Center, including: 1. Use error handling in all procedures and functions to prevent crashes. Optimize code by using procedures/functions and switch statements. 2. Access the current TDConnection through a global variable rather than creating a new connection. Use standard OTA interfaces instead of direct database queries. 3. Store common or user-specific data in TestDirector favorites to avoid external dependencies and optimize performance. The document includes code examples and refers the reader to additional code templates for implementing specific workflow tasks like setting field properties, handling errors, and using the TestDirector API.

Uploaded by

bussysam2
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views29 pages

As A General Guideline For Quality Center: Working With Workflow

This document provides guidelines for working with workflows in Quality Center, including: 1. Use error handling in all procedures and functions to prevent crashes. Optimize code by using procedures/functions and switch statements. 2. Access the current TDConnection through a global variable rather than creating a new connection. Use standard OTA interfaces instead of direct database queries. 3. Store common or user-specific data in TestDirector favorites to avoid external dependencies and optimize performance. The document includes code examples and refers the reader to additional code templates for implementing specific workflow tasks like setting field properties, handling errors, and using the TestDirector API.

Uploaded by

bussysam2
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 29

NOTE: TestDirector is no longer supported, use this guide

as a general guideline for Quality Center


Working with Workflow
I. Rules of Thumb......................................................................................2
1. Error Handling.......................................................................................2
2. Code Optimization..................................................................................3
3. Using TestDirector API (OTA) in Scripts....................................................4
4. Workflow Objects...................................................................................6
II. Code Templates....................................................................................8
1. Error Handling.......................................................................................8
1.1 Show the Standard Error to the User..............................................................8
1.2 Error Handling in Procedures and Functions.....................................................8
2. Working with the Fields..........................................................................9
2.1 Setting Field Properties................................................................................9
2.2 Resetting Properties of All Fields..................................................................10
2.3 Setting Field Layout on Form.......................................................................11
2.4 Setting List Dependencies...........................................................................12
2.5 Ensuring That User Updates Some Field When Another Field Is Changed............13
2.6 Check That the Object Is Not Yet Submitted to the Project (“new object”)..........15
2.7 Revert the Field to the Old Value On Update..................................................16
2.8 Implementing “By Owner Only” by Multiple Fields...........................................17
3. Working with TestDirector API (OTA)......................................................19
3.1 Getting the current connection (current session)............................................19
3.2 Getting current session properties................................................................19
3.3 Finding to which groups the current user belongs...........................................21
3.4 Keeping last used value in fields..................................................................22
3.5 Sending an E-Mail from the Workflow...........................................................24
3.6 Obtaining Defect Statistics for the User.........................................................26
3.7 Setting the Last Item in List As a Default Value of the Field..............................27
3.8 Copy Last Run Value to Test in Test Set........................................................28
I. Rules of Thumb

 Use Error Handling in all procedures and functions.


See: Error Handling
 Optimize your code and minimize its size.
Use all the features VBScript provides.
See: Code Optimization
 Use TestDirector API whenever possible instead of external objects,
files, registry.
See: Using TestDirector API (OTA) in scripts
 Explicitly initialize the values for all field properties for all fields.
See: Workflow Objects

1. Error Handling

 Use “On Error Resume Next” statement at the beginning of each


procedure and function.
 Use “On Error GoTo 0” at the end of each procedure or function
 Show errors to the user in some standard message box

Compare the following code fragments:

If Bug_Fields(“BG_SEVERITY”).Value = On Error Resume Next


“4-Urgent” Then ...
Bug_Fields(“BG_PRIORITY”).Value If Bug_Fields(“BG_SEVERITY”).Value =
= “4-Urgent” “4-Urgent” Then
End If Bug_Fields(“BG_PRIORITY”).Value
= “4-Urgent”
End If
...
PrintError “SomeSub”
On Error GoTo 0

The both code fragments will work the same way when no problems arise during the
code execution. But what happens if, for example, the user has no permissions to
modify BG_PRIORITY field? The left fragment will not update the field and will cause
the browser crash. The second will not update the field, but it will show the correct
error to the user and the browser will not crash.

See: Code Templates -> Error Handling


2. Code Optimization

 Use procedures and functions instead of the redundant code


 Use Switch statement instead of repetitive ElseIf statements
 Combine all values that require the same code to be executed to the
same Case statement

 Use procedures and functions instead of the redundant code


The following common tasks are an example of a good subject for separate
function/procedure:
- Setting field properties;
- Setting up fields on the form;
- Setting list dependencies;
- Any procedure that works with TD API (like: send mail)

 Use Switch statement instead of repetitive ElseIf statements


The rule of thumb here can be: if there are 2 or more ElseIf conditions, use
Switch statement.

 Combine all values that require the same code to be executed to the
same Case statement
VBScript allows you to put several values into one Case statement. Example:
In the following example the same code [Code A] should be executed when
the {Variable} value is X or Y. Instead of creating 2 cases (code on the left
side), you can put X and Y into 1 case (code on the right side).

Select Case {Variable} Select Case {Variable}


Case X Case X, Y
[Code A] [Code A]
Case Y Case Z
[Code A] [Code B]
Case Z End Select
[Code B]
End Select
3. Using TestDirector API (OTA) in Scripts

 Use a predefined TDConnection object to get the current session.


 Use standard OTA Interfaces. Avoid use of the Command interface.
 Use TestDirector favorites to store user and group-related data or
data common for all users.
 Use mailing methods available in OTA to send the custom mails to the
users.

 Use a predefined TDConnection object to get the current session.


When you use OTA from some external tool (like VB), the first step for any
application that uses OTA is to create the instance of the TDConnection
object, initialize the connection to the server, and connect to the database.
But in the Workflow there is the predefined TDConnection object (in this case
TDConnection is not only class name, but also the name of the global variable
that contains the instance of TDConnection), which points the same session in
which the current user works.
This means that access to all TestDirector collections and objects is always
available from any place in the Workflow.

See: Code Templates -> Working With TestDirector API -> Getting the current
connection (current session)

 Use standard OTA Interfaces. Avoid use of the Command interface.


The Command object allows execution of any query directly against the
database (using the QueryExecute method). This seems easy solution, but it
has two major disadvantages:
1. It avoids the whole TestDirector logic (permissions, verification of data
integrity, etc.), and
2. It works directly against database, avoiding TestDirector optimizations,
which reduces the performance.
This refers to the usage of QueryExecute for SELECT statements. But an even
more dangerous situation is when the Workflow updates or deletes records
from tables using the QueryExecute method. This may lead to database
corruption, unexpected errors, etc.
From the other side, it is always possible to avoid the use of the Command
interface and to use standard TestDirector interfaces instead (enough to say
that even TestDirector R&D does not use the QueryExecute method).

See: Code Templates -> Working With TestDirector API

 Use TestDirector favorites to store user and group-related data or


data common for all users.
TestDirector favorites are the universal place for storage of any user or
group-related information, as well as the information common for all users.
The following are the examples when TestDirector favorites can be used:
- Store the last used values for the fields per user.
- Store the up-to-date defaults (like “current version” or “current build”) for
fields for all users.
The advantages of the settings usage over the external files/registry are
- The TestDirector settings are not dependant on the machine from which
the user connects to TestDirector.
- They use all TestDirector optimizations.
- They are “native” to TestDirector, and do not need any additional objects,
DLLs, etc.
The OTA has two classes that allow access to the favorites:
- The CommonSettings class allows access/modification of the TestDirector
Public Favorites.
- The UserSettings class allows access/modification of the TestDirector
Private Favorites.
Both classes can be retrieved from the TDConnection object.

See: Code Templates -> Working With TestDirector API -> Keeping Last Used
Value In Fields

 Use mailing methods available in OTA to send the custom mails to the
users.
OTA allows access to TestDirector mailing, which allows you to:
- Create custom conditions that cannot be implemented using the
automatic notification system of TestDirector.
- Change the Subject or the text of the e-mail.
- Send an e-mail to the specific TestDirector groups or TestDirector
users.
- Send the e-mail from the specific user, rather then “admin” as
automatic mail notification does.
The mailing methods are available from any TestDirector object (like Defect,
Test, etc.) or directly from the TDConnection object. Using the Mail method
from the TestDirector object you can send the e-mail that contains that object
and your custom subject/text. Using the Mail method from the TDConnection
object allows you to send any custom mail.

See: Code Templates -> Working With TestDirector API -> Sending an E-Mail
from the Workflow
4. Workflow Objects

 Use {Object}_Fields(“{Field_Name}”) to access field by name.


Use loop on {Object}_Fields.FieldById(i) to access all fields in the
collection.
 Set the IsVisible property before setting the IsRequired or
IsReadOnly property of the field.
 Reset the layout for all fields before setting the fields layout (PageNo
and ViewOrder).

 Use {Object}_Fields(“{Field_Name}”) to access field by name.


Use loop on {Object}_Fields.FieldById(i) to access all fields in the
collection.
Both methods allow you to work with the fields of the “current object.”
The current object can be defined in the following way:
- Current object type: The object type for which the current event
works. Almost each event points to the object type for which the fields
can be retreived. For example, in Defects_Bug_... events, only
Bug_Fields can be retreived; in TestPlan_DesignStep_... events, only
DesignStep_Fields can be retrieved.
- Focused item: From all objects of the collection defined by event,
only the fields of the currently focused object can be retrieved. For
example, the test on which the cursor is placed or the current run in
manual runner.
To retrieve the fields of other objects of the same/other object type, use TD
API (OTA).
The first statement {Object}_Fields(“{Field_Name}”) can be used to retrieve
any particular field by name.
The second statement {Object}_Fields.FieldById(i) is needed to go over all
fields of the current object. For example, to reset the fields order.

See: Code Templates -> Working With the Fields

 Set the IsVisible property before setting the IsRequired or


IsReadOnly property of the field.
Setting the IsRequired or IsReadOnly property for the field not visible in the
UI is meaningless and is ignored by TestDirector. So it is important to ensure
that the field is visible before setting any of these properties.

See: Code Templates -> Working With the Fields -> Setting Field Properties

 Reset the layout for all fields before setting the fields’ layout (PageNo
and ViewOrder).
Since the fields have some default predefined order, it is important to reset
this order before defining the new, custom one.
Consider the following example:
Bug_Fields(“BG_SEVERITY”).ViewOrder = 1
Bug_Fields(“BG_PRIORITY”).ViewOrder = 2
For i=0 To Bug_Fields.Count
Bug_Fields.FieldById(i).ViewOrder = 100
Next
Bug_Fields(“BG_SEVERITY”).ViewOrder = 1
Bug_Fields(“BG_ PRIORITY”).ViewOrder = 2

In the first example, the ViewOrder is set only for BG_SEVERITY and
BG_PRIORITY fields. The ViewOrder of other fields is unknown (what if
ViewOrder of some other field is 1 as well? In this case, BG_ PRIORITY will be
third and not the second field on the form), so you do not actually know how
the fields will appear on the form. In the second example, the ViewOrder of
all the fields is reset to some big value, which ensures that BG_SEVERITY and
BG_PRIORITY fields will be indeed the first on the form.

See: Code Templates -> Working With the Fields -> Resetting Properties of All
Fields
II. Code Templates

1. Error Handling
1.1 Show the Standard Error to the User
Purpose: The following procedure shows the standard error to the user.
Code Location: The code should be added once to each Workflow script (Defects,
Test Plan, etc.).
Templates Used: None
Arguments:
strFunctionName - The name of the function or procedure in which the error have
happened
Return Value: None

Code Template:

Sub PrintError(strFunctionName)
If Err.Number <> 0 Then
MsgBox “Error #” & Err.Number & “: “ & Err.Description, _
vbOKOnly+vbCritical, _
“Workflow Error in Function “ & strFunctionName
End If
End Sub
Template 1.1

Usage Example: See the template in 2.1.

1.2 Error Handling in Procedures and Functions


Purpose: The following code ensures the correct error handling in procedures and
functions.
Code Location: The code should be added to each function and procedure.
Templates Used: Template 1.1
Arguments: Not relevant
Return Value: Not relevant

Code Template:

Function|Sub {Function|Sub_Name}()
On Error Resume Next
[Your code here]
PrintError “{Function|Sub_Name}”
On Error GoTo 0
End Function|Sub
Template 1.2

Usage Example: See the templates below.


2. Working with the Fields
2.1 Setting Field Properties

Solution 1: Setting all field properties


Purpose: The code below allows the setting of all field properties.
Code Location: The code should be added to the code of each Workflow script
(Defects, Test Plan, etc.) for each object (for example, in Test Plan script the
separate procedures for Test and Design Steps should be added). The {Object}
should be replaced with the name of the object (i.e., Bug, Test, etc.)
Templates Used: Template 1.1 and 1.2
Arguments:
strFieldName - The name of the field for which the properties should be set
blnIsVisible - The value of the IsVisible property of the field to be set
blnIsReadOnly - The value of the IsReadOnly property of the field to be set
blnIsRequired - The value of the IsRequired property of the field to be set
intPageNo – The value of the PageNo property of the field to be set
intViewOrder – The value of the ViewOrder property of the field to be set
Return Value: None

Code Template:

Sub {Object}_SetFieldProp(strFieldName,
blnIsVisible, blnIsReadOnly, blnIsRequired,
intPageNo, intViewOrder)
On Error Resume Next
With {Object}_Fields(strFieldName)
.IsVisible = blnIsVisible
.IsReadOnly = blnIsReadOnly
.IsRequired = blnIsRequired
.PageNo = intPageNo
.ViewOrder = intViewOrder
End With
PrintError “{Object}_SetFieldProp”
On Error GoTo 0
End Sub
Template 2.1.1

Usage Example: For example, if you have created the procedure Sub
Bug_SetFieldProp using this template, you can use it anywhere in the script like:

Bug_SetFieldProp “BG_USER_01”, True, False, False, 2, 1

Solution 2: Setting field flags and view properties separately


Purpose: Sometimes it is more convenient to separate the field flags (IsVisible,
IsRequired, IsReadOnly) and field view properties (PageNo and ViewOrder). The code
below allows for setting the field flags and view properties separately.
Code Location: The code should be added to the code of each Workflow script
(Defects, Test Plan, etc.) for each object (for example in Test Plan script the
separate procedures for Test and Design Steps should be added). The {Object}
should be replaced with the name of the object (i.e., Bug, Test, etc.)
Templates Used: Template 1.1 and 1.2
Arguments:
strFieldName - The name of the field for which the properties should be set
blnIsVisible - The value of the IsVisible property of the field to be set
blnIsReadOnly - The value of the IsReadOnly property of the field to be set
blnIsRequired - The value of the IsRequired property of the field to be set
intPageNo – The value of the PageNo property of the field to be set
intViewOrder – The value of the ViewOrder property of the field to be set
Return Value: None

Code Template:

Sub {Object}_SetFieldFlags(strFieldName,
blnIsVisible, blnIsReadOnly, blnIsRequired)
On Error Resume Next
With {Object}_Fields(strFieldName)
.IsVisible = blnIsVisible
.IsReadOnly = blnIsReadOnly
.IsRequired = blnIsRequired
End With
PrintError “{Object}_ SetFieldFlags”
On Error GoTo 0
End Sub
Template 2.1.2

Sub {Object}_SetFieldView( strFieldName,


intPageNo, intViewOrder)
On Error Resume Next
With {Object}_Fields(strFieldName)
.PageNo = intPageNo
.ViewOrder = intViewOrder
End With
PrintError “{Object}_ SetFieldView”
On Error GoTo 0
End Sub
Template 2.1.3

Usage Example: See the examples for templates 2.1.1 and 2.2.

2.2 Resetting Properties of All Fields

Solution 1: Resetting field properties in loop


Purpose: Before setting the field flags or layout properties, it’s recommended to
reset the properties of all fields in the collection to ensure that all the properties are
set to correct values (See: Workflow Objects in Rules of Thumb section). The code
below shows how to reset properties of all fields in the collection.
Code Location: The code should be added in each relevant procedure or function
(when the reset of field properties is needed). Alternatively, it can be put to the
separate procedure. In this case the separate procedures are needed for different
object types (for example in Test Plan script the separate procedures for Test and
Design Steps should be added).
The {Object} should be replaced with the name of the object (ie: Bug, Test, etc.),
{Property} should be replaced with the name of field property (ie: IsRequired,
PageNo, etc) and the {Value} should be replaced with property value.
Templates Used: None
Arguments: Not relevant
Return Value: Not relevant
Code Template:

For i=0 To {Object}_Fields.Count


{Object}_Fields.FieldById(i).{Property} = {Value}
Next
Template 2.2.1

Usage Example: in the following example, the IsVisible property of all defect fields
is reset:

For i=0 To Bug_Fields.Count


Bug_Fields.FieldById(i).IsVisible = False
Next

Solution 2: Calling function that resets field properties in loop


Purpose: Same as above. In this case the template procedures will be used to reset
the field properties (the {Procedure} should be replaced with the name of the
procedure used to reset the fields. The name of the field can be retrieved using
Code Location: Same as above.
Templates Used: templates 2.1.1, 2.1.2, 2.1.3
Arguments: Not relevant
Return Value: Not relevant

Code Template:

For i=0 To {Object}_Fields.Count


{Procedure} {Object}_Fields.FieldById(i).FieldName[, ...]
Next
Template 2.2.2

Usage Example: in the following example, the procedure Bug_SetFieldView was


created from template 2.1.3. The procedure is used to reset the layout of all fields:

For i=0 To Bug_Fields.Count


Bug_SetFieldView Bug_Fields.FieldById(i).FieldName, 100, 100
Next

2.3 Setting Field Layout on Form


Purpose: Organize fields order on forms and define pages. Using the template, you
can specify the names of the field just in the same way as you want the fields to
appear on page. To define several pages, call the procedure with different arrays.
Code Location: The code should be added to the code of each workflow script
(Defects, Test Plan, etc.), for each object (for example in Test Plan script the
separate procedures for Test and Design Steps should be added). The {Object}
should be replace with the name of the object (ie: Bug, Test, etc.). The {Form}
should be replace with the name of the form (ie: Add Defect, Defect Details, etc.)
Templates Used: Template 1.1, 1.2, 2.1.3
Arguments:
strFieldArray - the name of the field for which the properties should be set.
intPageNo – the value of the PageNo property of the field to be set.
Return Value: None
Note: It’s recommended to reset the layout of all the fields before setting the new
layout (ie: to set PageNo and ViewOrder properties to some big values, like 100, and
to set IsVisible, IsRequired and IsReadOnly properties of all fields to False. See:
Workflow Objects in Rules of Thumb section and 2.2 code template)

Code Template:

Sub {Form}_SetPageFieldsOrder(strFieldArray, intPageNo)


On Error Resume Next
For i=0 To Ubound(strFieldArray)
{Object}_SetFieldView strFieldArray(i), intPageNo, i + 1
Next
PrintError "{Form}_SetPageFieldsOrder"
On Error GoTo 0
End Sub
Template 2.3

Usage Example: for example you want to organize the fields on the Add Defect
form, so that all relevant system fields would be on first page, and all other fields
would be on the second page, the AddDefect_SetPageFieldsOrder procedure created
by template can be used in the following way:

Dim strFieldArray1, strFieldArray2


‘ First page
strFieldArray1 = Array(“BG_DETECTED_BY”, “BG_DETECTION_DATE”, _
“BG_STATUS”, “BG_SEVERITY”, _
“BG_PROJECT”, “BG_DETECTION_VERSION”, _
“BG_SUBJECT”, “BG_REPRODUCIBLE”)
AddDefect_SetPageFieldsOrder strFieldArray1, 1
‘ Second page
strFieldArray2 = Array(“BG_USER_01”, “BG_USER_02”, _
“BG_USER_03”, “BG_USER_04”)
AddDefect_SetPageFieldsOrder strFieldArray2, 2

2.4 Setting List Dependencies


Purpose: The code below allows to set up the value for some field (ie: Dependant
Field) according to the value of the other field (ie: Master Field).
Code Location: It should be added to the code of each workflow script (Defects,
Test Plan, etc.). Also the different procedures should be created for all pairs of field
that have different logic. The {Object} should be replace with the name of the object
(ie: Bug, Test, etc.)

Templates Used: templates 2.1.1, 2.1.2


Arguments:
strMasterField - the name of the field which defines the list for the dependant
field
strDepenadantField – the name of the field for which the list is set according
to master field.
Return Value: None
Code Template:

Sub {Object}_SetList(strMasterField, strDependantField)


On Error Resume Next
Select Case {Object}_Fields(strMasterField).Value
Case “{Value1}”
{Object}_Fields(strDependantField).List = Lists(“{List1}”)
...
Case Else
{Object}_Fields(strDependantField).List = Lists(“{ListN}”)
End Select
PrintError “{Object}_SetList”
On Error GoTo 0
End Sub
Template 2.4

Usage Example: For example if you’ve created the procedure Sub Bug_SetList
using this template, and you want to set the list for BG_CLOSING_VERSION,
BG_DETECTION_VERSION, BG_PLANNED_CLOSING_VER fields according to the
value of the BG_PROJECT field, you can use the following code anywhere in the
script:

Bug_SetList “BG_PROJECT”, “BG_CLOSING_VERSION”


Bug_SetList “BG_PROJECT”, “BG_ DETECTION _VERSION”
Bug_SetList “BG_PROJECT”, “BG_PLANNED_CLOSING_VER”

2.5 Ensuring That User Updates Some Field When Another Field Is Changed
Purpose: The code below allows to ensure that some field (“dependant field”) is
updated when another field (“master field”) is changed to some value. For example:
when the Status (aka “master field”) field is changed to “Fixed”, we want to ensure
that the user updates R&D Comments (aka “dependant field”).
Code Location: It should be added to the code of each workflow script (Defects,
Test Plan, etc.), separately for each object. The {Mode} should be replaced with the
name of the mode (TestPLan, TestLab, etc.); the {Object} should be replaced with
object name (Bug, Test, etc.). {MasterField} should be replaced with the name of
the “master field” (or with field label for flag names); {DependantField} should be
replaced with the name of the “dependant field” (or with field label for flag names).
See the example below for correct template usage.
Templates Used: None
Arguments: None
Return Value: None
Note: Since the template is only a part of the code, and doesn’t represent a
separate function or procedure, the error handling is not shown in template.
Steps:
1. Create 2 global boolean flags that will be False by default; one of them
will become True when the “master field” is changed to desired value; the
second will become true when the “dependant field” will be changed.
2. Update flags to False in MoveTo event
3. In FieldChange event, update the first flag to True when the “master field”
is changed to desired value; update the second flag to True when the
dependant field is changed
4. In CanPost event, if the “master field” was changed (ie: the first flag is
True), and the second field was not changed (ie: the second flag is False),
do not allow item posting.

Code Template:

Dim b{MasterField}Changed, b{DependantField}Changed

Sub {Mode}_{Object}_MoveTo()

b{MasterField}Changed = False
b{DependantField}Changed = False

End Sub

Sub {Mode}_{Object}_FieldChange(FieldName)

Select Case FieldName

Case “{MasterField}”
If {Object}_Fields(“{MasterField}”).Value = {Value} Then
b{MasterField}Changed = True
End If
Case “{DependantField}”
b{DependantField}Changed = True

End Select

End Sub

Function {Mode}_{Object}_CanPost()

If b{MasterField}Changed And _
Not b{DependantField}Changed Then
MsgBox “Please update <” & _
{Object}_Fields(“{DependantField}”).FieldLabel & _
“> field.”, vbCritical + vbOKOnly, _
“Workflow - Field Change Verification”
{Mode}_{Object}_CanPost = False
Else
{Mode}_{Object}_CanPost = True
End If

End Function
Template 2.5

Usage Example: In the following example, when the Status field is changed to
“Fixed”, the scripts ensures that R&D Comments field was updated as well.

Dim bStatusChanged, bRDCommentsChanged

Sub Defects_Bug_MoveTo()
bStatusChanged = False
bRDCommentsChanged = False
End Sub

Sub Defects_Bug_FieldChange(FieldName)
Select Case FieldName
Case “BG_STATUS”
If Bug_Fields(“BG_STATUS”).Value = “Fixed” Then
bStatusChanged = True
End If
Case “BG_DEV_COMMENTS”
bRDCommentsChanged = True
End Select
End Sub

Function Defects_Bug_CanPost()
If bStatusChanged And Not bRDCommentsChanged Then
MsgBox “Please update <“ & _
Bug_Fields(“BG_DEV_COMMENTS”).FieldLabel & _
“> field.”, vbCritical + vbOKOnly, _
“Workflow – Field Change Verification”
Defects_Bug_CanPost = False
Else
Defects_Bug_CanPost = True
End If
End Function

2.6 Check That the Object Is Not Yet Submitted to the Project (“new
object”)
Purpose: In many cases you need to verify if the object was not yet submitted to
the project. The following code allows to perform such verification. For example: you
want to verify that the new defect is always submitted with the status ‘New’; on test
creation you want to fill some user-defined field; etc.
Code Location: The code should be added in each relevant procedure or function
(when such verification is needed). {Object} should be changed with the name of
the object for which the verification is needed (for example: Bug, Test, etc.); the
{Object ID Field} should be changed to the name of the field stores the ID of the
object (for example: BG_BUG_ID, TS_TEST_ID, etc.).
Templates Used: None
Arguments: Not relevant
Return Value: Not relevant

Code Template: Check that the object ID field is empty

If {Object}_Fields(“{Object ID Field}”).Value = “” Then


Template 2.6

Usage Example: The example below checks if the defect is “new object”, and
doesn’t allow to post such defect id its status is not “New”:

Sub Defects_Bug_CanPost()
On Error Resume Next

If Bug_Fields(“BG_BUG_ID”).Value = “” And _
Bug_Fields(“BG_STATUS”).Value <> “New” Then
MsgBox “The <Status> of the new bug should be ‘New’.”
Defects_Bug_CanPost = False
End If

PrintError “Defects_Bug_CanPost”
On Error GoTo 0
End Sub

2.7 Revert the Field to the Old Value On Update


Purpose: The code below allows to revert the value of the field to the old value,
when some condition is not satisfied. For example: the Status of the bug cannot be
set to Closed if Closed In Version field was not filled.
Code Location: There are 3 parts of relevant code. The first part defines the global
variable that will store the original value of the field. For each field the separate
variable should be defined. The second part of code should be added MoveTo event
(this part preserves the original value of the field, before it was changed). The third
part of code should be added to the CanPost event (it checks the condition and
reverts the field value to the original value if the condition is not satisfied). All 3
parts of code should be added to each module, separately for each field and
condition when the old value retrieval mechanism is required.
Templates Used: None
Arguments: Not relevant
Return Value: Not relevant

Code Template:

Dim s{FieldLabel}OrigValue

Sub {Mode}_{Object}_MoveTo()

s{FieldLabel}OrigValue = {Object}_Fields(“{FieldName}”). Value

End Sub

Function {Mode}_{Object}_CanPost()

If {Condition} Then
{Object}_Fields(“{FieldName}”). Value = s{FieldLabel}OrigValue
End If

End Sub
Template 2.7

Usage Example: In the example below when the user sets the status of the defect
to Closed, and doesn’t fill the Closed In Version field, the value of the Status field is
changed back to the original value:

Dim sStatusOrigValue

Sub Defects_Bug_MoveTo()

sStatusOrigValue = Bug_Fields(“BG_STATUS”).Value

End Sub

Function Defects_Bug_CanPost()

If Bug_Fields(“BG_CLOSING_VERSION”).Value = “” Then
MsgBox “The Closed In Version value was not specified.”, vbCritical
Bug_Fields(“BG_STATUS”).Value = sStatusOrigValue
End If

End Function

2.8 Implementing “By Owner Only” by Multiple Fields


Purpose: While TestDirector allows one user to be the owner of the object,
sometimes it’s reasonable to have several owners of the object. For example if you
want that only the user sho submitted the defect (“Detected By”, BG_DETECTED_BY
field), or the user who is responsible for the defect (“Assigned To”,
BG_RESPONSIBLE field) will be able to change its Priority and Severity. Other users
can change other fields. If you will set “By Owner Only” flag for Priority and Severity
fields in group permissions, only “Assigned To” user will be able to change Priority
and Severity (since by default in TestDirector the owner of the defects is (“Assigned
To” user). If “By Owner Only” flag for Priority and Severity fields will not be set in
group permissions, all users will be able to change these fields.
The code below allows to work with multiple owners of the object.
Code Location: The function should be added to the code of each workflow script
(Defects, Test Plan, etc.), for each object (for example in Test Plan script the
separate procedures for Test and Design Steps should be added). The {Object}
should be replace with the name of the object (ie: Bug, Test, etc.). The function
should be called from {Mode}_{Object}_FieldChange or
{Mode}_{Object}_CanChange events, as shown in the example.
Templates Used: Template 1.1 and 1.2
Arguments:
strFieldNames - the names of the fields that define the owner of the object.
The system and user-defined fields that have the User list attached can be
specified. The format of the string should be: “FIELD_NAME1;FIELD_NAME2;
…”
Return Value: Boolean: True if the current user is the owner of the object; False if
the current user is not the owner of the object.

Code Template:

Function Check{Object}Owner(strFieldNames)
On Error Resume Next
Dim strFieldArr
CheckObjectOwner = False
strFieldArr = Split(strFieldNames, “;”)
For i = 0 To Ubound(strFieldArr)
If {Object}_Fields(strFieldArr(i)).Value = User.UserName Then
CheckObjectOwner = True
End If
Next
PrintError “Check{Object}Owner”
On Error GoTo 0
End Sub
Template 2.8

Usage Example: In the example below 3 fields define the owner of the defect:
BG_DETECTED_BY, BG_RESPONSIBLE and BG_USER_01 (user-defined field with the
User list attached). When the user tries to change defect’s Priority (BG_PRIORITY) or
Severity (BG_SEVERITY), workflow checks if the user is the owner of the defect (ie:
the name of current user appears in one of 3 specified fields). If the user is not the
owner of the object, the field value is reverted to the original value. Note that
template 2.7 is used in this example.

Dim sPriorityOrigValue
Dim sSeverityOrigValue

Sub Defects_Bug_MoveTo

sPriorityOrigValue = Bug_Fields(“BG_PRIORITY”).Value
sSeverityOrigValue = Bug_Fields(“BG_SEVERITY”).Value

End Sub

Sub Bug_FieldChange(FieldName)
Dim strOwnerFields
strOwnerFields = “BG_DETECTED_BY;BG_RESPONSIBLE;BG_USER_01”

Select Case FieldName
Case “BG_SEVERITY”, “BG_PRIORITY”
If Not CheckBugOwner(strOwnerFields) Then
MsgBox “Only owners can change defect Severity and Priority”
Bug_Fields(“BG_PRIORITY”).Value = sPriorityOrigValue
Bug_Fields(“BG_SEVERITY”).Value = sSeverityOrigValue
End If
End Select

End Sub
3. Working with TestDirector API (OTA)
3.1 Getting the current connection (current session)

Purpose: The code below shows how to receive the current session context in
workflow (the same session in which the user will work during script execution).
Code Location: The code should be added in each relevant procedure or function
(when the access to OTA is required).
Templates Used: None
Arguments: Not relevant
Return Value: Not relevant

Code Template: Just refer to the TDConnection object

Usage Example: In the example below server time (TDConnection class property) is
shown in message box:

MsgBox “Current time on server is: ” & TDConnection.ServerTime

3.2 Getting current session properties


Purpose: The code below allows getting the properties of the current session (server
URL, server time, domain name, project name, project type, user name, and
password). Any other TDConnection property can be obtained using the alike code.
For the list of TDConnection properties, please see the help for TDConnection object
in OTA Guide.
Code Location: code should be added to the appropriate function or procedure
where any of these properties is needed (the properties do not depend on each
other, meaning that any of the properties can be received separately).
Templates Used: None
Arguments: Not relevant
Return Value: Not relevant

Code Template:

Dim varRes
‘ Returns the current server URL
varRes = TDConnection.ServerName
‘ Returns the current server time (Date type)
varRes = TDConnection.ServerTime
‘ Returns the current domain name
varRes = TDConnection.DomainName
‘ Returns the current project name
varRes = TDConnection.ProjectName
‘ Returns the current project type (Access, Oracle, MS SQL, Sybase)
varRes = TDConnection.ProjectType
‘ Returns the current user name (no need to use TDConnection here – ‘ the
workflow has the predefined object called User)
varRes = User.UserName
‘ Returns the current user password
varRes = TDConnection.Password
Template 3.2
Usage Example: In the example below, the server name is used to verify whether
the user connected to the server using HTTP or HTTPS:

If Left(UCase(TDConnection.ServerName), 5) = “HTTPS” Then


MsgBox “You are currently connected to the server using SSL”
Else
MsgBox “You are not using SSL”
End If
3.3 Finding to which groups the current user belongs

Solution 1: Checking if the user belongs to some particular group


Purpose: The code below allows checking if the current user belongs to a given
group.
Code Location: code should be added to the appropriate function or procedure
where it’s needed to check if the user belongs to any particular group.
Templates Used: None
Arguments: Not relevant
Return Value: Not relevant

Code Template: Just refer to the User.IsInGroup(“Group_Name”) property

Usage Example: The example below checks if the user belongs to TDAdmin group

If User.IsInGroup(“TDAdmin”) Then
MsgBox “You are the member of TDAdmin group”
Else
MsgBox “You are not the member of TDAdmin group”
End If

Solution 2: Receiving the list of all the groups to which the current user
belongs
Purpose: The code below allows getting the list of all groups to which the current
user belongs.
Code Location: code should be added to the code of each workflow script (Defects,
Test Plan, etc.).
Templates Used: templates 2.1.1, 2.1.2
Arguments: None
Return Value: string that contains the names of the groups to which the user
belongs. The names of the groups are separated by semicolon.

Code Template:

Function GetUserGroups()
Dim objCustomization, objUsers, objUser, objGroup
Dim strGroupList
On Error Resume Next
Set objCustomization = TDConnection.Customization
Set objUsers = objCustomization.Users
Set objUser = objUsers.User(User.UserName)
strGroupList = “”
For Each objGroup In objUser.GroupsList
strGroupList = strGroupList & “;” & objGroup.Name
Next
GetUserGroups = Left(strGroupList, Len(strGroupList)-1)
Set objCustomization = Nothing
Set objUsers = Nothing
Set objUser = Nothing

PrintError "GetUserGroups"
On Error GoTo 0
End Function
Template 3.3

Note: You can use Split function in order to convert the string returned by this
function into array:

Dim strGroupArray
strGroupArray = Split(GetUserGroups, “;”)

Usage Example: in the following example the list of the groups is received using the
template above; the user role is later defined according to the groups. For example if
the user is the member of “QA Tester” team, the user role is defined as “QA”; if the
user is the member of “Managers” and “Developers” groups, then user role is defined
as “R&D Manager” etc.

Dim strGroups, strRole


strGroups = UCase(GetUserGroups)
If InStr(strGroups, “DEVELOPER”) > 0 Then strRole = “R&D “
If InStr(strGroups, “QA”) > 0 Then strRole = strRole & “QA “
If InStr(strGroups, “MANAGER”) > 0 Then strRole = strRole & “Manager “
strRole = Left(strRole, Len(strRole) – 1)

3.4 Keeping last used value in fields


Purpose: The following code template allows preserving the value of the field, and
to fill the field automatically next time the field needs to be filled (even after the
closure of the browser, or from different client machine). The template uses
TestDirector private favorites to store the settings (which allow using the saved
fields’ settings even if the user connects from different machine). The template is
especially useful for Add Defect form and the Manual Runner, but can be used for
any other object as well.
Code Location: code should be added to the code of each workflow script (Defects,
Test Plan, etc.). Separate procedures should be created for each object for which this
functionality is needed. The {Object} statement should be replaced with the name of
the object for which the template is used (for example: Bug, Test, etc.).
Templates Used: templates 2.1.1, 2.1.2
Arguments:
strAction - Accepts the values “GET” and “SET”. When “GET” is specified for
strAction argument, the values of the fields previously saved are retrieved
(the value for the field is set only if the field is empty). When “SET” is
specified for strAction argument, the values of the specified fields are stored
(the second argument specifies which fields need to be saved).
strFieldArray – Relevant only when “SET” is specified as the strAction
argument: the array that contains the names of the fields for which the
values should be saved. The empty string can be specified for “GET” action.
Note: The second argument of the function (strFieldArray) can be defined as follows
before function call:

Dim strFieldArray
strFieldArray = Array(“{Field Name1}”, “{Field Name2}”, …)

See also the usage example below.


Return Value: None

Code Template:

Sub KeepLastValue(strAction, strFieldArray) ‘ strAction = {“GET”|”SET”}


On Error Resume Next
Dim strValues, objUserSettings, strFields, strField
If strAction = "SET" Then
strValues = ""
For i=0 To UBound(strFieldArray)
If strValues <> "" Then strValues = strValues & ";"
strValues = strValues & strFieldArray(i) & "=" & _
{Object}_Fields(strFieldArray(i)).Value
Next
End If
Set objUserSettings = TDConnection.UserSettings
If strAction = "SET" Then
objUserSettings.Open ("KeepLastValue")
objUserSettings.Value("{Object}_KeepLastValue") = strValues
objUserSettings.Close
End If
If strAction = "GET" Then
objUserSettings.Open ("KeepLastValue")
strValues = objUserSettings.Value("{Object}_KeepLastValue")
If strValues <> "" Then
strFields = Split(strValues, ";")
For i = 0 To UBound(strFields)
strField = Split(strFields(i), "=")
If UBound(strField) = 1 And
{Object}_Fields(strField(0)).Value = "" Then
{Object}_Fields(strField(0)).Value = strField(1)
End If
Next
End If
End If
objUserSettings.Close
Set objUserSettings = Nothing
PrintError “KeepLastValue(“ & strAction & “)”
On Error GoTo 0
End Sub
Template 3.4

Usage Example: in the following example the values of Detected in Version field
(BG_DETECTION_VERSION) and Project field (BG_PROJECT) are saved when the
user submits the new bug. The saved values are retrieved the next time the user
opens Add Defect form.

Sub Defects_Bug_New
On Error Resume Next

‘ Retrieve the values of the fields on opening of new bug
KeepLastValue "GET", ""

PrintError “Defects_Bug_ New”
On Error GoTo 0
End Sub

Function Defects_Bug_CanPost
On Error Resume Next
Dim strFieldArray

‘ Save the values of the fields on submit of new bug
strFieldArray = Array(“BG_DETECTION_VERSION”, "BG_PROJECT")
If Bug_Fields("BG_BUG_ID").Value = "" Then
KeepLastValue "SET", strFieldArray
End If

PrintError “Defects_Bug_CanPost”
On Error GoTo 0
End Function

3.5 Sending an E-Mail from the Workflow

Purpose: The following code template allows sending any object in TestDirector
(Defect, Test, etc.) by e-mail. The code can be used to extend the automatic mail
notifications with custom conditions, not available for Send All Qualified. The
template uses TestDirector mailing functions.
Code Location: The code for the each object should be placed in the script of the
corresponding module. For example: SendDefect function should be placed in
Defects module.
Templates Used: templates 2.1.1, 2.1.2
Arguments:
iObjectId – The ID of the object that should be sent (see the note below on
how to obtain the object ID).
strTo – The TestDirector names or e-mails of the people that will appear in To
field of the e-mail (the names and e-mails should be separated by semicolon.
For example: “[email protected];admin;alice_td”).
strCc – The TestDirector names or e-mails of the people that will appear in Cc
field of the e-mail (the names and e-mails should be separated by semicolon.
For example: “[email protected];admin;alice_td”). Specify an empty string
(“”) to omit this parameter.
strSubject – The e-mail Subject. Specify an empty string (“”) to omit this
parameter.
strComment – The e-mail comment (will appear at the top of the e-mail).
Specify an empty string (“”) to omit this parameter.
Notes:
1. The object ID value can always be retrieved using the {Object}_Fields
collection, by retrieving the Value property of the ID field. The example below
shows how to retrieve the Ids of Defect, Test and Requirement:

’ Defect ID – for SendDefect


Bug_Fields(“BG_BUG_ID”).Value
’ Test ID – for SendTest
Test_Fields(“TS_TEST_ID”).Value
’ Requirement ID – for SendReq
Req_Fields(“RQ_REQ_ID”).Value
2. The templates for Defect, Test and Requirement are provided. However the
function may be used to work with any object that has Mail function.
3. The third parameter in Mail function allows specifying e-mail options. In
the templates below this parameter is hard-coded (its value 2 means that the
object History will be sent). However you can change this value to any of the
values of TDMAIL_FLAGS. You can use sum to combine the mail properties.
For example: 1 – means “send attachments”; 2 – means “send history”. In
order to send the mail with attachments and history, specify 3 for this
argument.

Return Value: None

Code Template:

Sub SendDefect (iObjectId, strTo, strCc,


strSubject, strComment)
On Error Resume Next
Dim objBugFactory, objBug
Set objBugFactory = TDConnection.BugFactory
Set objBug = objBugFactory.Item(iObjectId)
objBug.Mail strTo, strCc, 2, strSubject, strComment
Set objBug = Nothing
Set objBugFactory = Nothing
PrintError “SendDefect”
On Error GoTo 0
End Sub
Template 3.5.a

Sub SendTest (iObjectId, strTo, strCc,


strSubject, strComment)
On Error Resume Next
Dim objTestFactory, objTest
Set objTestFactory = TDConnection. TestFactory
Set objTest = objTestFactory.Item(iObjectId)
objTest.Mail strTo, strCc, 2, strSubject, strComment
Set objTest = Nothing
Set objTestFactory = Nothing
PrintError “SendTest”
On Error GoTo 0
End Sub
Template 3.5.b

Sub SendRequirement (iObjectId, strTo, strCc,


strSubject, strComment)
On Error Resume Next
Dim objReqFactory, objReq
Set objReqFactory = TDConnection.ReqFactory
Set objReq = objReqFactory.Item(iObjectId)
objReq.Mail strTo, strCc, 2, strSubject, strComment
Set objReq = Nothing
Set objReqFactory = Nothing
PrintError “SendRequirement”
On Error GoTo 0
End Sub
Template 3.5.c
Usage Example: In the following example when the test status is changed, the e-
mail notification is sent to the designer of the test, cc to all the members of the [QA
Testers] group.

Sub TestPlan_Test_FieldChange(FieldName)
On Error Resume Next
Dim strSubject, strComment
If FieldName = "TS_STATUS" Then
strSubject = “Test Change Notification” & _
“ for project “ & TDConnection.ProjectName & _
“ in domain “ & TDConnection.DomainName
strComment = “The user “ & User.FullName & _
“ changed the status of the test ” & _
Test_Fields(“TS_NAME”).Value & _
“ to “ & Test_Fields(“TS_ STATUS”).Value
SendTest Test_Fields("TS_TEST_ID").Value, _
Test_Fields(“TS_RESPONSIBLE”).Value, “[QA Testers]”, _
strSubject, StrComment
End If
On Error GoTo 0
End Sub

3.6 Obtaining Defect Statistics for the User

Purpose: The template allows obtaining statistics for the user, for example: how
many defects are assigned to current user. The template may be used to create the
button that shows this statistics whenever user clicks on it. Another way to use this
template is to create the conditions that allow the team leader to decide on tasks.
For example: the team leader doesn’t want to allow more then 5 defects with priority
Urgent and with status Open or Reopen to be assigned to one person.
Note: The template below is for the Defects. However such function can be created
for any object in TestDirector.
Code Location: The code for the each object should be placed in the script of the
corresponding module. Each logical set should be placed in separate function as well.
Templates Used: templates 2.1.1, 2.1.2
Arguments:
strFilterConditions – The conditions for which the number of objects should be
found. Should be specified in the format
“FILTER_FIELD2=FilterCondition1; FILTER_FIELD2=FilterCondition2;”
While filter conditions format is the same as the format that is used in
OTAClient for filters.
For example: if you want to get the number of defects assigned to the user
“alex_td”, that have status “Open” or “Reopen” and the priority “4-Urgent”,
the following string should be specified:
“BG_RESPONSIBLE=alex_td;BG_STATUS=Open Or Reopen;BG_PRIORITY=4-
Urgent”
Return Value: Returns the number of objects for given condition

Code Template:

Function GetDefectStatistics(strFilterConditions)
On Error Resume Next
Dim strFilterConditionArr, strCondition
Dim objBugFactory, objFilter, objList
Set objBugFactory = TDConnection.BugFactory
Set objFilter = objBugFactory.Filter
strFilterConditionArr = Split(strFilterConditions, “;”)
For i = 0 To Ubound(strFilterConditionArr)
strCondition = Split(strFilterConditionArr(i), “=”)
If Ubound(strCondition) = 1 Then
objFilter.Filter(strCondition(0)) = strCondition(1)
End If
Next
Set objList = objFilter.NewList
GetDefectStatistics = objList.Count
Set objList = Nothing
Set objBugFactory = Nothing
Set objFilter = Nothing
PrintError “GetDefectStatistics”
On Error GoTo 0
End Function
Template 3.6

Usage Example: In the following example when the defect with priority “4-Urgent”
is assigned to some user, workflow checks how many defects with the same priority
and the status “Open” or “Reopen” are already assigned to the same user. If the
number of defects is 5 or more, the workflow will show warning.

Sub Defects_Bug_FieldChange(FieldName)
On Error Resume Next
Dim strConditions, iNumberOfBugs
If FieldName = "BG_RESPONSIBLE" Then
strConditions = “BG_RESPONSIBLE=” & _
Bug_Fields(“BG_RESPONSIBLE”).Value & _
“;BG_STATUS=Open Or Reopen” & _
“;BG_PRIORITY=4-Urgent”
iNumberOfBugs = Cint(GetDefectStatistics(strConditions))
If iNumberOfBugs >= 5 Then
MsgBox “” & iNumberOfBugs & “ defects” & _
“ with Priority=<4-Urgent> and “ & _
“ Status=<Open> or <Reopen>” & _
“ are already assigned to the user “ & _
Bug_Fields(“BG_RESPONSIBLE”).Value
End If
End If
On Error GoTo 0
End Sub

3.7 Setting the Last Item in List As a Default Value of the Field

Purpose: The template allows to select the last item from the list, and to set it as a
default value for some field. This is useful for the fields where the last value is most
commonly used. For example: the field Detected In Version has a list of versions
attached. Most of the users will select the current version for the defects they
submit, which is the last in the list. So this value can be a default for this field.
Code Location: code should be added to the code of each workflow script (Defects,
Test Plan, etc.). Separate procedures should be created for each object for which this
functionality is needed. The {Object} statement should be replaced with the name of
the object for which the template is used (for example: Bug, Test, etc.).
Templates Used: templates 2.1.1, 2.1.2
Arguments:
strFieldName – The name of the field for which the default value should be
set.
strListName – The name of the list from which the default value should be
selected. This list should be attached to the field specified by strFieldName.
Return Value: None

Code Template:

Sub SetDefaultValue(strFieldName, strListName)


On Error Resume Next
Dim objCustomization, objLists, objList, objNode, objChildren
Dim iChildrenCount
Set objCustomization = TDConnection.Customization
objCustomization.Load
Set objLists = objCustomization.Lists
Set objList= objLists.List(strListName)
Set objNode = objList.RootNode
iChildrenCount = objNode.ChildrenCount
Set objChildren = objNode.Children
{Object}_Fields(strFieldName).Value =
objChildren(iChildrenCount).Name
objCustomization.Commit
Set objCustomization = Nothing
Set objLists = Nothing
Set objList= Nothing
Set objNode = Nothing
PrintError “SetDefaultValue”
On Error GoTo 0
End Sub
Template 3.7

Usage Example: In the following example when the New Defect form is opened, the
script assigns “Versions” list to Detected in Version (BG_DETECTION VERSION) field.
Then the value of the Detected In Version field is set to the last item in Versions list.

Sub Defects_Bug_New()
On Error Resume Next
Bug_Fields(“BG_DETECTION_VERSION”).List = Lists(“Versions”)
SetDefaultValue(“BG_DETECTION_VERSION”, “Versions”)
On Error GoTo 0
End Sub

3.8 Copy Last Run Value to Test in Test Set

Purpose: The template allows copying the value from last test run to test in test set.
For example: each time the test is executed, the user wants the value of Duration
field of the run to be copied to the Expected Duration user-defined field of test in test
set.
Code Location: code should be added to the code of Test Lab workflow script
Templates Used: templates 2.1.1, 2.1.2
Arguments:
strSrcRunField – The name of the Run field from which the value should be
copied.
strTrgTSTestField – The name of the Test in Test Set field to which the value
should be copied.
Return Value: None

Code Template:

Sub CopyLastRunValue(strSrcRunField, strTrgTSTestField)


On Error Resume Next
Dim iTestSetId, iTSTestId, objTestSet, objTSTest, objLastRun
iTestSetId = TestSetTest_Fields("TC_CYCLE_ID").Value
iTSTestID = TestSetTest_Fields("TC_TEST_ID").Value
Set objTestSet = TDConnection.TestSetFactory.Item(iTestSetId)
Set objTSTest = objTestSet.TSTestFactory.Item(iTSTestID)
Set objLastRun = objTSTest.LastRun
If objLastRun.Field(strSrcRunField) <>
TestSetTest_Fields(strTrgTSTestField).Value Then
TestSetTest_Fields(strTrgTSTestField).Value =
LastRunObject.Field(strSrcRunField)
End If
Set objTestSet = Nothing
Set objTSTest = Nothing
Set objLastRun = Nothing
PrintError “CopyLastRunValue”
On Error GoTo 0
End Sub
Template 3.8

Usage Example: In the following example the user has Expected Duration field for
Test in Test Set (TC_USER_01). The value of this field is updated any time the value
of Duration field (RN_DURATION) of the last run differs from Expected Duration of
the test.

Sub TestLab_TestSetTests_MoveTo
On Error Resume Next
CopyLastRunValue "TC_USER_01", "RN_DURATION"
On Error GoTo 0
End Sub

You might also like