Build 验证测试(Build Verification Test)是测试过程的第一步,通常只对软件的主干功能进行初步测试,通过验证的 Build 才能转给功能测试人员进行大规模的细化测试,以此确保功能测试人员不会由于安装坏 Build 而浪费时间。
在持续集成的软件开发过程中,构建(Build)服务器一般每天都会编译最新的源代码并构建新的 build,这就要求 Build 验证也以同样的频率紧随进行。另一方面,由于软件的主干功能通常比较稳定,所以 Build 验证的重复性较强。正是因为这两个特点,各软件产品的 Build 验证都力图实现 100% 自动化。
相对 Build 的手工验证,自动验证能够带来以下好处:
- 让 Build 验证人员从枯燥的,简单的重复性测试中解脱出来。
- 自动验证的执行速度比手工验证更快,允许开发人员在最短的时间内获知新 Build 中存在的严重问题,并进行及时修复,功能测试人员也能更快获取值得信赖的新 Build 。
- Build 自动验证系统 7 × 24 小时工作,不受白天黑夜以及人员假期的影响。当 Build 验证人员和开发(及功能测试)人员在时区和国度上存在差异的时候,手工验证就容易滞后。
Build 验证的自动化解决方案
源代码配置管理服务器和构建(Build)服务器是自动化开发环境的一个基本子集,构建(Build)服务器定期编译最新源代码,并生成面向测试人员的 Build 。为了在自动化开发环境中增加 Build 自动验证的功能,这个基本拓扑需要被进一步扩展。如图 1 的红框部分所示,我们添加了构建(Build)验证服务器和验证结果发布服务器。
图 1. 带 Build 自动验证的自动化开发环境
验证结果发布服务器
Build 验证结果需要被持久化存储,所以我们引入验证结果发布服务器,开发人员和测试人员可以通过浏览器查看所有 Build 的验证结果。图 3 展示了验证结果发布服务器的具体实现,构建(Build)验证服务器和发布服务器通过数据库交互,并通过一个 Web 程序进行结果发布;图 4 则是一个典型的验证结果发布的实例。
图 3. 验证结果发布服务器的具体实现
验证结果发布程序的实现相对简单,我们对此不作展开。 Build 自动验证程序则是整个解决方案的核心,下面对它的所有步骤逐一说明。
轮询下载 Build
Build 的下载一般通过 FTP 协议完成,虽然 Windows 和 Unix 的命令脚本都提供相信的 FTP 支持,但用命令脚本不易实现各种错误(例如 络错误或者 Build 服务器不可访问)的处理逻辑,因此脚本运行的容错性和稳定性相对较差。而 Build 自动验证程序要求在无人干预的情况下 7 × 24 小时工作,所以我们选择 Java 实现 Build 轮询下载。图 5 是 Build 轮询下载的基本流程,BuildDownload.java 则是该流程的具体实现。
图 5. Build 轮询下载流程

清单 1. BuildDownload.java
public class BuildDownload { private String server; //Build Server’s IP or host name private int port; //Build Server’s FTP port private String user; //User ID used to log in the Build Server private String pwd; //Password private String remoteBuildDir; //The remote build directory on the Build Server private String localBuildDir; //The local directory to store the downloaded build private int interval; //The interval minutes to search the new build public static void main(String[] args) { //1. Check the input parameter: the full path of the configuration file if (args.length != 1) { System.out.println(“Error – Invalid parameters.”); System.exit(1); } BuildDownload dameon = new BuildDownload(args[0]); //2. Search and download the newest build boolean isSuccess = false; do { isSuccess = dameon.download(); } while(!isSuccess); } public BuildDownload(String configFile) { /*Load the specified property file and initialize the configurations*/ } public boolean download() { FtpClient client = new FtpClient(); InputStream input = null; BufferedInputStream buffer = null; BufferedReader bufferReader = null; FileOutputStream outfile = null; try { System.out.println(“Info – Wait ” + this.interval + ” minutes.”); Thread.sleep(this.interval*60000); //1. Connect to FTP server client.openServer(this.server, this.port); client.login(this.user, this.pwd); //2. Search the newest build on the Build Server System.out.println(“Info – Search the newest build on the Build Server.”); client.cd(this.remoteBuildDir); input = client.list(); bufferReader = new BufferedReader(new InputStreamReader(input)); String newest = “00000000000000.zip”; //The format of build name: yyyyMMddHHmmss.zip while ((temp=bufferReader.readLine())!=null) { String temp = temp.trim(); int start = temp.lastIndexOf(” “); temp = temp.substring(start+1); if ( temp.compareTo(newest) > 0 ) newest = temp; } bufferReader.close(); input.close(); System.out.println(“Info – The newest build on the Build Server is ” + newest); //3. Compare the remote newest build with the latest verified build String latestVerifiedBuild = getLatestVerifiedBuildID(); if (latestVerifiedBuild.compareTo(newest) >= 0) { client.closeServer(); System.out.println(“Info – The build ” + newest + ” has been verified.”); return false; } System.out.println(“Info – A new build ” + newest + ” is ready.”); //4. Download the newest build clearLocalDirectory(); System.out.println(“Info – Start to download the build ” + newest); client.binary(); input = (InputStream)client.get(this.remoteBuildDir + “/” + newest); buffer = new BufferedInputStream(input); outfile = new FileOutputStream(this.localBuildDir + “/” + newest, true); int content; while((content=buffer.read()) != -1) { outfile.write(content); } outfile.flush(); outfile.close(); buffer.close(); input.close(); client.closeServer(); System.out.println(“Info – Finish to download the build ” + newest); return true; } catch (Exception e) { e.printStackTrace(); System.out.println(“Error – Unexpected exception happened.”); return false; } } public String getLatestVerifiedBuildID() { /*Get the latest verified build from the database in the publish server*/ } public void clearLocalDirectory() { /*Clear the local directory in which the downloaded build was stored*/ } }
安装 Build
Build 本身必须提供命令行安装模式,具体过程如下。
- 解压刚下载的最新 Build
- 启动 silent install (安装所需的配置文件必须预先定义好)
- 检查安装日志,确认没有错误发生
- 初步验证安装结果,例如文件系统,数据库,以及创建在 Websphere 应用服务器中的各种配置对象等。
Build 成功安装是执行功能测试用例的前提。如果验证程序无法检测出 Build 安装失败,则其在继续执行功能测试用例时,测试用例必然失败,验证程序虽然仍能判断 Build 是坏的,但问题定位却是错误的:某功能测试用例失败,实际则是安装失败。
为避免这种情况的发生,就要求对实际安装结果进行适当验证。通常来说,简单的日志检查并不充分,我们还要预先搞清正确的安装结果,并以此为标准对实际安装结果进行验证,如文件系统和数据库等。
执行主干功能测试用例
Build 验证只对软件的主干功能进行初步测试,不同软件的测试用例各不相同。在测试用例的自动化开发中,需要注意以下几点:
- 尽量选择相对稳定的系统级接口,如各模块的命令行脚本,J2EE 应用服务器的 mbean 等。这样可以使 Build 自动验证程序长时间稳定运行,而无需频繁修改。
- 对测试用例执行结果进行严格验证,如检查返回代码,日志文件,以及用例生成的各种对象(如数据库记录等),以此提高对坏 Build 的问题自动定位的准确度。
- 避免图形用户界面(GUI)的细节测试。因为在一个完整的软件开发周期中,GUI 的实现是一个渐进的过程,因此它们的自动化测试脚本也需要经常更新。这与 Build 自动验证程序的稳定性要求相背。
- 避免陷入底层的 API 测试,一方面底层 API 本身并不稳定,另一方面单元测试已经覆盖底层 API 的测试。
发布 Build 验证结果
构建(Build)验证服务器需要把 Build 验证结果存储到验证结果发布服务器,两者通过数据库交互,数据库结构可参考 BVT(Build Verification Test)DDL 。
清单 2. BVT DDL
create table BVT.RESULTS ( —- build id —- BUILD_ID VARCHAR(256) NOT NULL, —- start time of BVT —- START_TIME TIMESTAMP, —- end time of BVT —- END_TIME TIMESTAMP, —- whether the build passed BVT —- BVT_STATE SMALLINT, —- result of the download build step —- DOWNLOAD_BUILD SMALLINT, —- result of the silent install step —- SILENT_INSTALL SMALLINT, —- result of the install verification step —- VERIFY_INSTALL SMALLINT, —- result of each test case —- CASE1 SMALLINT, CASE2 SMALLINT, … … —- defect number for the bad build —- DEFECT_NO VARCHAR(20), —- log.zip —- BVT_LOG BLOB(1000M), —- specific description for the build —- NOTES VARCHAR(2048), primary key (BUILD_ID) );
验证结果发布通常包含以下步骤:
- 将测试用例的执行结果存储到验证结果发布服务器。
- 将 Build 验证过程的相关日志存储到验证结果发布服务器。
- 将 Build 验证结果通过 email 发送给相关的测试开发人员。
- 如果被验证 Build 是坏的,则自动在 Bug 追踪系统(如 CMVC)中生成 Defect 。
清理测试环境
Build 验证结果发布以后,必须清理测试环境,为下一个 Build 做好准备。这个步骤非常重要,由于构建(Build)验证服务器需要在无人干预的情况下 7 × 24 小时连续运行,如果环境清理不成功,则可能引起下一次 Build 自动验证的失败,甚至导致构建(Build)验证服务器发送错误的 Build 验证 告。一般来说,有以下几种清理测试环境的方法:
- 调用软件本身的卸载命令。由于软件开发过程中,卸载命令本身可能并不完善,出错的可能性很大,所以该方法使用较少。
- 直接编程删除文件系统的相关文件,数据库中的相关对象,甚至操作系统中的相关配置。该方法可靠性较好,但需要较大的开发工作量,而且在整个软件开发周期中,可能需要经常修改环境清理程序。尤其当被验证的软件需要安装在其他软件之上的时候,环境清理问题会变得更加复杂。
- 准备一个干净的测试环境(如果被验证软件需要安装在其他软件之上,则可事先安装好相关的软件),然后用 Ghost(或其他备份软件)做硬盘备份,清理测试环境时只要简单的从备份映像恢复即可。
方案 3 简单可靠,而且适用于复杂软件(即被验证软件需要安装在其他软件之上)。在 Windows 上,我们可以配置一个任务计划(Scheduled Task)使得自动验证程序在备份映像恢复时能够自启动。
结束语
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树使用JDBC操作数据库数据库操作93916 人正在系统学习中 相关资源:软件滤波杂汇-C代码类资源-CSDN文库
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!