摘要:Quality Center(以下简称QC)是一款优秀的软件测试管理工具,它可以在测试的不同阶段帮助你管理你的测试,但是不同的公司对于不同类型的测试项目测试流程可能不尽相同,QC能否更好的提供服务还需要看它能否满足你的测试管理的实际需要。运用QC API可以在QC框架下通过自定义编写程序代码定制复杂的测试流程,实现更具有针对性的操作。
题记:在一次项目中,为
了加强测试管理,利用QC管理已有的测试用例,这些测试用例都记录在WORD文档中,用例格式及组织方式不尽相同,有些并没有严格按照规范书写,如何将这些用例导入到QC中,是笔者面对的一大问题。在开始这个工作前,本人对QC的底层架构和接口并不太了解,也算是从零开始,借助QC提供的帮助文档,在摸索中向着目标靠近,并达到了预期想要的结果。在这个过程中,并没有系统的对QC API进行系统的学习,大多也停留在“知其意”上,本文就这个过程略作说明,也作自我勉励,力求温故知新。
一、关于QC API
使用 QC API 可以将外部应用程序与 QC 集成,QC API 对象会公开基于 COM 的接口,通过这些接口,我们可以直接与 QC 服务器通信以执行各种测试任务。QC 用户界面将同一 API 用于其所有操作例如,连接到项目、将信息从外部应用程序导入到项目以及将信息从项目导出到外部应用程序。
我们可以通过 COM 对象将外部应用程序与 QC 项目相集成。每个对象的定义(包括其属性、方法和参数)都打包在 OTA (开放式测试架构)客户端动态链接库 (根据版本不同这个库也有所不同,我安装的9.0版本的库 OTA COM 9.0 Type Library) 中。当您的应用程序已执行了对象函数调用后,会将其发送到 QC 服务器进行处理。
要利用 QC API 将外部应用程序与 QC 集成,必须了解 QC 项目的数据库设计以及 QC API 对象模型。本文重点是对如何向 QC 中导入测试用例进行阐述,因此也仅以于此相关的部分进行说明。
二、了解 QC 项目数据结构
图1 数据表关系图
与 QC 服务器通信执行某项操作,需要对 QC 的数据如何存放有一定的了解,图1给出了项目中主要数据表之间的关系,并给出这些表相关的字段。我们要向 QC 的测试计划中加入一条测试用例,与此相关的数据表有:TEST表和DESSTEPS表。
TEST表包含项目中每个测试的信息,如测试 ID(TS_TEST_ID)、名称(TS_ NAME)和类型(TS_TYPE)等。新建测试后,会向 TEST表中添加新的一行。
表中不同字段定义各自的信息,有些是内部标识如TS_TEST_ID,有些是存储用例的直接信息,如TS_NAME,TS_DESCRIPTION等,有些则字段则记录用例额外的信息,如TS_TYPE(MANUAL、WR-AUTOMANTED),TS_EXEC_STATUS等,参照图2。
图2 TEST表字段与QC中各字段的对应关系
DESTEST表包含有关设计步骤的信息。设计步骤包含有关如何执行测试的详细的分步说明,包括对应用程序执行的操作、所需的输入以及预期的输出。新建设计步骤后,会向表中添加新的一行。它包含字段有TS_STEP_ID、DS_STEP_ID、DS_STEP_NAME、DS_DESCRIPTION、DS_EXPECTED等。
此外我们还可以向表中添加一定的自定义字段。
三、了解 QC API 对象模型
在 QC API 对象模型中,只有一个 COM 类(即 TDConnection)可以直接创建。所有其他对象类都通过 TDConnection 对象创建。在大多数情况下,TDConnection 创建类工厂对象。然后类工厂对象创建类的子对象。还有另外一些对象也由 TDConnection 创建,如定义字段、命令和用户权限的对象。图3说明在 QC API 对象模型中的对象创建层次结构。
图3 QC API 对象模型中的对象创建层次结构
这些对象可以划分为多种类别,这里我们主要关注对下面三类对象:实用程序类,该类别包括使用文件存储、数据库筛选和列表等资源的类。比如,在导入测试用例时,我们要对TEST数据表中的数据进行筛选,或者要获取表中当前用例名称的列表等。
数据对象,这些对象处理项目的数据元素,如TestFactory 负责测试管理,Test 负责测试计划等。数据对象与项目的数据元素是对应的,熟悉了项目数据结构后,需要对那些数据进行操作,相应的使用相关的数据对象。
系统和安全对象,下列对象用于数据库管理。这包括数据库命令、字段和字段属性、历史记录、列表以及系统树管理。
对这些对象模型有了一定的了解,便可以知道使用那些对象可以帮你完成某个操作了,具体需要用到该对象的时候再通过帮助文档查看对象的引用细节。
四、向 QC 导入用例思路分析
向 QC 导入测试用例需要完成以下几个过程:
1、连接 QC ,用户登录,选择域和项目。
2、导入用例。
1)设置树结构文件夹
A 设置根节点;
B 以根节点为父节点,在子节点搜索用例所在的文件夹,若没发现此节点,则添加新节点;
C 根据实际需要重复B过程,直至最底层的文件夹,即用例主题的父节点。
2)从文档中读取一个用例
3)根据用例主题字段内容设置主题文件夹
4)在主题文件夹下添加用例,根据读取相关内容设置用例各字段信息
5)逐一向用例添加测试步骤及预期结果
6)重复2)至5),直至用例全部导入
第一个过程对于不同的版本存在一些差异,QC 9.0的习惯做法是连接服务器,登录用户,然后依次选择域和项目,但是此登陆方法在 TD 8.0中不支持,TD 8.0的一般登录方法为连接到服务器的某个域,再登录用户连接项目。具体采用哪种方法,我们只能依赖 QC API 提供的方法。
五、细化设计,编写代码
明确了开发的过程,就可以进一步细化设计,用程序将设计描述出来。我选择比较简洁的VB语言来实现。
首先需要安装 OTA (开放式测试架构)客户端动态链接库,这只需安装 QC 客户端就可以了。然后,设置 VB ,引用 QTA COM 9.0 Type Library(不同版本的 QC ,此类型库有所不同),如图4所示。下面就按照上面介绍的几个过程列举说明。
图4 引用 OTA (开放式测试架构)客户端动态链接库变量声明:
Public tdc As New TDConnection 'TDConnection 对象是唯一可以在 QC 内直接 '创建的对 '象,它表示单个 QC
服务器连接
Public testNodesTree As TreeManager '系统树结构
Public tstFactory As
TestFactory '测试计划管理对象引用
Public rootNode As SysTreeNode
'文件夹树根节点,TreeManager对象的一个树节点
Public nodeParent As SysTreeNode '父节点文件夹
Public treeNode As SysTreeNode '测试主题文件夹节点
Public TestPlan As Test
'测试用例对象引用
Public newtestPlan As Test '新添加测试用例
Public stepFactory As
DesignStepFactory '测试用例步骤的管理对象引用
Public step As DesignStep '测试用例步骤对象引用
Public tstFilter As TDFilter '从测试计划中筛选用例
Public stepFilter As TDFilter
'从测试步骤中筛选
对于 QC 9.0,可以按照下面三个步骤完成连接到项目的过程。
1)连接 QC 服务器:
Public serverName As String
'。。。获取服务器名,并做初步的合法性校验
If tdc.Connected =
False Or (tdc.Connected = True And tdc.serverName <> serverName) Then
tdc.InitConnection serverName
End If
'。。。
2)用户登录,登录成功以后,就可以获取此用户可用的域:
'获取用户名和密码,并做初步合法性校验
tdc.Login userName, password
'。。。
'下面获取此用户所有的域信息
For iDomain = 1 To tdc.VisibleDomains.Count
'将域名信息加入域选择列表
Next
'。。。
3)连接域和项目:
'选择域
'获取域下项目信息
'选择项目
tdc.Connect domainName, projectName '连接到项目
对于 TD 8.0,连接过程如下:
tdc.InitConnection serverName, "DEFAULT"
tdc.ConnectProject projectName,
userName, password
成功连接到项目后,就可以开始导入过程了,首先是设置树结构文件夹。为了方便,我仅在根节点(” Subject ”)和用例本身所在的文件夹(用例的主题)之间添加一层文件夹结构(比如是系统的名称)。还要注意,在 QC 中,同一目录下是不允许有名称相同的文件夹的,因此在这个过程中,首先要遍历一下是否已经存在当前节点,如果不存在再添加,详细过程如下:
Set testNodesTree = tdc.TreeManager
Set rootNode =
testNodesTree.TreeRoot("Subject") '设置根节点
rootNode.Refresh
Set nodeParent
= Nothing '主题文件夹父节点
'主题文件夹父节点设置,从根节点开始,遍历子节点
For iNode = 1 To
rootNode.Count
If UCase(rootNode.Child(iNode).Name) = UCase(NewNode) Then
Set nodeParent = rootNode.Child(iNode) ‘如果节点已经存在,将它置为父节点
End If
Next
iNode
'如果没有找到该节点,则添加
If nodeParent Is Nothing Then
Set nodeParent =
rootNode.AddNode(NewNode) ‘添加新节点
End If
读取用例信息:
'将用例主题、用例名称等信息保存并做初步校验
' strTable(IndexFunctionUnit) = "主题名称"
'
strTable(IndexTestName) = "用例名称"
' 。。。
设置主题文件夹:
Set treeNode = Nothing
'如果用例主题文件夹已经存在,则指定其为当前用例树节点
For iNode = 1 To
nodeParent.Count
If UCase(nodeParent.Child(iNode).Name) =
UCase(strTable(IndexFunctionUnit)) Then
Set treeNode =
nodeParent.Child(iNode)
Exit For
End If
Next iNode
'如果当前用例主题是新,添加到节点树中
If treeNode Is Nothing Then
Set treeNode =
nodeParent.AddNode(strTable(IndexFunctionUnit))
End If
下面的工作是添加用例,此处默认用例是规范的,即一个主题下文件夹名称不会重复。添加用例时需要设置用例各字段的信息,有些重要的字段即使用例文档中没有给出,也要采取一定的措施补上(如设置成一个默认值):
Set newTestPlan = Nothing '新用例
'则添加新的用例
Set newTestPlan =
tstFactory.AddItem(testItem)
'设置测试用例字段信息
newTestPlan.Field("TS_NAME") =
"用例名称"
newTestPlan.Field("TS_TYPE") = "测试类型"
newTestPlan.Field("TS_RESPONSIBLE") = "编制人员"
newTestPlan.Field("TS_SUBJECT") = treeNode.NodeID '测试主题文件夹的ID,这个字段必不可少
'。。。其他字段定义与此,如果是必须的字段,即使用例中缺失,可以设定一个默认值
newTestPlan.Field("TS_STATUS") =
TESTSTATUS
newTestPlan.Post
接下来的工作添加测试用例步骤,这个过程类似添加用例的过程,只不过应用不同的对象和一些细微的差别而已,在此不再累赘。
五、完善程序
如果认为完成了编码就万事大吉了,那是测试人员在砸自己的饭碗,对于这个程序,如果真正完善它的功能,可能还需要多加数倍的代码,你可以想象一下手工向 QC 中添加一个用例可能会产生多少种失败的情况,用例名称为空、重复,同一目录下文件夹重复,文件夹包含非法字符等,还有 QC 程序帮你避免的或是帮你自动完成的操作,如果你的程序没有主动去处理这些,任何异常情况将给导入程序带来致命性的问题,甚至影响 QC 正常的使用。
首先,程序在每一个过程执行对输入进行初步的校验是必要的,连接空的服务器,未选择项目,用例的主题或用例名称为空或其他非法的输入都应该预先避免掉。
其次,根据经验尽可能充分的想到一个过程中可能会发生的情况,如主题中包含 QC 不允许的字符,或是用例名称重复等。
例如,在添加一个用例前加入如下代码:
'如果导入名称相同的测试用例则会出现异常,在此要做特别处理
Set tstFilter = tstFactory.Filter '对测试用例进行过滤
tstFilter.Filter("TS_SUBJECT") = treeNode.Path '过滤出某个主题的用例
For Each
testPlan In tstFilter.NewList
If strTestName = testPlan.Name Then
'如果名称重复,采取措施
End If
Next
'如果已经避免了重复,则添加新的用例
If newTestPlan
Is Nothing Then
Set newTestPlan = tstFactory.AddItem(testItem)
End If
第三,注意细节问题,如如果退出时没有主动断开连接,QC 下次登录时会出现意想不到的问题。如,完成导入,需要显式断开连接:
If Len(tdc.projectName) > 0 And Not tdc Is Nothing Then
If
tdc.ProjectConnected = True Then tdc.Disconnect
End If
If
tdc.Connected = True Then tdc.ReleaseConnection
此外,我们很难保证在程序中主动处理所有可能出现的异常,因此还需要利用异常处理机制,捕获 QC 异常情况。如:
On Error GoTo
ErrorHandler: '如果发生异常,执行异常处理代码
'。。。
ErrorHandler:
'异常处理代码
'如果出现异常,我们最好能够尽可能给出详细的信息
If isError = 1 Then
MsgBox "文件夹设置异常!"
GoTo TheEnd:
End If
If isError = 2 Then
If (MsgBox("测试用例" &
TestCounter & "出现异常,异常信息:" & Err.Description & _
vbCrLf &
"是否继续?", vbYesNo) = vbNo) Then
MsgBox "导入被取消!"
GoTo TheEnd:
End If
End If
TheEnd:
'程序被迫结束,做出相应的事宜
最后,你可以尝试导入用例了,对于各种各样的没有统一规范的文档,可能会给你的程序带来一定的考验,我想,你的程序健壮的可以尽可能地满足文档给你带来的成就感要远远大于不得不修改文档而获得的满足。