内容


使用 IBM Rational ClearQuest Java API 进行集成开发

通过 JNI 技术使用 ClearQuest Java API 实现与 Rational ClearQuest Test Manager(CQTM)系统的集成

Comments

开始之前

预备知识

本教程针对使用过 Rational ClearQuest Test Management 的人员。需要你了解 CQTM 中的基本概念。另外你最好了解 Eclipse,但不是必需的。

系统需求

您可以安装 IBM WebSphere Integration Developer 来运行本文中的示例程序。

Rational ClearQuest Test Manager(CQTM)简介

目前,测试部门面临着许多严峻的问题。他们需要迅速地适应市场变化,协调分散在世界各地的团队间的合作,与来自外部的服务提供商之间进行交互,等等。为了能够及时地发布高质量的应用,IBM Rational将企业测试管理能力融入到了IBM Rational ClearQuest v7.0产品中,这一新特性称为ClearQuest test management (CQTM)。

Rational ClearQuest是一个知名的变更(新的需求、软件缺陷、各种工单等)管理工具。CQTM作为该产品的一个新增特性,能够有效地帮助Rational ClearQuest用户实现测试的计划、创建、执行和报告。作为Eclipse Test and Performance Tools Platform (TPTP) 功能的扩展,CQTM能够支持各种类型的测试,从纯手工的测试一直到完全自动的测试,包括单元测试、功能回归测试和性能测试。

CQTM提供了四种类型的客户端

  • Rational ClearQuest Eclipse Client:包括两种基于Eclipse技术的客户端。Rational ClearQuest Client,是一个基于Eclipse Rich Client Platform (RCP) 技术开发的独立的客户端;Rational ClearQuest Client for Eclipse, 作为Eclipse插件安装在支持的Eclipse内核上。
  • Rational ClearQuest Web Client:是一个基本浏览器的图形用户接口。
  • Rational ClearQuest for Windows Client:是一个Microsoft Windows接口,允许用户创建报告和图表。
  • Rational ClearQuest Client for Visual Studio.NET:允许用户在Microsoft Visual Studio.NET环境中访问ClearQuest数据库。

对于不同类型的客户端,它们所支持的功能集不同。其中Rational ClearQuest Client for Eclipse支持的功能最为全面,因此,本文将使用Rational ClearQuest Client for Eclipse v7.0.1.0向您展示示例程序的执行结果。

对于一般用户和管理员来说,可以直接通过ClearQuest客户端完成ClearQuest的各项任务,包括提交、修改和追踪变更请求等。但是,在某些情况下您可能需要通过编程的方式来访问ClearQuest的数据。例如,如果您的部门需要将自身的应用和ClearQuest进行集成,以便增加测试管理的功能。此时,您就需要使用ClearQuest API进行集成开发。

Rational ClearQuest提供了基于VB和Perl的两种脚本语言的编程接口。其中,VB脚本的API通过一个名为cqole.dll的COM library来实现,Perl脚本的API通过一个名为CQPerlExt的Perl package实现。关于具体的类及其方法的使用描述,请参见ClearQuest随身附带的文档"cq_api.pdf"。本文讨论的主要内容是,如何帮助开发人员使用Java API来实现与ClearQuest的集成。

Rational CQTM 中的重要概念

在开始介绍ClearQuest Java API之前,我们有必要对ClearQuest涉及的基本概念以及特定于CQTM的概念做一个简单的介绍,这将有利于您对本文中示例代码的理解。

对于ClearQuest范围的概念有:

  • 变更请求(change requests):一个变更请求是用来记录和跟踪与项目相关的各种类型变更活动的对象,这些对象以记录的形式存储在用户数据库中。不同的变更请求使用不同类型的记录存储,记录类型定义了关于变更请求的字段、显示样式和状态迁移模型等。当用户操作变更请求时,变更请求会从一个状态迁移到另一个状态。常见的状态包括已被提交(submitted)、已被分配(assigned)、继续进行 (working on)、已决 (resolved) 和已被验证 (validated)。
  • 模式 (schemas):记录与用户数据库相关的所有属性信息,包括变更请求记录的字段定义、展示样式的定义、状态迁移模型定义以及执行状态迁移的角色定义等。
  • 模式数据库 (schema repository):作为master数据库,用来存储模式相关的数据。
  • 用户数据库(user databases):用来存储可以被最终用户访问和输入的所有数据。每一个用户数据库都和一个特定版本的模式相关联,可以说,用户数据库是特定版本模式的一个实例。一个特定版本的模式可以与多个用户数据库关联。需要注意的是,当用户添加或修改变更请求的信息时,用户更改的是用户数据库中的数据,并不影响与之相关联的模式。
  • 数据库集/连接 (dbset/connection):包括一个模式数据库以及所有与该数据库相关的用户数据库。通常,一个项目所涉及的所有模式和数据库都被归为一个连接。当然,一个连接也可以支持多个项目,或者一个项目也可以有多个连接。

图1为模式、模式数据库和用户数据库之间的关系示例。

图 1. 数据库关系结构
数据库关系结构
数据库关系结构

以下是针对CQTM特性的基本概念。CQTM的各种测试资产都用ClearQuest的记录类型来表示,存储在ClearQuest的用户数据库中。如图2所示,展示了各种记录的层次结构:

  • 资产注册(asset registry):记录类型为TMAssetRegistry。资产注册是测试计划层次结构的入口。用于定义测试的范围,作为测试计划、测试套件、文件位置和迭代记录信息的容器。如CQSTF Test.
  • 测试计划(test plan):记录类型为TMTestPlan。测试计划是有状态的记录,表示预计要执行的测试的分类。测试计划可以包含子测试计划,也可以包含若干测试用例。如测试计划Plan2包含测试用例case1以及三个子测试计划CQTM01V1、STF01V1、withdraw。
  • 测试用例(test case):记录类型为TMTestCase。代表需要在被测系统中进行验证的行为单元。一个测试用例包含若干个配置的测试用例,如case1 – Maximum Memory Windows XP, case1 – Minimum Memory Windows XP。
  • 配置的测试用例(configured test case):记录类型为TMConfiguredTestCase。配置的测试用例是具有关联配置和迭代信息的测试用例的可执行格式。每个已配置的测试用例都与父测试用例相关联,单个测试用例可与多个已配置的测试用例关联,用于测试不同的配置。
  • 配置(configurations):记录类型为TMConfiguration。一条配置记录用于定义测试环境,是多个属性值的集合,如
    • Operating System – Windows XP
    • Processor – 3 Ghz
    • Memory – 1GB
    • Network – 100 Mbs
    配置记录信息独立与资产注册,应用于创建配置的测试用例和测试集。
  • 测试套件(Test Suites):记录类型为TMTestSuite。表示可按顺序执行的已配置测试用例的有序列表。
  • 迭代(iterations):记录类型为TMIteration。包含迭代信息,代表开发正在接受测试的系统期间的特定里程碑。
  • 文件地址(File Locations):记录类型为TMFileLocation。用于为外部的引用文件指定文件地址。
  • 测试日志 (test log):记录类型为TMTestLog。显示执行的已配置测试用例记录的摘要结果。
图 2. 测试计划的结构
测试计划的结构
测试计划的结构

ClearQuest Java API简介

在文章开头我们提到,Rational ClearQuest提供了基于VB和Perl两种脚本语言的编程接口,而并没有直接提供Java语言的编程接口。但在它的安装目录中,包含有一个名为cqjni.jar的包,可用于支持Java API。它通过JNI技术,实现使用Java语言完成对ClearQuest功能的调用。JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。在Windows平台的ClearQuest的安装目录下,您可以发现相应的库文件cqjniporxy.dll.

ClearQuest Java API包括用户数据库对象、模式数据库对象、模式数据库对象集合以及其他对象。其中,主要的入口点对象有两个:

  • 会话对象(CQSession):提供对用户数据库对象的访问。
  • 管理员会话对象 (CQAdminSession):提供对模式数据库对象的访问。

会话对象

Rational ClearQuest使用会话对象验证访问用户数据库的用户身份。因此,开发人员在对用户数据库执行任何操作之前,必须通过该对象登录到指定的用户数据库。作为用户数据库对象的根对象,开发人员可以使用CQSession对象完成以下任务:

  • 登录到用户数据库
  • 创建新的数据库记录或查看、修改已经存在的记录
  • 创建查询对象,用于查询数据库中的特定记录

用户数据库对象

图3展示了可以通过CQSession对象访问的用户数据库对象及其之间的关系。图中的箭头表示对象间的关系,可以概括为两种类型:

  • 简单关系:例如,通过会话对象,开发人员可以直接访问多个不同类型的对象,包括CQDatabaseDesc, CQEntity, CQEntityDef, CQQueryDef和CQResultSet对象。
  • 复杂关系:例如,开发人员需要同时使用CQQueryDef和CQResultSet两个对象实现查询,CQResultSet对象通过CQQueryDef对象创建,并使用CQQueryDef对象中定义的规则信息执行查询,而这两个对象又是各自通过会话对象单独创建。

从图中我们可以看出,访问用户数据库涉及的主要对象包括

  • CQEntity对象:代表数据库中的一条记录,用于查看和修改记录中的数据。
  • CQEntityDef对象:用于查看数据库记录的只读元数据,包括字段、hook、状态等。
  • CQQueryDef对象:定义查询规则。
  • CQResultSet对象:包含查询得到的结果。
  • CQQueryFilterNode对象: 为查询规则添加比较过滤器。
  • CQDatabaseDesc对象:提供数据库的描述信息。
  • CQEventObject对象:提供关于数据库记录,即CQEntity对象的调用方法的只读上下文信息。
  • CQFieldInfo对象:提供数据库记录字段的只读信息。
图 3. 用户数据库对象
用户数据库对象
用户数据库对象

管理员会话对象

管理员会话对象提供对模式数据库的管理服务。作为模式数据库对象的根对象,开发人员可以利用管理员会话对象完成以下任务:

  • 创建数据库
  • 删除数据库
  • 订阅用户到一个数据库
  • 订阅组到一个数据库

管理员会话对象必须在执行对模式数据库任何操作进行之前创建,它与会话对象之间没有重叠的功能。

模式数据库对象

模式数据库对象用于访问和设置模式数据库的元数据。图4展示了模式数据库对象及其之间的关系。主要包括以下对象

  • CQDatabase对象:用于存储用户数据库的信息。CQDatabases对象代表该对象的集合。
  • CQSchema对象:表示模式数据库中的模式,该对象提供若干模式修订用于更新数据库。开发人员不能通过编程方式修改该对象。CQSchemas对象代表该对象的集合。
  • CQSchemaRev对象:每一次对模式数据库中模式的修订,都会产生一个SchemaRev对象。开发人员不能通过编程修改该对象,而只能使用Rational ClearQuest Designer工具对模式进行修改。CQSchemaRevs对象代表该对象的集合。
  • CQGroup对象:代表模式数据库中的一个用户组。该对象包含基本的组信息,组成员信息以及该组订阅的数据库信息。CQGroups对象代表该对象的集合。
  • CQUser对象:代表模式数据库中的一个用户。该对象包含用户的基本信息,该用户所属组的信息以及订阅的数据库信息。CQUsers对象代表该对象的集合。
  • CQPackageRev对象:该对象不被API支持。CQPackageRevs对象代表该对象的集合。
图 4. 模式数据库对象
模式数据库对象
模式数据库对象

使用CQ Java API 实现与Rational CQTM集成

本文中示例的应用场景是一个使用Java语言开发的Web服务测试工具,测试人员需要使用该测试工具进行Web服务测试并将测试结果录入到CQTM中实现对测试结果的管理。因此,测试人员需要为CQTM的每个测试用例创建日志记录,并将测试工具的执行结果逐项地填写到测试日志中。例如,测试人员在测试工具中分别创建了两个测试用例case1和case2,用于对serviceA和serviceB进行测试。执行后得到两个执行结果, case1执行成功,表明serviceA的功能正常,但是由于serviceB的实现存在问题,导致case2执行失败,得到异常信息。接下来,测试人员需要将得到的执行结果记录到CQTM中进行管理。首先,他先在CQTM的测试计划中找到对应于case1和case2的两个测试用例,然后为测试用例创建一个空的日志记录并根据测试工具中的执行结果,依次填写测试结果(成功、失败、不确定等)、测试时间,测试执行人员、导致测试失败的原因等信息。从中我们可以看出,当待测服务数量比较大的时候,创建日志是一件非常耗时并容易出错的事情。因此,为了解决这个问题,测试工具的开发人员决定利用CQ Java API实现测试工具与CQTM的集成,使得测试人员可以将测试工具中的执行结果很方便地导入到CQTM的测试管理框架中。

该测试工具是一个Web应用,运行于应用服务器WAS之上。为了能够与CQTM实现集成,我们必须将ClearQuest client与应用服务器安装在同一台机器上,ClearQuest的数据库系统可以安装在任何一台机器上。系统的基本架构如图5所示。安装完毕后,需要进行以下配置。

  • 设置系统环境变量:将ClearQuest安装目录添加到系统环境变量PATH中,例如C:\Program Files\Rational\common。
  • 在ClearQuest的安装目录下,将cqjni.jar和cqjniproxy.dll拷贝到WAS的lib目录下。
图 5. 集成系统架构
集成系统架构
集成系统架构

在正确配置环境之后,您便可以开始实现测试工具与CQTM功能的集成。为了能够在CQTM中自动为每个测试用例创建日志记录,并将测试工具中得到的测试结果写入日志记录中,我们首先必须登录到CQTM数据库,这是调用CQTM 其他功能的前提。然后我们将执行相应的查询活动,得到创建日志记录所需的相关信息。接下来,我们将会为CQTM中的每个测试用例创建日志类型的记录,填充必要的日志信息并保存到数据库中。

为了让读者能够更多地了解CQTM的功能,在本文接下来的讨论中,我们除了对导入日志所需的功能进行介绍外,还会对其他一些比较常用的功能进行介绍,尽可能地让您了解到更多的CQ API。此外,我们在逐一向您讲解实现集成功能的代码的同时,还会与通过ClearQuest Client实现该功能的步骤进行对比,帮助您更好地理解程序代码。

登录到用户数据库

该功能将向您展示如何连接到Rational ClearQuest的用户数据库。获取连接是执行其他各项操作的前提。我们首先向您介绍如何通过ClearQuest Client创建一个连接并登录到指定的用户数据库,帮助您更好地理解此项功能。之后,向您讲解相应的实现代码。

1. 打开ClearQuest Client,在顶部的菜单栏中,点击连接按钮,在弹出的下拉列表中,选择New Connection.

图 6. 创建新连接
创建新连接
创建新连接

图 6 大图

2. 在模式数据库页面从下拉列表中选择所需的模式数据库。

图 7. 模式数据库选择页面
模式数据库选择页面
模式数据库选择页面

3. 在额外连接信息页面,填写登录用户名,并点击Finish按钮关闭此对话框。

图 8. 额外登录信息页面
额外登录信息页面
额外登录信息页面

4. 在连接对话框中,填写登录密码并选择登录到的用户数据库。选中 Remember the password复选框,这将为后续操作保存密码。

图 9. 连接对话框
连接对话框

5. 如果填写的信息正确,您将成功地登录到指定的用户数据库。此时,在Test Manager视图中,您将会看到出现一个新的连接信息。

图 10. Test Manager视图
Test Manager视图
Test Manager视图

通过以上操作,您可以创建一个连接并登录到指定的用户数据库,相应的实现代码清单1所示。该代码片断中用到的主要对象为CQSession对象。对于外部的应用程序来说,必须创建一个CQSession对象并使用该对象登录到数据库。成功登录后,开发人员还可以使用该对象,完成多种任务,包括创建新的数据库记录和查询,编辑已经存在的记录以及查看数据库的信息。该功能的具体实现步骤为:

  • 第1行,创建一个新的CQSession对象。
  • 第2-6行,为了确保我们登录到的用户数据库名称,我们可以通过CQSession对象的GetAccessibleDatabases方法得到与一个特定的模式数据库相关的所有用户数据库信息。GetAccessibleDatabases方法的语法为
    GetAccessibleDatabases(String master_db_name, String user_login_name, 
        String database_set)

    需要注意的是,该方法只返回允许指定用户访问的用户数据库信息。如果方法中第二个参数user_login_name为空字符串的话,该方法将返回所有与指定模式数据库(master_db_name) 关联的用户数据库信息。开发人员可以进一步访问得到的每一个CQDatabaseDesc对象,从而得到相应的数据库名称,数据库集合的名称以及其他登录所需的信息。

  • 第8行,指定具体的登录信息,通过CQSession对象的UserLogon方法,登录到指定的用户数据库。其中,UserLogon方法的语法结构为
    UserLogon(String user_login_name, String password, String database_name,
        String database_set)

    其中,第一个参数对应步骤3中指定的UserID信息, 中间两个参数对应步骤4中指定的Password和Database信息,第四个参数对应步骤2中指定的Schema Repository.

清单1. 连接到用户数据库
// get a cqsession object
1 CQSession cqSession = new CQSession();
// get a list of dbs associated with a schema repository
2 CQDatabaseDescs dbDescs = cqSession.GetAccessibleDatabases(
                           “master_db_name”, 
                           “user_login_name”, 
                           “database_set”);
3 CQDatabaseDesc dbDesc = null;
4 for(int i=0; i<dbDescs.count(); i++){
5    dbDesc = dbDescs.item(i);
6    String dbName = dbDesc.getDatabaseName();
7    If(dbName.equals(“db”)){
       // log on to the specified user db
8      cqSession.UserLogon(
                           “userName”, 
                           “userPwd”, 
                           dbName,  
                           dbDesc.getDatabaseSetName()
                           );
9       break;    
10    }
11 }

在成功地登录到数据库之后,创建的CQSession对象将对整个登录会话有效,像JSP中的session对象一样,我们可以在CQSession对象中设置会话变量用于保存全局的信息并在之后读取该变量的值。示例代码如清单2所示。

  • 第1行,使用CQSession对象的SetNameValue方法,创建一个会话变量,第一个参数为变量的名称,第二个参数为赋予该变量的值。如果该会话变量已经存在,SetNameValue方法将会使用新值覆盖掉原来的变量值。
  • 第2行,利用HasValue方法判断会话变量是否存在。
  • 第3行,利用CQSession对象的GetNameValue方法获取会话变量的值,其中的参数为变量的名称。
清单2. 使用会话变量
1 cqSession.SetNameValue("userAge", "25");
2 if(cqSession.HasValue("userAge")){
3     System.out.println(cqSession.GetNameValue("userAge"));
4 }

在本节中,我们向您介绍了如何通过API登录到指定的CQTM数据库。在成功登录之后,为了创建日志记录,我们需要查询构造记录所需的其他信息,包括迭代信息、配置信息等。下面,我们就以查询配置信息为例,向您介绍如何创建数据库查询。

创建数据库查询

查询用于指定从数据库中获取数据的规则。在CQ中,创建查询主要有以下几个步骤:

  • 构造一个查询(CQQueryDef对象),指定欲查找的数据。CQQueryDef对象包含查询的规则定义。
  • 创建一个数据集(CQResultSet对象)存储查询得到的数据。
  • 执行查询,将查询结果写入数据集中。
  • 遍历数据集,对查询结果进行分析。

本节我们以 查询测试的配置信息为例(如图11),向您展示如何构造查询规则、执行查询以及解析查询结果。

图 11. 配置信息
配置信息
配置信息

实现程序的代码片段如清单3所示。具体的实现步骤为:

  • 第1行,利用CQSession对象的BuildQuery方法,构造一个CQQueryDef对象。其中的参数为测试记录类型的名称。本例中,配置记录类型名为TMConfiguration。关于其他记录类型请参考本文第二部分对CQTM术语的介绍。如果您对记录类型不明确的话,也可以使用BuildSQLQuery方法,通过构造SQL表达式,定义查询规则。
  • 第2行,利用CQQueryDef对象的BuildField方法指定包含在查询结果中的字段。在执行查询之前,您必须指定至少一个字段包含在结果集中。每指定一个字段,都要调用一次BuildField方法。本例中,只添加了一个字段Name, 即配置的名称。
  • 第3行,利用CQSession对象的BuildResultSet方法,构造一个结果集,用于执行查询并记录查询结果。CQResultSet对象将按照BuildField方法添加字段的顺序记录查询结果。
  • 第4行,利用CQResultSet对象的ExecuteAndCountRecords方法,执行查询并返回查询结果数量。您也可以使用Execute方法执行查询,再利用其他方法得到结果的数量。
  • 第5行,利用ResultSet对象的MoveNext方法,将光标移动到结果集中的下一条记录。如果返回值为1,表示光标移动成功,即存在下一条记录。
  • 第6行,利用ResultSet对象的GetColumnValue方法,得到当前行中指定列的值。列的计数从1开始。
清单3. 查询配置信息
// create a query for record "TMConfiguration"
1 CQQueryDef queryDef = cqSession.BuildQuery(“TMConfiguration”);
					
// set display fields
2 queryDef.BuildField("Name");
3 CQResultSet resultSet = cqSession.BuildResultSet(queryDef);
4 long records = resultSet.ExecuteAndCountRecords();
5 while (resultSet.MoveNext()== 1) {
6	String name = resultSet.GetColumnValue(1);	
}

在本节中,我们向您介绍了如何通过API查询数据库记录。细心的您会发现,使用本节介绍的API得到的结果集包括特定数据表的所有记录,而不能有选择地进行查询,即查询具有特定约束条件的记录。为了实现对数据库查询的过滤,请您阅读下一节“过滤数据库查询”。

过滤数据库查询

如果您的查询规则包含比较运算的话,就需要通过一个过滤器(filter)实现,即CQQueryFilterNode对象。一个过滤器允许您将一个字段与单个值或一个范围进行比较,过滤器中的操作符指定比较的类型。关于操作符的描述请见表格1。

我们将查询表达式组成一棵树的形式,树中的节点为逻辑运算符。通过逻辑运算符,可以将多个过滤器连接起来。每个过滤器可以包含一个条件表件式或多个条件表达式,它们之间通过And或者Or运算符关联在一起。

对于清单4中的查询表达式,需要查询关于缺陷 (defect) 描述的信息,要求缺陷的提交日期不超过01/03/2008,而且提交者必须为bill或admin. 相应的实现代码请见清单5.

  • 第1行,创建一个关于缺陷记录类型(TMDEFECT)的CQQueryDef对象。
  • 第2行,指定结果集中包含的字段是缺陷的描述信息。
  • 第3行,调用QueryDef对象的BuildFilterOperator方法创建查询树中的根节点(CQQueryFilterNode对象) 。QueryDef对象的该方法是构造一个查询表达式的入口点。开发人员必须调用该方法得到查询表达式中的第一个过滤器。从这个节点出发, 进而构造查询规则中的其他过滤节点。其中,BuildFilterOperator方法的参数为一个long型的整数,代表逻辑操作符(1为逻辑与,2为逻辑或)。
  • 第4行,通过CQQueryFilterNode对象的BuildFilterOperator方法创建一个内嵌的CQQueryFilterNode对象包含指定的逻辑运算符。
  • 第5-7行,通过调用BuildFilter方法为逻辑运算符节点增加一个过滤器,该方法将一个字段和一个或一组值进行比较。其中,第一个参数为字段的名称,第二个参数为比较运算符,第三个参数为字符串数组。
清单4. 查询表达式
Select id from CQSTF_DEFECT where state = “Fixed” AND 
(owner = ‘bill’ OR owner = ‘admin’)
清单5. 过滤查询代码
// create a query for record " TMDEFECT"
1 CQQueryDef queryDef = cqSession.BuildQuery(“TMDEFECT”);
					
// set display fields
2 queryDef.BuildField("id");
3 CQQueryFilterNode filterNode1 = queryDef.BuildFilterOperator(1);
4 CQQueryFilterNode filterNode2 = filterNode1.BuildFilterOperator(2);
			
5 filterNode2.BuildFilter("Owner", 1, new String[]{“bill”});
6 filterNode2.BuildFilter("Owner", 1, new String[]{“bill”});
7 filterNode1.BuildFilter("State", 1, new String[]{“Fixed”});
8 CQResultSet resultSet = cqSession.BuildResultSet(queryDef);	
9 resultSet.Execute ();
表格1. 比较运算符
常量值描述
1等于运算符(=)
2不等于运算符(<>)
3小于运算符 (<)
4小于等于运算符 (<=)
5大于运算符 (>)
6大于等于运算符 (>=)
7Like运算符(值是指定字段字符串值的子串)
8Not-like运算符(值不是指定字段字符串值的子串)
9Between操作符(值在指定的多个分隔值之中)
10Not-between操作符(值不在指定的多个分隔值之中)
11Is-NULL操作符(字段不包含任何值)
12Is-Not-NULL操作符(字段包含值)
13In操作符(值在指定的集合中)
14Not-In操作符(值不在指定的集合中)

在本节中,我们向您介绍了如何过滤数据库查询。在查询得到了所需的信息之后,我们便可以创建日志记录,并填充记录的相关信息。下面,我们就一起来看看如何创建一个数据库记录。

创建数据库记录

数据库使用记录组织和存储信息。在ClearQuest中,记录(CQEntity)指的是一种结构信息,用于将特定记录类型 (CQEntityDef) 的实例的信息组织起来。ClearQuest使用CQEntity对象组织和管理记录数据。每一个CQEntity对象提供对记录中任何已定义的字段数据的访问,包括记录的历史数据,与该记录相关联的文件信息等。

本节通过为已配置的测试用例创建日志记录为例,向您介绍如何创建一个特定类型的用户数据库记录。在ClearQuest Client中,为已配置的测试用例手动创建日志记录的步骤如下:

1. 选择一个已配置的测试用例,点击右键,选择New Test Log选项。

图12. 创建日志记录
创建日志记录
创建日志记录

2. 在弹出的创建日志记录对话框中,填写必要的信息。其中,红色圆圈标识的字段为必填字段,包括

  • Verdict:记录配置测试用例的执行结果。有四种类型,Pass, Fail, Inconclusive, Error.
  • Start Time/End Time: 测试脚本执行的启动和终止时间。
  • Owner: 创建该日志记录的用户。
图13. 日志记录主页面
日志记录主页面
日志记录主页面

对应于上述操作的实现代码请见清单6. 该代码片段实现了为指定的配置测试用例创建一个日志记录的功能。

  • 第1行,利用CQSession对象的BuildEntity方法,创建一条指定类型的记录(类型为TMTestLog的CQEntity对象)。此外,该方法还初始化了一个提交(submit)活动,使得开发人员可以对记录的内容进行编辑(不必调用EditEntity方法将记录设为可编辑的状态)。
  • 第2-9行,利用CQEntity对象的SetFieldValue方法,为记录的指定字段赋值。该方法的第一个参数为字段的名称,第二个参数为赋予该字段的值,返回一个包含结果信息的字符串。通过返回的字符串,可以看出赋予该字段的值是否有效。如果该值有效,则返回空字符串;如果字段是不可更改的,在返回的字符串中会指明为什么该字段不可改变,典型的返回值包括”no such field”, “record is not being edited”, “field is read-only”等。如果该字段可以包含多个值,可以使用AddFieldValue方法为其添加多个值。SetFieldValue方法只适用于可以被编辑的CQEntity对象,为了让一个CQEntity对象可以被编辑,我们可以通过调用CQSession对象的EditEntity方法实现,这将在后续的介绍中涉及。
  • 第10行,调用CQEntity对象的validate方法,对创建的CQEntity对象进行验证并报告出现的错误。在一个CQEntity对象被提交之前,即使没有字段被改变,我们也建议您需对其进行验证。如果验证中出现错误,该方法会返回一个包含错误信息的字符串,否则,返回空字符串。请不要通过编程方式试图对包含错误信息的字符串做进一步的处理,因为在后续的版本中,返回的字符串中的错误信息很可能会发生变化。
  • 第11-22行,如果验证正确的话,我们需要调用CQEntity对象的commit方法将新创建的日志记录提交到用户数据库。该方法可以提交任何改变到数据库。如果在提交过程中出现错误的话,该错误将被作为异常抛出。如果在提交完成之后出现错误的话,错误信息将被包含在字符串中返回。
清单6. 过滤查询代码
1 CQEntity record = cqSession.BuildEntity(“TMTestLog”);
2 record.SetFieldValue("ConfiguredTestCase", selectedCQLog[i]);
3 record.SetFieldValue("Owner", owner);
4 record.SetFieldValue("Verdict",mapping.get(i).getResult()); 
5 record.SetFieldValue("StartTime", 
  new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss").format(new Date()));
6 record.SetFieldValue("EndTime", 
  new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss").format(new Date())); 
7 record.SetFieldValue("Build", buildNum);
8 record.SetFieldValue("BuildNum", buildNum);
9 record.SetFieldValue("Iteration", iteration);
// save the record 
10 String result = record.Validate();
11 if (result.equals("")) { 
	// if there is no validation errors 
12      try{
13         result = record.Commit(); 
14	     if (!result.equals("")) {					
15		   throw exception;						
16	    }
17      }catch(Exception e){
18           throw e;
19      }
20   } else { 					
21	 throw exception;				
22   }

到此,我们就已经完成了对一条日志记录的创建和存储。在测试工具的代码中,我们就是通过以上的步骤,将测试工具中得到的测试结果一条一条地导入到CQTM中。接下来,我们将一起讨论CQTM中其他的常用功能。

编辑已存在的数据库记录

本节主要向您讲述如何获取已经存在的数据库记录并对该记录进行编辑。CQ提供了多种方法从用户数据库中获取一条记录 (CQEntity)。如果您知道该实体对象的ID值,可以使用CQSession对象的GetEntity或者GetEntityByDbId方法得到实体对象。否则,可以使用CQSession对象的BuildQuery方法创建一个查询,执行后得到符合条件的实体对象。通过以上方法得到的实体对象都是只读的,为了能够对实体对象进行编辑,开发人员必须调用CQSession对象的EditEntity方法。清单7中的示例代码用于得到一个缺陷记录列表,并修改其中的特定缺陷记录。

  • 第1-5行,构建一个对缺陷记录的查询对象,指定结果集为缺陷记录的id字段和Headline字段。
  • 第8-10行,执行后遍历结果集,得到每条记录的id信息。调用CQSession对象的GetEntity方法,得到相应的实体对象。GetEntity方法的语法结构为:
    GetEntity (String entity_def_name, String display_name)

    第一个参数为记录类型的名称,第二个参数为记录的显示名称。通常,为记录的ID字段的值。您也可以通过调用CQEntity对象的GetDisplayName方法查看。

    之前,我们提到过,除了使用GetEntity方法,我们也可以通过GetEntityByDbId方法得到实体对象,该方法也包含两个参数,第一个参数与GetEntity方法相同,为记录类型的名称,第二个参数为数据库ID (db_id), 可以通过调用CQEntity对象的GetDbId获得。

  • 第11行,得到每条记录的Headline字段的值,注意,这里我们使用了CQEntity对象的GetFieldStringValue方法来获取字段的值,而不是GetColumnValue方法。
  • 第13行,我们通过调用CQSession对象的EditEntity方法,将指定的实体对象设置为可编辑的状态。这里需要注意的是,如果实体对象是通过GetEntityByDbId或GetEntity方法或执行查询得到的,就需要调用EditEntity方法设置实体对象的状态。如果实体对象时使用BuildEntity方法创建的而且还未提交到数据库,则该实体对象已经处于可编辑的状态,因此,不需要使用EditEntity方法。该方法的语法为
    EditEntity (CQEntity entity, String edit_action_name)

    第一个参数为CQEntity对象,第二个参数为一个字符串,用于指定编辑的行为。对于特定记录类型的实例的编辑行为,我们可以通过清单8中的方法查看。

  • 第14行,通过CQEntity对象的SetFieldValue方法改变实体对象的值。
  • 第15-16行,验证通过后,提交对实体记录的修改到用户数据库。
清单7. 修改已存在的记录
1 CQQueryDef queryDef = cqSession.BuildQuery("TMDEFECT");
// set display fields
2 queryDef.BuildField("id");
3 queryDef.BuildField("Headline");
			
4 CQResultSet resultSet = cqSession.BuildResultSet(queryDef);	
5 resultSet.Execute();
6 String id = null;
7 String headline = null;
8 while(resultSet.MoveNext() == 1){
9	id = resultSet.GetColumnValue(1);
10	CQEntity entity = cqSession.GetEntity("TMDEFECT", id);
11	headline = entity.GetFieldStringValue("HeadLine");
				
12	if(id.equals("CQSTF00000141")){
13		cqSession.EditEntity(entity, "Modify");
14		entity.SetFieldValue("Description", "This defect has been modified");
15		entity.Validate();
16		entity.Commit();
17	}
18 }
清单8. 获取编辑活动名称
1 CQEntityDef entityDef = cqSession.GetEntityDef("TMDEFECT");
2 String[] actions = entityDef.GetActionDefNames();
3 for(String action: actions){
4     System.out.println(action);
5 }

访问模式数据库

通常,用户都通过Rational ClearQuest Designer工具修改模式数据库 (master数据库)。但是,在某些情况下,开发人员需要通过API实现对模式数据库的访问并进行一定的修改。由于模式数据库与用户数据库不同,您不能使用CQSession对象登录到模式数据库并访问其中的数据。而必须使用CQAdminSession对象来完成这样的操作。通过CQAdminSession对象,您可以访问与指定模式数据库相关联的用户数据库信息。每个用户数据库都被表示为一个Database对象。您可以使用该对象得到并设置用户数据库的某些信息,如登录用户名、密码以及数据库自身的设置等。我们将分别三个部分向您介绍对模式数据库的访问功能,包括模式数据库登录、访问模式数据库中的对象、更新用户数据库信息。

登录模式数据库

清单9中的代码片段实现了登录到指定模式数据库的功能。首先创建一个CQAdminSession对象,然后指定登录的具体信息,包括登录用户名、密码和数据库集的名称。

清单9. 登录模式数据库
1 CQAdminSession adminSession = new CQAdminSession();
2 adminSession.Logon("admin", "admin", "dbSet");

访问模式数据库中的对象

大多数模式数据库的信息都可以通过访问对象的属性信息获得。例如,CQAdminSession对象包含多个属性,可以得到与特定模式数据库相关的用户数据库信息列表、模式列表、所有的用户和组信息列表。如果您知道对象名称的话,也可以通过CQAdminSession对象得到指定的对象。此外,通过CQAdminSession对象还可以创建新的数据库、用户帐户和用户组。如清单10中的代码片段所示,

  • 第1-2行,通过CQAdminSession对象,得到与特定模式数据库相关联的数据库对象列表和组对象列表。您可以进一步对对象列表中的对象进行解析。
  • 第3行,通过CQAdminSession对象,得到指定名称的CQUser对象。
  • 第4-7行,通过CQAdminSession对象,创建了一个新的用户对象,并设置了其中的属性值,最终将其添加到指定的用户组中。
清单10. 访问模式数据库中的对象
1 CQDatabases dbs = adminSession.GetDatabases();
2 CQGroups groups = adminSession.GetGroups();
			
3 CQUser user = adminSession.GetUser("bill");
4 CQUser aUser = adminSession.CreateUser("testUser");
5 user.SetEmail("testUser@sohu.com");
6 user.SetPassword("testUser");
7 groups.Item(0).AddUser(aUser);

更新用户数据库信息

在提交了新的对象或修改后,这些修改在模式数据库中会立即生效。但需要注意的是,如果您修改了关于用户和组的信息的话,则必须更新关联的用户数据库。例如,如果想要把对模式数据库中用户信息的修改同步到关联的用户数据库中,可以采取以下两种方法实现:

  • 利用CQUser对象的UpgradInfo方法。该方法可以更新用户信息(如is-active, e-mail, full name, phone等)到所有该用户订阅的数据库。但该方法不能更新组中成员的信息。
  • 利用CQDatabase对象的UpgradMasgterUserInfo信息。该方法可以更新一个数据库的所有用户和组信息。

对于已经存在的用户,开发人员可以采取以下方法完成更新同步:

  • 得到指定模式数据库的用户数据库列表,循环访问每一个用户数据库对象,调用该对象的UpgradMasterUserInfo方法进行更新。
  • 调用用户对象的UpgradInfo方法.

对于新创建的用户,如果是通过CQAdminSession对象的CreateUser方法创建的话,您必须循环访问每一个用户数据库,利用该对象的UpgradMasterUserInfo方法进行更新。UpgradInfo方法只适用于已经存在的用户。

总结

结束语

通过阅读本文,我们可以看出Rational ClearQuest是一个高度可定制化的产品,提供了丰富的程序接口,帮助开发人员定制自己应用程序,实现与CQTM的功能集成。本文通过多个实例,向您阐述了CQ Java API提供的常用功能。希望通过本文的介绍,能够帮助开发人员更好地理解和掌握CQ Java API,在未来的工作中能够付诸实践。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational, Java technology
ArticleID=364881
ArticleTitle=使用 IBM Rational ClearQuest Java API 进行集成开发
publish-date=01152009