To handle those scenarios QualityCentre comes with an API that a project can use to sync up other tools with QualityCentre. This API is called Open Test Architecture (OTA). You may notice QuickTest Professional and Quality Centre also uses this API to speak to each other. Another example is, people exporting bulk tests/ defects/ requirements in to QualityCentre from excel. This process also uses OTA in the background. However for this API the entry point is TDconnect.exe. You can download this exe file from internet by google'ing for it. Once you install this you will have the flexibility to use this in Excel or use the references/ API's in any other programming languages.
This way user can directly play with the database that the Quality Centre is running on without opening the GUI for it. You can literally perform every function that you can perform by logging on to its console, like
- Logging in to QC
- Find specific details about a Defect/ Requirement/ Test/ TestSet
- Filtering Tests/ defects/ Requirements etc
- Perform CRUD operations on Requirements/Tests/ TestSets/ Runs/ Defects etc
- Also create links between Requirements > Tests, Tests > TestSets, TestSets > Defects and so on
In order to perform most of the above mentioned stuff you would need to know the database structure/ schema so you know which table, which column to hit to get a value associated with a particular field in QC. Database schema is all open for everyone to know and is available on-line as well.
If you have Quality Centre installed on your machine, you can find the OTA reference guide, OTA database guide, and OTA custom type help files in your help folder. Alternatively, you can hit Help and then go to documentation page where you should get all this documentation ready available for you to either reference or download. In these help files you should see a good set of examples for each and every class module that we can use. an Example code to connect to QC is found as below:
Exmaple1: How to Connect to Quality Centre using OTA API
Private Function makeConnection(ByVal qcHostName$, qcDomain$, qcProject$, _
qcUser$, qcPassword$, Optional qcPort) As Boolean
'------------------------------------------------------------------------
' This routine makes the connection to the gobal TDConnection object,
' declared at the project level as Global tdc as TDConnection,
' and connects the user to the specified project.
'-----------------------------------------------------------------------
Dim qcServer As String
Const fName = "makeConnection" 'For error message
On Error GoTo makeConnectionErr
errmsg = ""
'Construct server argument of format "http://server:port/qcbin"
qcServer = "http://" & qcHostName
If Not (IsMissing(qcPort)) Then
If Len(qcPort) > 0 Then qcServer = qcServer & ":" & qcPort
End If
qcServer = qcServer & "/qcbin"
''Check status (For illustrative purposes.)
' 'MsgBox tdc.LoggedIn 'Error: OTA Server is not connected
' MsgBox tdc.Connected 'False
' MsgBox tdc.ServerName 'Blank string
'Create the connection
errmsg = "Failed to create TDConnection"
If (tdc Is Nothing) Then Set tdc = New TDConnection
If (tdc Is Nothing) Then GoTo makeConnectionErr
errmsg = ""
tdc.InitConnectionEx qcServer
''Check status.
' MsgBox tdc.LoggedIn 'False
' MsgBox tdc.Connected 'True
' MsgBox tdc.ServerName 'http:///qcbin/wcomsrv.dll
'Log on to server
tdc.Login qcUser, qcPassword
''Check status.
' MsgBox tdc.LoggedIn 'True
' MsgBox tdc.ProjectName 'Empty String
' MsgBox tdc.ProjectConnected 'False
' Connect to the project and user
tdc.Connect qcDomain, qcProject
' MsgBox tdc.ProjectName 'qcProject
' MsgBox tdc.ProjectConnected 'True
' Exit status
makeConnection = SUCCESS
Exit Function
makeConnectionErr:
ErrHandler err, fName, err.Description & vbCrLf & errmsg
makeConnection = FAILURE
End Function
Here you can customise this to be a public function and create an object as in QcObject to connect to Quality Centre and set it to Nothing once the job is done. Some issues I have encountered while working with OTA API is if you keep connected to the object and working away for long time, you may get Automation Error: suggesting Quality Centre connections is no more available or something similar to this. Its always suggested to connect to it before performing an operation and close the connection once the job done and so on.qcUser$, qcPassword$, Optional qcPort) As Boolean
'------------------------------------------------------------------------
' This routine makes the connection to the gobal TDConnection object,
' declared at the project level as Global tdc as TDConnection,
' and connects the user to the specified project.
'-----------------------------------------------------------------------
Dim qcServer As String
Const fName = "makeConnection" 'For error message
On Error GoTo makeConnectionErr
errmsg = ""
'Construct server argument of format "http://server:port/qcbin"
qcServer = "http://" & qcHostName
If Not (IsMissing(qcPort)) Then
If Len(qcPort) > 0 Then qcServer = qcServer & ":" & qcPort
End If
qcServer = qcServer & "/qcbin"
''Check status (For illustrative purposes.)
' 'MsgBox tdc.LoggedIn 'Error: OTA Server is not connected
' MsgBox tdc.Connected 'False
' MsgBox tdc.ServerName 'Blank string
'Create the connection
errmsg = "Failed to create TDConnection"
If (tdc Is Nothing) Then Set tdc = New TDConnection
If (tdc Is Nothing) Then GoTo makeConnectionErr
errmsg = ""
tdc.InitConnectionEx qcServer
''Check status.
' MsgBox tdc.LoggedIn 'False
' MsgBox tdc.Connected 'True
' MsgBox tdc.ServerName 'http://
'Log on to server
tdc.Login qcUser, qcPassword
''Check status.
' MsgBox tdc.LoggedIn 'True
' MsgBox tdc.ProjectName 'Empty String
' MsgBox tdc.ProjectConnected 'False
' Connect to the project and user
tdc.Connect qcDomain, qcProject
' MsgBox tdc.ProjectName 'qcProject
' MsgBox tdc.ProjectConnected 'True
' Exit status
makeConnection = SUCCESS
Exit Function
makeConnectionErr:
ErrHandler err, fName, err.Description & vbCrLf & errmsg
makeConnection = FAILURE
End Function
Exmaple2:How to Use Filter method to filter the results (Bug Factory)
Sub BugFilter()
Dim BugFact As BugFactory
Dim BugFilter As TDFilter
Dim BugList As list
Dim theBug As Bug
Dim i%, msg$
'Get the bug factory filter
'tdc is the global TDConnection object.
Set BugFact = tdc.BugFactory
Set BugFilter = BugFact.Filter
'Set the filter values
BugFilter.Filter("BG_STATUS") = "Closed"
BugFilter.Order("BG_PRIORITY") = 1
MsgBox BugFilter.Text
'Create a list of defects from the filter
' and show a few of them
Set BugList = BugFilter.NewList
msg = "Number of defects = " & BugList.Count & Chr(13)
For Each theBug In BugList
msg = msg & theBug.ID & ", " & theBug.Summary & ", " _
& theBug.Status & ", " & theBug.Priority & Chr(13)
i = i + 1
If i > 10 Then Exit For
Next
MsgBox msg
End Sub
Dim BugFact As BugFactory
Dim BugFilter As TDFilter
Dim BugList As list
Dim theBug As Bug
Dim i%, msg$
'Get the bug factory filter
'tdc is the global TDConnection object.
Set BugFact = tdc.BugFactory
Set BugFilter = BugFact.Filter
'Set the filter values
BugFilter.Filter("BG_STATUS") = "Closed"
BugFilter.Order("BG_PRIORITY") = 1
MsgBox BugFilter.Text
'Create a list of defects from the filter
' and show a few of them
Set BugList = BugFilter.NewList
msg = "Number of defects = " & BugList.Count & Chr(13)
For Each theBug In BugList
msg = msg & theBug.ID & ", " & theBug.Summary & ", " _
& theBug.Status & ", " & theBug.Priority & Chr(13)
i = i + 1
If i > 10 Then Exit For
Next
MsgBox msg
End Sub
Exmaple3:Find a specified requirement in a specified folder
Public Function GetReqByPath(fullPath$, _
Optional delimChar As String = "\") _
As Req
' This function returns a Req object specified by its
' full path.
' For example:
' Set r = GetReqByPath("SCRATCH\OTA_REQ_DEMO\OTA_S_O_1")
' will return the OTA_S_O_1 object.
' A requirement name is not unique in the project, but it is
' unique as a direct child of another requirement.
' Therefore, these routine works by walking down the
' requirement tree along the fullPath until the requirement
' is found at the end of the path.
' If a backslash is not used as the folder delimiter, any other
' character can be passed in the delimChar argurment.
Dim rFact As reqFactory
Dim theReq As Req, ParentReq As Req
Dim reqList As list
Dim NodeArray() As String, PathArray() As String
Dim WorkingDepth As Integer
On Error GoTo GetReqByPathErr
'Trim the fullPath and strip leading and trailing delimiters
fullPath = Trim(fullPath)
Dim pos%, ln%
pos = InStr(1, fullPath, delimChar)
If pos = 1 Then
fullPath = Mid(fullPath, 2)
End If
ln = Len(fullPath)
pos = InStr(ln - 1, fullPath, delimChar)
If pos > 0 Then
fullPath = Mid(fullPath, 1, ln - 1)
End If
' Get an array of requirements, and the length
' of the path
NodeArray = Split(fullPath, delimChar)
WorkingDepth = LBound(NodeArray)
' Walk down the tree
'tdc is the global TDConnection object.
Set rFact = tdc.reqFactory
For WorkingDepth = LBound(NodeArray) To UBound(NodeArray)
'First time, find under the root (-1)
'After that, under the previous requirement found: ParentReq.ID
If WorkingDepth = LBound(NodeArray) Then
Set reqList = rFact.Find(-1, "RQ_REQ_NAME", _
NodeArray(WorkingDepth), TDREQMODE_FIND_EXACT)
Else
Set reqList = rFact.Find(ParentReq.ID, "RQ_REQ_NAME", _
NodeArray(WorkingDepth), TDREQMODE_FIND_EXACT)
End If
' Delete parent. Each loop has to find it again.
Set ParentReq = Nothing
Dim strItem, reqID&, strID$, thePath$
For Each strItem In reqList
' The List returned from ReqFactory.Find is a List
' of strings of format ID,Name.
' For example "9,Products/Services On Sale"
' Extract the ID from the string by splitting the
' string at the comma.
pos = InStr(strItem, ",")
strID = Mid(strItem, 1, pos - 1)
' Convert the ID to a long, and get the object
reqID = CLng(strID)
Set theReq = rFact.Item(reqID)
'Now check that the object is at the correct depth.
'If so, we've found the requirement. On the next loop,
'we'll look from here down.
thePath = theReq.Path
PathArray = Split(thePath, "\")
' Debug.Print "Number of elements is " & UBound(PathArray)
' Debug.Print theReq.ID, theReq.Name
If UBound(PathArray) = WorkingDepth Then
Set ParentReq = theReq
Exit For
End If
Next strItem
If ParentReq Is Nothing Then Exit For
Next WorkingDepth
Set GetReqByPath = ParentReq
Exit Function
GetReqByPathErr:
ErrHandler err, "GetReqByPath"
Set GetReqByPath = Nothing
End Function
Optional delimChar As String = "\") _
As Req
' This function returns a Req object specified by its
' full path.
' For example:
' Set r = GetReqByPath("SCRATCH\OTA_REQ_DEMO\OTA_S_O_1")
' will return the OTA_S_O_1 object.
' A requirement name is not unique in the project, but it is
' unique as a direct child of another requirement.
' Therefore, these routine works by walking down the
' requirement tree along the fullPath until the requirement
' is found at the end of the path.
' If a backslash is not used as the folder delimiter, any other
' character can be passed in the delimChar argurment.
Dim rFact As reqFactory
Dim theReq As Req, ParentReq As Req
Dim reqList As list
Dim NodeArray() As String, PathArray() As String
Dim WorkingDepth As Integer
On Error GoTo GetReqByPathErr
'Trim the fullPath and strip leading and trailing delimiters
fullPath = Trim(fullPath)
Dim pos%, ln%
pos = InStr(1, fullPath, delimChar)
If pos = 1 Then
fullPath = Mid(fullPath, 2)
End If
ln = Len(fullPath)
pos = InStr(ln - 1, fullPath, delimChar)
If pos > 0 Then
fullPath = Mid(fullPath, 1, ln - 1)
End If
' Get an array of requirements, and the length
' of the path
NodeArray = Split(fullPath, delimChar)
WorkingDepth = LBound(NodeArray)
' Walk down the tree
'tdc is the global TDConnection object.
Set rFact = tdc.reqFactory
For WorkingDepth = LBound(NodeArray) To UBound(NodeArray)
'First time, find under the root (-1)
'After that, under the previous requirement found: ParentReq.ID
If WorkingDepth = LBound(NodeArray) Then
Set reqList = rFact.Find(-1, "RQ_REQ_NAME", _
NodeArray(WorkingDepth), TDREQMODE_FIND_EXACT)
Else
Set reqList = rFact.Find(ParentReq.ID, "RQ_REQ_NAME", _
NodeArray(WorkingDepth), TDREQMODE_FIND_EXACT)
End If
' Delete parent. Each loop has to find it again.
Set ParentReq = Nothing
Dim strItem, reqID&, strID$, thePath$
For Each strItem In reqList
' The List returned from ReqFactory.Find is a List
' of strings of format ID,Name.
' For example "9,Products/Services On Sale"
' Extract the ID from the string by splitting the
' string at the comma.
pos = InStr(strItem, ",")
strID = Mid(strItem, 1, pos - 1)
' Convert the ID to a long, and get the object
reqID = CLng(strID)
Set theReq = rFact.Item(reqID)
'Now check that the object is at the correct depth.
'If so, we've found the requirement. On the next loop,
'we'll look from here down.
thePath = theReq.Path
PathArray = Split(thePath, "\")
' Debug.Print "Number of elements is " & UBound(PathArray)
' Debug.Print theReq.ID, theReq.Name
If UBound(PathArray) = WorkingDepth Then
Set ParentReq = theReq
Exit For
End If
Next strItem
If ParentReq Is Nothing Then Exit For
Next WorkingDepth
Set GetReqByPath = ParentReq
Exit Function
GetReqByPathErr:
ErrHandler err, "GetReqByPath"
Set GetReqByPath = Nothing
End Function
Exmaple4:How to Create a Test using OTA
'Get or create test plan subject folder
errmsg = "Subject tree error"
Set root = TreeMgr.TreeRoot("Subject")
On Error Resume Next
Set folder = root.FindChildNode(FolderName)
On Error GoTo LinkDefectsToEntitiesErr
If folder Is Nothing Then _
Set folder = root.AddNode(FolderName)
'Create a design test
errmsg = "Design test error"
'Get the test if it exists
' For the code of GetTest, see the Test object example
' "Get a test object with name and path"
Set NewTest = GetTest(TestName, FolderName)
'If it doesn't exist, create it
If NewTest Is Nothing Then
Set NewTest = TestF.AddItem(Null)
NewTest.Name = TestName
NewTest.Type = "MANUAL"
'Put the test in the new subject folder
NewTest.Field("TS_SUBJECT") = folder.NodeID
NewTest.Post
End If
'Get or create a design step from the factory of the new test
errmsg = "Design step error"
Set StepF = NewTest.DesignStepFactory
Dim aFilter As TDFilter
Set aFilter = StepF.Filter
Dim StepName$
StepName = TestName & "Step_1"
aFilter.Filter("DS_STEP_NAME") = StepName
Set lst = StepF.NewList(aFilter.Text)
If lst.Count = 0 Then
Set desStep = StepF.AddItem(Null)
desStep.StepName = StepName
desStep.StepDescription = "Step to be linked to defect."
desStep.StepExpectedResult = "This step expected to be linked."
desStep.Post
Else
Set desStep = lst.Item(1)
End If
errmsg = "Subject tree error"
Set root = TreeMgr.TreeRoot("Subject")
On Error Resume Next
Set folder = root.FindChildNode(FolderName)
On Error GoTo LinkDefectsToEntitiesErr
If folder Is Nothing Then _
Set folder = root.AddNode(FolderName)
'Create a design test
errmsg = "Design test error"
'Get the test if it exists
' For the code of GetTest, see the Test object example
' "Get a test object with name and path"
Set NewTest = GetTest(TestName, FolderName)
'If it doesn't exist, create it
If NewTest Is Nothing Then
Set NewTest = TestF.AddItem(Null)
NewTest.Name = TestName
NewTest.Type = "MANUAL"
'Put the test in the new subject folder
NewTest.Field("TS_SUBJECT") = folder.NodeID
NewTest.Post
End If
'Get or create a design step from the factory of the new test
errmsg = "Design step error"
Set StepF = NewTest.DesignStepFactory
Dim aFilter As TDFilter
Set aFilter = StepF.Filter
Dim StepName$
StepName = TestName & "Step_1"
aFilter.Filter("DS_STEP_NAME") = StepName
Set lst = StepF.NewList(aFilter.Text)
If lst.Count = 0 Then
Set desStep = StepF.AddItem(Null)
desStep.StepName = StepName
desStep.StepDescription = "Step to be linked to defect."
desStep.StepExpectedResult = "This step expected to be linked."
desStep.Post
Else
Set desStep = lst.Item(1)
End If
Reference: OTA COM 9.0 Type Library
Note: You can find a list of open source tools that're currently available by searching for them on the internet. I found this link on the net http://www.software-pointers.com/en-defecttracking-opensource-tools.html
Hi. Great info. I need to create links between Requirements and Tests from Excel. ¿Dou you know where can i get some examples? Thank you.
ReplyDeleteHi Thanks for the information. I need to use OTA to upload attachments to test instance in QC. I am receving OTA Server not connected error while trying to use Attachment property. Please advice.
ReplyDeleteNice information , Having a place empty, want to rent and looking for a best channel manager for vacation rentals. Su here is to help you out to gain the best of all. Su here is to help you out to gain the best of all.
ReplyDeletebest channel manager for vocation rentals