Yesterday I cleaned up and posted my example QCIntegration utility on GitHub.
While it works as a standalone tool, some people might not want to wade through the code to understand or modify it. So today, I’m going to try to explain how the OTA API works by recreating the steps as a blog post with explanation in a simple script.
I’ll start with an example using C# and then give an equivalent Python example. I’ll use the same scenario, updating test case results in QC, but if requested, I can also show how to get test steps from a test plan, or read & update defects in QC using the OTA library.
First, create a new project in Visual Studio (or SharpDevelop). You’ll need to add the OTAClient.dll as a reference. It is a COM library and contains the single interface TDConnection.
When searching for the library name it is called the “OTA COM Type Library”. The package is “TDApiOle80.” Since it is a COM library, it needs to use an interop for C#, but this is handled automatically by the IDE.
using TDAPIOLELib; TDConnection conn = new TDConnection();
Now, let’s create a connection to your Quality Center server. You’ll need to know the URL of your QC Server and have valid login credentials with access to an existing Domain and Project.
Assuming you have quality center installed on your local machine (not a typical setup) you might have the following setup:
string qcUrl = "http://localhost:8080/qcbin"; string qcDomain = "oneshore"; string qcProject = "qa-site"; string qcLoginName = "aaron"; string qcPassword = "secret";
Note: I do not use this same password for my bank account
There are several ways to log in, but I’ll use the simplest here:
tdConn.InitConnectionEx(qcUrl); tdConn.ConnectProjectEx(qcDomain, qcProject, qcLoginName, qcPassword);
Now you need to find your test sets that need updated. I typically use folder structure that goes something like:
Project – Iteration – Component – Feature
It’s a bit convoluted but here’s the code to get a testSet:
string testFolder = "Root\QASite\Sprint5\Dashboard\Recent Updates"; string testSet = "Recent Updates - New Defects Logged"; TestSetFactory tsFactory = (TestSetFactory)tdConn.TestSetFactory; TestSetTreeManager tsTreeMgr = (TestSetTreeManager)tdConn.TestSetTreeManager; TestSetFolder tsFolder = (TestSetFolder)tsTreeMgr.get_NodeByPath(testFolder); List tsList = tsFolder.FindTestSets(testSetName, false, null);
The parameters for FindTestSets are a pattern to match, whether to match case, and a filter. Since I’m looking for a specific test set, I don’t bother with the other two parameters.
You could easily get a list of all test sets that haven’t been executed involving the recent updates feature by substituting this line:
List tsList = tsFolder.FindTestSets("recent updates", true, "status=No Run");
Now we want to loop through the test set and build a collection of tests to update. Note that we might have more than one test set in the folder and one or more subfolders as well:
foreach (TestSet testSet in tsList)
{
TestSetFolder tsFolder = (TestSetFolder)testSet.TestSetFolder;
TSTestFactory tsTestFactory = (TSTestFactory)testSet.TSTestFactory;
List tsTestList = tsTestFactory.NewList("");
And finally, update each test case status:
foreach (TSTest tsTest in tsTestList)
{
Run lastRun = (Run)tsTest.LastRun;
// don't update test if it may have been modified by someone else
if (lastRun == null)
{
RunFactory runFactory = (RunFactory)test.RunFactory;
String date = DateTime.Now.ToString("yyyyMMddhhmmss");
Run run = (Run)runFactory.AddItem("Run" + date);
run.Status = "Pass";
run.Post();
}
} // end loop of test cases
} // end outer loop of test sets
Of course you might want to add your actual test results. If you have a dictionary of test names and statuses, you can simply do this:
Dictionary testResults = new Dictionary();
testResults.Add("New defects in Recent Updates are red", "Pass");
testResults.Add("Resolved defects in Recent Updates are green", "Pass");
testResults.Add("Reopened defects in Recent Updates are bold", "Fail");
if (testResults.ContainsKey(tsTest.TestName))
{
string status = testResults[tsTest.TestName];
recordTestResult(tsTest, status);
}
That’s all for now. I’ll translate the example into Python tomorrow, but you’ll see it’s really quite straightforward.

[...] and writing to a log file. It can then use the Quality Center integration tool I described in an earlier post, though I’m planning on wiring it all together eventually, so anyone can run tests [...]
By: Running NUnit tests programmatically « Fiji Ecuador Seattle Greece Montana on November 22, 2011
at 11:05 am
Hi,
I have to Transfer some Result files to QC on particular TC.
By: vinay on January 30, 2012
at 4:21 am
[...] http://fijiaaron.wordpress.com/2011/11/16/upload-seleniumjunit-test-results-to-quality-center/ http://fijiaaron.wordpress.com/2011/11/17/updating-test-results-in-qc-using-the-qc-ota-api-explained… [...]
By: Selenium QC integration summary « Fiji Ecuador Seattle Greece Montana on February 2, 2012
at 8:51 am
[...] JUnit with HP Quality Center part 2 Upload Selenium/JUnit test results to Quality Center Updating test results in QC using the QC OTA APK explained Getting a QC test coverage report from [...]
By: Selenium QC integration update « Fiji Ecuador Seattle Greece Montana on February 2, 2012
at 8:58 am
Hi Aaron,
Thanks a lot for your post.It was really helpful for me as I am just entering in the QC world.I have 4 custom fields in QC test instance properties ie OS,Locale,prod version and IE version. I am trying to do something as below but getting an error saying “Field not present”.
RunFactory runFactory = (RunFactory)test.RunFactory;
String date = DateTime.Now.ToString(“yyyyMMddhhmmss”);
Run run = (Run)runFactory.AddItem(“Run” + date);
run["IE Version"]=”IE 9.0″;
run["OS"]=”Win 7 SP1 32 bit”;
run["Prod Version"]=”33″;
run["Locale"]=”En-US”;
run.Status = “Pass”;
run.Post();
By: Nitin Kumar on February 6, 2012
at 11:00 am
Hi,
I have lots of manul test cases under a test set.After executing them I have to update the results in QC. For that I am using your blog to write an exe for the same.But, in my case when I update the test status in QC manully I am asked to enter OS,IE version,Locale,Prod version. How can I add these information to the current run.I am trying to do something like this but getting error saying invalid field.
Could you help?
foreach (TSTest tsTest in tsTestList)
{
//Console.WriteLine(tsTest.Name);
Run lastRun = (Run)tsTest.LastRun;
string g = lastRun["Browser Version"].ToString(); //error
//Console.WriteLine(lastRun.Name);
RunFactory runFactory = (RunFactory)tsTest.RunFactory;
String date = DateTime.Now.ToString(“yyyyMMddhhmmss”);
Run run = (Run)runFactory.AddItem(“Run_” + date);
run.Status = status;
run["Browser Version"] = “IE 9.x”; //error
run.Post();
Console.WriteLine(status + ” ” + tsTest.Name);
}
By: Nitin on February 7, 2012
at 1:44 am
Hi,
The above issue has been resolved. Now, the isue is using above approach only the main test case is marked as “passed”, but if we open the test run instance and click on the run created by the code ,it is missing all the test steps.On the other hand if we do the same thing manually all the test steps along with the test case are marked as “passed”.
By: Nitin on February 13, 2012
at 4:26 am
how did you solve following error ?
run["Browser Version"] = “IE 9.x”; //error
By: an on March 9, 2012
at 11:51 am
Hi An,
You can do something like this to solve the issue:
1. Retreive all the fields
RunFactory rf = (RunFactory)tsTest.RunFactory;
List allfields = rf.Fields;
2. Compare allfields list elements to what you want and store them in a variable
TDField item1 = null;
foreach (TDField item in allfields)
{
if ((((FieldProperty)item.Property).UserLabel).Equals(“Browser Version”))
{
item1 = item;
}
3. At last update it with your value
run[item1.Name] = “IE 9.0″;
Hope this will help.
By: Nitin on April 17, 2012
at 6:22 am
Do you have a VBScript code for this?
By: AutoTester on March 30, 2012
at 9:15 am
Sorry, I don’t know VBScript. The COM objects and function calls should translate directly to VBScript. I’d welcome someone who knows VBscript to add a version though.
By: fijiaaron on March 30, 2012
at 9:30 am
How can I acheive the below:
the isue in using above approach is that only the main test case is marked as “passed”, but if we open the test run instance in QC and click on the run created by the code ,it is missing all the test steps.On the other hand if we do the same thing manually all the test steps along with the test case are marked as “passed”.
Thanks in advance for your help.
By: Nitin on April 17, 2012
at 6:25 am
Its a great post, preciseley what I was looking for.
Everything is working fine for me. I can later open the run result from QC. But when I close the test run QC logs out. Any idea?
By: Subhadeep on April 21, 2012
at 8:20 pm
Glad it’s working for you. Just a guess, but does your QC only allow 1 login per user at a time?
By: fijiaaron on April 24, 2012
at 8:20 am
No, we can have “multiple login per user” at a time. I am still stuck with this problem. It seems run created is in locked state. If we refresh the run from QC before opening the result, things work fine. If we dont refresh, QC trashes. I eagerly wait for your expert feedback. Thanks
By: Subhadeep on May 8, 2012
at 8:47 pm
Sorry, I don’t have any idea. I’d need much more specific information.
By: fijiaaron on May 9, 2012
at 6:14 pm