自动化测试可以很大程度的减少人工参与的工作量,提高测试效率。在自动化测试中,测试人员经常需要与 Notes/Domino 数据库打交道,比如说在自动化测试之前,需要从测试用例数据库中挑选出哪些测试用例要被执行;在测试完成之后,需要将测试结果记录到测试用例数据库,或者将测试报告存放到 Notes 某一指定的数据库中,通常这些工作是由手工完成。如果将这些工作自动化,将会很大程度上节约测试时间和测试成本。幸运的是,Lotus Notes/Domino 为程序员提供了一系列 C++/Java API,利用这些 API 可以完成对 Notes 数据库的访问、创建、管理等几乎所有的操作。本文将介绍利用 Lotus Notes API 进行编程,自动操作 Notes/Domino 数据库,使整个测试过程自动完成。
图 1 说明了自动化测试的整体流程:首先从 TCDB 中提取符合条件的测试用例,然后在指定测试机上安装被测软件、执行挑选出来的测试用例、生成测试报告,然后将测试结果回填到 Testcase DB 中,并且将测试报告发送到指定数据库中。
Notes/Domino C++ API 在自动化测试中的应用
C++ API 是在对 Notes C API 进行封装的基础上建立的。由于 C++ 语言的面向对象的特性,所以 C++ API 使用起来更简单一些。
在使用 Notes C++ API 进行编程之前,根据你当前使用的 Notes 版本,需要下载匹配版本的 C++ API Toolkit, 这个工具箱可以从 IBM 网站上得到。该工具箱中包含有 API 帮助文档、库文件、头文件、示例程序以及示例程序中用到的数据库文件等。
在利用 Notes C++ API 进行编程之前,需要先配置 Visual C++,环境配置正确才能保证代码能够正常编译链接。
接下来介绍如何利用 Notes C++ API 访问 Notes, 并对 Notes 数据库中的文档进行操作。
代码清单 1 是个简单的例子程序,目的是得到某个数据库名字。
#include <lncppapi.h> #include <iostream.h> void main(int argc, char *argv[]) { char errorBuf[256]; LNNotesSession session; LNSetThrowAllErrors(TRUE); LNDatabase db; session.Init(); try{ session.GetDatabase(nsfFileName, &db, server); db.Open(); cout <<"DB title: "<< db.GetTitle() <<endl; }catch (LNSTATUS error){ LNGetErrorMessage(error, errorBuf); cout<<"Error: " <<errorBuf <<endl; } db.Close(); session.Term(); return; } |
其中:
lncppapi.h:在利用 Notes API 编程时,一定要包含该头文件。这个文件位于 NotesCPP\Include 目录下,通过该头文件链接到其他的定义所有 API 对象和数据类型的类库。比如 LNNotesSession 类就定义在其中。
Session.Init: 初始化 C++ API,建立与 Notes 的连接,读取 notes.ini 文件,找到当前 Notes 用户 ID。当与 Notes 建立连接之后,就可以操作 Notes 数据库了。
session.term: 在对 notes db 操作完成之后,调用该函数切断与 Notes 的连接、释放资源。
GetDatabase( const LNString &path, LNDatabase *db, const LNString &server = "" ) :其中参数 NSF 文件名和服务器的 hostname 可以通过查看数据库的属性得到,如图 3 所示:
数据库中的每个文档属性(通过右键单击可得到)都是由不同的域组成,通过这些域可以唯一的确定一个文档,我们通过改变域的值对其进行操作。文档属性如图 4 所示:
自动化测试完成之后,测试报告可以自动存放到指定数据库的指定目录下,清单 2 演示了如何对数据库中的文档进行操作。该代码片断目的是先在指定的数据库中新建文档,然后将测试报告导入到该文档中,这样使测试报告更加直观。当然,也可以通过调用
LNRichText::CreateAttachment()方法把测试报告以附件的形式贴在该文档中。
Session.Init(); Session.GetDatabase(nsfFileName, &Db, server); // 连接指定数据库 . LNText Author, Categories, Subject, DocumentType; LNDocument NewDoc, NewRes; Db.Open(); // 首先查找主文档,然后使测试报告对该文档进行回复 SearchFormula = "Subject = \""; SearchFormula += mainDocSubject; SearchFormula += "\""; // 如果找到没有主文档,则新建一个类型为“MainTopic”的文档。 Search()方法,找到文档,返回为 0. if (Db.Search (SearchFormula, &DocResponseTo)) { Db.CreateDocument(&NewDoc, "MainTopic"); Subject.SetValue(mainDocSubject); Author.SetValue("CN=Jing Xing/OU=China/O=IBM"); Categories.SetValue(Category); DocumentType.SetValue("Reference"); // 为文档不同的域设值 NewDoc.CreateItem("From", Author, LNITEMFLAGS_SUMMARY); NewDoc.CreateItem("Subject", Subject, LNITEMFLAGS_SUMMARY); NewDoc.CreateItem("Categories", Categories, LNITEMFLAGS_SUMMARY); NewDoc.CreateItem("DocType", DocumentType, LNITEMFLAGS_SUMMARY); NewDoc.ComputeWithForm(true); NewDoc.Save();// 保存文档 } // 创建文档 , 类型为 Response Db.CreateDocument(&NewRes, "Response"); Subject.SetValue(subSubject); Author.SetValue("CN=Jing Xing/OU=China/O=IBM"); Categories.SetValue(Category); NewRes.CreateItem("From", Author, LNITEMFLAGS_SUMMARY); NewRes.CreateItem("Subject", Subject, LNITEMFLAGS_SUMMARY); // 如果分类不存在,则新建 category if(Category!="") { NewRes.CreateItem("Categories", Categories, LNITEMFLAGS_SUMMARY); } NewRes.CreateItem("ShowAuthors", ShowAuthors, LNITEMFLAGS_SUMMARY); NewRes.MakeResponse(NewDoc); // 对 NewDoc 进行回复 RT.Append("Here is the report: \n\n"); RT.GetEndCursor(&BeginCursor); RT.Import(ReportLocation, &BeginCursor);// 将 report 文件导入新建文档中。 NewRes.CreateItem("Body", RT); NewRes.Save(); Db.close(); Session.term(); |
其中每个函数的具体用法可以参考 NotesAPP 中提供的帮助文档。
同 C++ API 一样,Notes Java API 也可以完成对 Notes/Domino 数据库的大部分操作。不同的是,Java API 使用起来相对更简单一些,不用配置很多的东西,只需要将 ${Notes}/jvm/lib/ext/notes.jar 包含在 classpath 中即可。关于 Java API 的帮助文档可以参考:IBM Lotus Notes and Domino 信息中心。
下面以一段简单的例子说明如何通过 Java API 连接数据库 , 清单 3 是访问某个数据库 , 然后输出该数据库的名字。
Public static void main(String args[]){ try{ NotesThread.sinitThread(); // 启动线程 Session session = NotesFactory .createSession((String)null, (String)null, password); Database database = session.getDatabase(host, nsf, false);// 连接数据库 System.out.println("DataBase tilte is: " + database .getTitle()); } finally { NotesThread.stermThread(); // 结束该线程 } } |
其中:
正如前文提到的,自动化测试时需要从测试用例数据库中选出符合条件的测试用例后自动执行。以下代码清单 4 是从数据库中选出 cycle-001 中所有的执行方法为 Automated 的测试用例,并将其组织成一个测试用例集保存于 .suite 文件中。
String cycle = "CYC-001"; try { NotesThread.sinitThread(); File file = new File("C:/cyc-001.suite");// 该文件用于保存符合条件的测试用例的 ID if (file.getParentFile() != null) file.getParentFile().mkdirs(); suiteFileWriter = new BufferedWriter(new FileWriter(suiteFile)); Session session = NotesFactory .createSession((String)null, (String)null, notesPassword); Database database = session.getDatabase(host, nsf, false); DocumentCollection dc = database .search("ExecCycleID=" + "\"" + cycle + "\"");// 搜索所有属于"CYC-001"的测试用例。 Document doc = dc.getFirstDocument(); while (doc != null) { String method = doc.getItemValueString("Method"); // 得到域”Method”的值 String tcID = doc.getItemValueString("ExecTCID"); if ("Automated".equals(method)) { suiteFileWriter.write("tcID.replace("-", "_") + "\r\n"); } } } } finally { NotesThread.stermThread(); if (suiteFileWriter != null) try { suiteFileWriter.close(); } catch (Exception e) { } } } |
本文介绍了在自动化测试中使用 Notes/Domino 提供的 API 来访问 Notes/Domino 数据库,并进行数据库中文档操作,使在自动化测试中的很多工作可以自动完成。不管使用 Notes C++ API 还是 Java API,都能很好的完成自动化测试时对 Notes/Domino 数据库的操作需求,这大大地增加了测试的自动化程度,节约了测试成本。