Visualising manual test execution distribution
The Quality Center (QC) Open Test Architecture (OTA) API is a COM library that enables you to integrate external applications with Quality Center. This article focuses on how you can generate customised reports with the use of OTA and Python.
Even though QC provides reporting and they are customizable with DB query, the default reports are rigid and the representation of the data may not suit your need. In some cases, you may want to manipulate data as well. For example, building a search library using the data retrieved from QC, allowing you to quickly search a project for an automated test associated with a manual test or vice versa.
In our implementation, we decided to use OTA with Python as the language of choice because it is faster to manipulate complex data structure as compared to VBScript.
Preparation
1. Install Python for Windows. You can find the installation file from the Python website at http://www.python.org/getit/windows/ .
2. Install the OTA COM library (TDConnect.exe).
Script breakdown
Below are snippets of Python code used to grab data from QC. The individual steps are explained.
1. Import the necessary libraries.
- win32com - TDConnect object that we will be accessing to communicate with QC.
- codecs - Allows us to format the text in various encoding.
- re - Allow us to use regular expression.
- json - Allow us to dump data in json format.
import win32com
from win32com.client import Dispatch
import codecs
import re
import json
2. Initialising variables. These include the URL to QC, credentials, QC project names, and QC domain.
# Login Credentials
qcServer = "http://qcserver/qcbin/"
qcUser = "user"
qcPassword = "password"
qcDomain = "MyDomain"
projects = ["Project1","Project2"]
DataFile = "data.js"
3. Connecting to QC. The most important bits are those in bold below.
testdict = {}
for project in projects:
# Do the actual login
td = win32com.client.Dispatch("TDApiOle80.TDConnection.1")
td.InitConnectionEx(qcServer)
td.Login(qcUser,qcPassword)
td.Connect(qcDomain,project)
if td.Connected == True:
print "System: Logged in to " +project
else:
print "Connect failed to " +project
4. Once you have the td connection, you can pretty much grab any stats you want from QC.
In our example below, we access the RunFactory object to grab all the tests ran. Once, we grabbed the tests, we grab statistics on run duration, total runs, and average duration. These are separated by individual projects. In addition, we have also calculated the time taken to complete a test set.
runFactory = td.RunFactory
runFilter = runFactory.Filter
testFactory = td.TestFactory
testFilter = testFactory.Filter
# Query the Test Factory
testdict[project] = {}
for run in runFactory.NewList(""):
testset = run.TestSetId
try:
testFilter.SetFilter("TS_TEST_ID", run.TestId)
test = testFactory.NewList(testFilter.Text).Item(1).Name
except:
print "Something wrong with Test Id: " + run.TestId
if testset in testdict[project]:
if test in testdict[project][testset]["Tests"]:
if run.Field("RN_DURATION") is not None:
testdict[project][testset]["Tests"][test]["Tot_Duration"] += run.Field("RN_DURATION")
testdict[project][testset]["Tests"][test]["Tot_Runs"] += 1
testdict[project][testset]["Tests"][test]["Avg_Duration"] = testdict[project][testset]["Tests"][test]["Tot_Duration"]/testdict[project][testset]["Tests"][test]["Tot_Runs"]
else:
testdict[project][testset]["Tests"][test] = {}
if run.Field("RN_DURATION") is not None:
testdict[project][testset]["Tests"][test]["Tot_Duration"] = run.Field("RN_DURATION")
testdict[project][testset]["Tests"][test]["Tot_Runs"] = 1
testdict[project][testset]["Tests"][test]["Avg_Duration"] = run.Field("RN_DURATION")
if run.Field("RN_DURATION") is not None:
testdict[project][testset]["TotalDuration"] += run.Field("RN_DURATION")
testdict[project][testset]["TotalRun"] += 1
else:
testdict[project][testset] = {}
testdict[project][testset]["Tests"] = {}
testdict[project][testset]["TotalDuration"] = 0
testdict[project][testset]["TotalRun"] = 0
5. Finally, clean up! We disconnect from td and close the file handler after dumping data out in JSON format.
if td.Connected == True:
td.Disconnect
td.Logout
print "System: Logged out from " +project
td = None
fh = codecs.open(DataFile, 'w', encoding="utf-8")
fh.writelines (json.dumps(testdict))
fh = None
For more information about OTA API, you can refer to the OTA API Reference document.
One application of using the Python OTA is visualising manual test execution distribution data. In a large project with many testers, it is hard to identify which manual test is executed most often. Thus, it is more difficult to identify good candidates for automation. Using the above code, we produced two sets of data. One is the execution data with run duration, total runs, and average duration. The second set of data is path data with test set ID and their path in test lab.
Execution Data (data.js)
Path Data (path.js)
JavaScript can pick up the exported data and do data massaging. Path data is mainly used for building the navigation tree, while the execution data is used to draw the chart. Clicking on a node in the navigation pane would update the distribution chart on the right of the screen.
The exported data is JavaScript code which assigns a variable to the JSON object.
// Data.js
var executionData = {"Project_Name": {"8192": {"TotalRun": 0, "Tests": {}, "TotalDuration": 0}, "8193": {"TotalRun": 0, "Tests": {}, …}
This executionData variable then can be accessed directly via JavaScript.
JQuery then can be used to draw the JS file directly without doing evaluation of the code.
$.getScript("data.js", function(data, textStatus, jqxhr) {
$.getScript("path.js", function(data, textStatus, jqxhr) { … // Process and display chart … } }
Looking at the chart, the test with the higher number of “Total Run Count” and higher number of “Total Run Duration” are good candidates for automation. After identifying these tests, it is necessary to discuss with the test owner to verify the finding and discuss among testers and team leaders to prioritize automation effort accordingly.
Tech tips from JDS

Browser Console
Read More

Glide Variables
Read More

Understanding Database Indexes in ServiceNow
Read More

Fast-track ServiceNow upgrades with Automated Testing Framework (ATF)
Read More

Read More

Splunk .conf18
Read More

ServiceNow Catalog Client Scripts: G_Form Clear Values
Read More

Is DevPerfOps a thing?
Read More

The benefits of performance testing with LoadRunner
Read More

Monitoring Atlassian Suite with AppDynamics
Read More

5 quick tips for customising your SAP data in Splunk
Read More

How to maintain versatility throughout your SAP lifecycle
Read More

How to revitalise your performance testing in SAP
Read More

Reserve and import data through Micro Focus ALM
Read More

How to effectively manage your CMDB in ServiceNow
Read More

ServiceNow and single sign-on
Read More

How to customise the ServiceNow Service Portal
Read More

Integrating a hand-signed signature to an Incident Form in ServiceNow
Read More

Integrating OMi (Operations Manager i) with ServiceNow
Read More

Implementing an electronic signature in ALM
Read More

Service portal simplicity
Read More

Learning from real-world cloud security crises
Read More

Static Variables and Pointers in ServiceNow
Read More

Citrix and web client engagement on an Enterprise system
Read More

Understanding outbound web services in ServiceNow
Read More

How to solve SSL 3 recording issues in HPE VuGen
Read More

How to record Angular JS Single Page Applications (SPA)
Read More

Calculating Pacing for Performance Tests
Read More

Vugen and GitHub Integration
Read More

What’s new in LoadRunner 12.53
Read More

Filtered Reference Fields in ServiceNow
Read More

ServiceNow performance testing tips
Read More

Monitor Dell Foglight Topology Churn with Splunk
Read More

Straight-Through Processing with ServiceNow
Read More

Splunk: Using Regex to Simplify Your Data
Read More

ServiceNow Choice List Dependencies
Read More

Tips for replaying RDP VuGen scripts in BSM or LoadRunner
Read More

Incorporating iSPI metric reports into MyBSM dashboard pages
Read More

Using SV contexts to simulate stored data
Read More

What’s new in LoadRunner 12.02
Read More

Recycle Bin for Quality Center
Read More

LoadRunner Correlation with web_reg_save_param_regexp
Read More

LoadRunner 11.52
Read More

QC for Testers – Quiz
Read More

Agile Performance Tuning with HP Diagnostics
Read More

What’s new in HP Service Virtualization 2.30
Read More

Understanding LoadRunner Virtual User Days (VUDs)
Read More

Problems recording HTTPS with VuGen
Read More

Improving the management and efficiency of QTP execution
Read More

Performance testing Oracle WebCenter with LoadRunner
Read More

Generating custom reports with Quality Center OTA using Python
Read More

Asynchronous Communication: Scripting For Cognos
Read More

How to fix common VuGen recording problems
Read More

Monitoring Active Directory accounts with HP BAC
Read More

URL Attachments in Quality Center
Read More

What’s new in LoadRunner 11.00?
Read More

Restore old License Usage stats after upgrading Quality Center
Read More

Changing LoadRunner/VuGen log options at runtime
Read More

Restricting large attachments in Quality Center
Read More

Retrieving Quality Center user login statistics
Read More

A comparison of open source load testing tools
...
Read More

Worst practices in performance testing
Read More

LoadRunner Sales Questions
Read More

LoadRunner Analysis: Hints and tips
Read More

LoadRunner in Windows 7
HP Loadrunner 11 is now available. This new version now natively supports Windows 7 and Windows Server 2008. I ...
Read More

Using the QuickTest Professional “commuter” license
Read More

Installing HP Diagnostics
Read More

Understanding LoadRunner licensing
Read More

VuGen scripting for YouTube video
Read More

Creating a Web + MMS vuser
Read More

Why you should use backwards dates
Read More

How to get the host’s IP address from within VuGen
Read More

VuGen scripting for BMC Remedy Action Request System 7.1
Read More

Unique usernames for BPM scripts
Read More

Mapping drives for LoadRunner Windows monitoring
Read More

VuGen feature requests
Read More

LoadRunner script completion checklist
Read More

Querying Quality Center user roles
Read More

Querying the Quality Center Database
Read More

HPSU 2009 Presentation – Performance Testing Web 2.0
Read More

Scaling HP Diagnostics
Read More

Global variables aren’t really global in LoadRunner
Read More

Client-side certificates for VuGen
Read More

Detect malicious HTML/JavaScript payloads with WebInspect (e.g. ASPROX, Gumblar, Income Iframe)
Read More

VuGen code snippets
Read More

Integrating QTP with Terminal Emulators
Read More

Why you must add try/catch blocks to Java-based BPM scripts
Read More

Querying a MySQL database with LoadRunner
Read More

ANZTB 2009 Presentation: Performance Testing Web 2.0
Read More

How to make QTP “analog mode” steps more reliable
Read More

Testing multiple browsers in a Standardized Operating Environment (SOE)
Read More

DNS-based load balancing for virtual users
Read More

What’s new in LoadRunner 9.50?
Read More

Calculating the difference between two dates or timestamps
Read More

The “is it done yet” loop
Read More

Think time that cannot be ignored
Read More

Understanding aggregate variance within LoadRunner analysis
Read More

Load balancing vusers without a load balancer
Read More

Harvesting file names with VuGen
Read More

Parameterising Unix/Posix timestamps in VuGen
Read More

HP Software trial license periods
Read More

How to handle HTTP POSTs with a changing number of name-value pairs
Read More

VuGen string comparison behaviour
Read More

Persistent data in VuGen with MySQL
Read More

How to write a Performance Test Plan
Read More

Unable to add virtual machine
To get ...
Read More

LoadRunner scripting languages
Read More

WDiff replacement for VuGen
Read More

Testing web services with a standard Web Vuser
Read More

Why your BPM scripts should use Download Filters
Read More

Querying your web server logs
Read More

Importing IIS Logs into SQL Server
Read More

QTP “Uninstall was not completed” problem
Read More

VuGen correlation for SAP Web Dynpro
Read More

How to save $500 on your HP software license
Read More

Testing and monitoring acronyms
Read More

Solving VuGen script generation errors
Read More

An introduction to SiteScope EMS Topology
Read More

Using the BAC JMX Console
Read More
When I ran the script I am getting the following error:
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
com_error: (-2147221164, ‘Class not registered’, None, None)
–> td = win32com.client.Dispatch(“TDApiOle80.TDConnection.1”)
When i run the code in the 4th section, i am not getting anything the script needs to be manually interrupted. Plz help
Thank you for your comment. Unfortunately, this post is now more than five years old, so while the code included may be used as a guideline, it will likely be ineffective if simply copied and pasted. JDS continues to provide excellent services for IT departments and companies all over the world using Quality Center. If you are interested in hearing more about our services or getting information about how we can test and provide custom code for your business, please get in touch with us at contactus@jds.net.au.
Hi. Such a great article, but there seems to be some missing code. the path.js part is missing completely. Could you possibly show us? Also, how did you generate the graphs, this would be a great addition for me. Thanks
Thank you for your comment. Unfortunately, this post is now more than five years old, so while the code included may be used as a guideline, it will likely be ineffective if simply copied and pasted. JDS continues to provide excellent services for IT departments and companies all over the world using Quality Center. If you are interested in hearing more about our services or getting information about how we can test and provide custom code for your business, please get in touch with us at contactus@jds.net.au.
The code is really nice one, its working perfectly well with my requirement, one thing I wanted to ask is, after testcase execution is finished I want to attach a result file to testcase. Currently I am doing it with below code,
attachmentPath = test.Attachments
nowAttachment = attachmentPath.AddItem(None)
nowAttachment.FileName = file_name
nowAttachment.Type = 1
nowAttachment.Post()
But problem is even if the name of file is same its not overwriting with existing file, intern it creates new file itself, how to fix this. thank you.
Can we programatically fetch the already existing reports in Quality Center(10.0)?
we have all reports defined, and have to publish these reports daily onto confluence pages!
Any help regarding this would be deeply appreciated.
Could you please give me advise, how to implement the similar script for automatically generate the test’s status report?
As a result I need to get the report that include next fild: “test_name”, status of the test (“pass”, “fail”, “not complete”, “not run”) and “tester_name”.
Hope for your experience and look forward to for your advice.
Best regards,
Lena