(单元测试)

项目

2

企业网站单元测试项目

企业网站开发项目组为了提高软件开发的质量,最近要进行单元测试。根

据项目经理的安排,开发组的程序员小张,下周要对同事小王用JAVA编写的企业网站登录模块的类代码进行测试。根据详细设计说明书,登录模块主要的类有:DBAccess、Userbean二个类。小张应该从哪些方面、采用哪些工具,对小王编写的代码进行单元测试呢?

项目目标与要求

 能根据JAVA编码规范检查用户登录模块相关类的代码  能根据系统详细设计编写登录模块相关类的测试用例

 能熟练使用JNIT工具,根据测试用例对登录模块相关类进行测

 能熟练使用EXCEL工具管理测试中发现的缺陷(BUG)  能写单元测试报告

项目工作任务

 阅读企业网站的开发计划、需求分析、系统概要设计和系统详细设计,制订单元测试计划

 根据JAVA编码规范,检查DBAccess、Userbean二个类的代码(代码是否符合编码规范),并填写检查记录表

 根据详细设计说明书对DBAccess类的主要方法(验证、查询、更新、删除)进行走查(算法分析)

 根据系统详细设计说明书编写企业网站登录模块的单元测试用例

 用EXCEL软件完成测试工作日志,用EXCEL软件管理测试中发现的软件缺陷,并完成单元测试的测试报告

项目任务书

模块一:理解企业网站设计

学习目标

工作任务

1、阅读系统开发计划和需求分析报告 2、阅读登录模块的系统详细设计说明书 3、绘制登录模块单元测试计划甘特图

任务1:阅读系统开发计划和需求分析报告

做一做:

1、打开项目经理提供的项目开发计划,了解单元测试的具体时间安排。

1、理解企业网站开发的计划书和需求分析报告 2、理解登录模块的详细设计说明书 3、能编制登录模块的单元测试计划

4、掌握用PROJECT软件绘制单元测试的甘特图

图2-1企业网站单元测试甘特图

2、打开项目经理提供的企业网站需求分析报告,了解用户对登录的具体需求。

登录模块的具体功能:

输入用户名和密码可以登录到系统,显示系统欢迎页面,如果用户名与

密码不对则显示出错页面

在登录模块中可以进行新用户的注册,单击注册,则显示注册页面,输

入用户、密码和重复密码,系统能够查找是否已注册,如有是显示出错信息,如果没有则写和数据库,显示注册成功信息。

读一读:

任务2:阅读登录模块的系统详细设计说明书

1、打开项目经理提供的企业网站详细设计说明书,分析DBAccess、Userbean

单元测试的概念

单元测试的主要内容和过程 系统不要提供修改密码的功能。

类的类图,登录和注册过程的时序图。

A、类图:

图2-2 系统类图

B、登录的时序图

图2-3 系统登录的时序图

注册用户的时序图

图2-4 系统注册的时序图

主要方法的伪代码: 连接数据库的方法的方法

createConn() { 建立逻辑型就是 b,初设值为假; try { 加载drv成员变量指定的数据库驱动; conn =通过系统方法,根据url, usr, pwd 成员变量的值取得连接对象; b = true;//链接成功 } catch (捕获数据库访问错误) {

}

} catch (捕获驱动类找不到错误) { }

返回 b;

在数据库中查询数据的方法

query(select语句串) { try { stm = conn对象的方法建设命令对象; rs = 执行stm对象的方法执行传入的select语句串; } catch (错误捕获) { } }

验证指定用户名、密码是否存在的方法

valid(用户名串, 密码串) { 建立逻辑变量isValid,并设为假 db =用new操作建立数据库访问对象; if(在数据库对象db执行连接方法) { sql = "select * from user where user_name='"+用户名+"' and user_pass='"+密码+"'";//生成执行的SQL命令 在db对象上执行sql查询; if(db.是否存在记录) { 有记录isValid为真; } 调用db的关闭记录对象; 调用db的关闭命令对象; 调用db的关闭连接对象; } 返回 isValid; }

添加新用户的方法

add(用户名串, 密码串) { db =用new操作建立数据库访问对象; if(在数据库对象db执行连接方法) { String sql = "insert into user(user_id,user_name,user_pass,user_qx) values(null,'"+用户名+"',user_pass='"+密码+"'",2)"; //生成执行的insert命令 在db对象上执行update更新操作; 调用db的关闭命令对象; 调用db的关闭连接对象; } }

读一读:

任务3:绘制登录模块单元测试计划的甘特图

1、根据开发计划,编写登录模块单元测试的计划。

类图 时序图

2、在Project中绘制登录模块单元测试计划的甘特图。

图2-5 登录模块单元测试甘特图

操作步骤:

(1) 启动Project,打开项目计划.mpp文件

(2) 选择“网站模块二”任务项,单击“插入菜单”,选取“插入任务” (3) 输入在任务名称栏中输入“理解项目计划与系统设计”,将工期改为0.4 (4) 单击工具栏的“下移”工具按钮

(5) 反复(2),(3),(4)步骤,分别建立“编写单元测试计划”、“代码检查”、

“重要算法代码走查”、“编写单元测试用例”、“在Junit中执行测试”和“编写测试报告”任务

(6) 选取刚才添加的7个任务项,单击工具栏的“链接”按钮

(7) 设置显示比例:选择“登录模块单元测试”任务项,单击“视图”菜单,

选择“显示比例”菜单子项,在显示比例对话框中选取“选择任务”项,

单击确认。

读一读:

甘特图

Project2003的使用

模块二:检查DBAccess、Userbean类的代码

学习目标

工作任务

1、阅读JAVA编码规范 2、检查DBAccess类的代码 3、检查Userbean类的代码 1、掌握JAVA代码的格式要求 2、掌握JAVA代码的命名要求 3、掌握JAVA代码的注释要求

任务1:阅读JAVA编码规范

1、掌握JAVA代码的格式要求

Java源文件还遵循以下规则:

(1) 开头注释(参见"开头注释")

(2) 包和引入语句(参见"包和引入语句") (3) 类和接口声明(参见"类和接口声明")

类/接口声明的各部分 注解

(1) 类/接口文档注释(/**„„*/) 该注释中所需包含的信息,参见"

文档注释"

(2) 类或接口的声明

(3) 类/接口实现的注释(/*„„*/)如果有必要的话 该注释应包含任

何有关整个类或接口的信息,而这些信息又不适合作为类/接口文档注释。

(4) 类的(静态)变量 首先是类的公共变量,随后是保护变量,再后是

包一级别的变量(没有访问修饰符,access modifier),最后是私有变量。

(5) 实例变量 首先是公共级别的,随后是保护级别的,再后是包一级

别的(没有访问修饰符),最后是私有级别的。 (6) 构造器

(7) 方法 这些方法应该按功能,而非作用域或访问权限,分组。例如,

一个私有的类方法可以置于两个公有的实例方法之间。其目的是为了更便于阅读和理解代码。

4个空格常被作为缩进排版的一个单位。

尽量避免一行的长度超过80个字符,因为很多终端和工具不能很好处理之。

当一个表达式无法容纳在一行内时,可以依据如下一般规则断开之:

(1) 在一个逗号后面断开 (2) 在一个操作符前面断开

(3) 宁可选择较高级别(higher-level)的断开,而非较低级别(lower-level)

的断开

(4) 新的一行应该与上一行同一级别表达式的开头处对齐

(5) 如果以上规则导致你的代码混乱或者使你的代码都堆挤在右边,

那就代之以缩进8个空格。

只在代码块的开始处声明变量,尽量在声明局部变量的同时初始化,推荐

一行一个声明,因为这样以利于写注释。

复合语句是包含在大括号中的语句序列,形如"{ 语句 }"。例如下面各段。 (1) 被括其中的语句应该较之复合语句缩进一个层次

(2) 左大括号"{"应位于复合语句起始行的行尾;右大括号"}"应另起一行并

与复合语句首行对齐。

(3) 大括号可以被用于所有语句,包括单个语句,只要这些语句是诸如

if-else或for控制结构的一部分。这样便于添加语句而无需担心由于忘了加括号而引入bug。

下列情况应该总是使用两个空行:

(1) 一个源文件的两个片段(section)之间 (2) 类声明和接口声明之间 下列情况应该总是使用一个空行: (1) 两个方法之间

(2) 方法内的局部变量和方法的第一条语句之间

(3) 块注释(参见"5.1.1")或单行注释(参见"5.1.2")之前

一个方法内的两个逻辑段之间,用以提高可读性,若没有足够理由,不要

把实例或类变量声明为公有;

避免用一个对象访问一个类的静态变量和方法;

一般而言,在含有多种运算符的表达式中使用圆括号来避免运算符优先级

问题,是个好方法;

不要使用内嵌(embedded)赋值运算符试图提高运行时的效率; 不要将赋值运算符用在容易与相等关系运算符混淆的地方; 避免在一个语句中给多个变量赋相同的值。

2、掌握JAVA代码的命名要求

包(Packages) 一个唯一包名的前缀总是全部小写的ASCII字母并且是一个

顶级域名,通常是com,edu,gov,mil,net,org,或1981年ISO 3166标准所指定的标识国家的英文双字符代码。包名的后续部分根据不同机构各自内部的命名规范而不尽相同。这类命名规范可能以特定目录名的组成来区分部门;

类(Classes) 命名规则:类名是个一名词,采用大小写混合的方式,每个单

词的首字母大写;

方法(Methods) 方法名是一个动词,采用大小写混合的方式,第一个单词的

首字母小写,其后单词的首字母大写。

变量(Variables) 除了变量名外,所有实例,包括类,类常量,均采用大小写混合的方式,第一个单词的首字母小写,其后单词的首字母大写。变量名不应以下划线或美元符号开头,尽管这在语法上是允许的。

变量名应简短且富于描述。变量名的选用应该易于记忆,即,能够指出其

用途。尽量避免单个字符的变量名,除非是一次性的临时变量。临时变量通常被取名为i,j,k,m和n,它们一般用于整型;c,d,e,它们一般用于字符型。

实例变量(Instance Variables) 大小写规则和变量名相似,除了前面需要一个

下划线;

常量(Constants) 类常量和ANSI常量的声明,应该全部大写,单词间用下

划线隔开。

3、掌握JAVA代码的注释要求

实现注释是那些在C++中见过的,使用/*...*/和//界定的注释。文档注释(被

称为"doc comments")是Java独有的,并由/**...*/界定。文档注释可以通过javadoc工具转换成HTML文件。

实现注释用以注释代码或者实现细节。文档注释从实现自由

(implementation-free)的角度描述代码的规范。它可以被那些手头没有源码的开发人员读懂。

注释应被用来给出代码的总括,并提供代码自身没有提供的附加信息。注

释应该仅包含与阅读和理解程序有关的信息。

文档注释描述Java的类、接口、构造器,方法,以及字段(field)。每个文档注释都会被置于注释定界符/**...*/之中,一个注释对应一个类、接口或成员。该注释应位于声明之前。

描述类和接口的文档注释的第一行(/**)不需缩进;随后的文档注释每行都

缩进1格(使星号纵向对齐)。成员,包括构造函数在内,其文档注释的第一行缩进4格,随后每行都缩进5格。

类、接口、变量或方法的信息,而这些信息又不适合写在文档中,则可使

用实现块注释(见5.1.1)或紧跟在声明后面的单行注释(见5.1.2)。例如,有关一个类实现的细节,应放入紧跟在类声明后面的实现块注释中,而不是放在文档注释中。

块注释通常用于提供对文件,方法,数据结构和算法的描述。块注释被置

于每个文件的开始处以及每个方法之前。它们也可以被用于其他地方,比如方法内部。在功能和方法内部的块注释应该和它们所描述的代码具有一样的缩进格式。

极短的注释可以与它们所要描述的代码位于同一行,但是应该有足够的空白来分开代码和注释。若有多个短注释出现于大段代码中,它们应该具有相同的缩进。 读一读:

编码规范 驼峰命名法则 注释的重要性

任务2:检查DBAccess类的代码

DBAccess类的代码如下:

package com.javabean;

import java.sql.Connection;

import java.sql.DriverManager; import java.sql.ResultSet;

import java.sql.SQLException; import java.sql.Statement;

public class DBAccess { public static String drv ; public static String url ; public static String usr ; public static String pwd ; private Connection conn = null; private Statement stm = null; private ResultSet rs = null; public boolean createConn() { boolean b = false; try { Class.forName(drv).newInstance(); conn = DriverManager.getConnection(url, usr, pwd); b = true; } catch (SQLException e) { } catch (ClassNotFoundException e) { } catch (InstantiationException e) {

}

}

return b;

public boolean update(String sql) { boolean b = false; try { stm = conn.createStatement(); stm.executeUpdate(sql); b = true; } catch (Exception e) { System.out.println(e.toString()); } return b; }

public void query(String sql) { try { stm = conn.createStatement(); rs = stm.executeQuery(sql); } catch (Exception e) { } }

public boolean next() { boolean b = false; try { if(rs.next()) b = true; } catch (Exception e) { } return b; }

public String getValue(String field) { String value = ""; try { if(rs!=null)value = rs.getString(field); } catch (Exception e) { e.printStackTrace(); } if (value == null) value = ""; return value; }

public void closeConn() { try { if (conn != null) conn.close(); } catch (SQLException e) { } }

public void closeStm() { try { if (stm != null) stm.close(); } catch (SQLException e) {

}

}

public void closeRs() { try { if (rs != null) rs.close(); } catch (SQLException e) { } }

1、 检查代码书写格式是否附合要求

代码的总体结构 空行的使用 {}的使用 空格的使用 缩进的使用 2、

检查代码中类、属性、方法、变量的命名是否附合要求

类的命名 成员属性的命名 成员方法的命名 临时变量的命名 3、

检查代码中的注释是否附合要求

文件注释 类注释

成员变量的注释 成员方法的注释 重点条件语句的注释 4、 填写DBAccess类检查结果汇总表

任务3:检查Userbean类的代码

Userbean类的代码

package com.javabean;

public class UserBean { public boolean valid(String username, String password) { boolean isValid = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where

user_name='"+username+"' and user_pass='"+password+"'"; db.query(sql); if(db.next()) { isValid = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isValid; } public boolean isExist(String username) { boolean isExist = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where user_name='"+username+"'"; db.query(sql); if(db.next()) { isExist = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isExist; } public void add(String username, String password) { DBAccess db = new DBAccess(); if(db.createConn()) {

String sql = "insert into

user(user_id,user_name,user_pass,user_qx)

values(null,'"+username+"','"+password+"',2)"; db.update(sql); db.closeStm(); db.closeConn(); } } }

1、

检查代码书写格式是否附合要求

代码的总体结构 空行的使用 {}的使用 空格的使用 缩进的使用 2、

检查代码中类、属性、方法、变量的命名是否附合要求

类的命名 成员属性的命名 成员方法的命名 临时变量的命名 3、

检查代码中的注释是否附合要求

文件注释 类注释

成员变量的注释 成员方法的注释 重点条件语句的注释 4、 填写Userbean类检查结果汇总表

模块三:编写测试用例

学习目标

工作任务

1、编写DBAaccess类的单元测试的测试用例

任务1:编写DBAaccess类的单元测试的测试用例

DBAaccess类主要用于系统对数据库的底层访问,提供了连接、查询、是2、编写Userbean类的单元测试的测试用例 1、测试用例的一般格式

2、掌握用条件组合覆盖法编写测试用例 3、掌握用基本路径法编写测试用例

否为纪录尾、取得当前记录指定字段的值、更新、关闭记录、关闭命令、关闭连接等方法。

1、createConn()方法的测试用例设计 DBAaccess类的createConn()方法是完成与数据库的链接操作,主要包含try,catch语句,因此采用语句覆盖法来设计测试用例比较适合。

public boolean createConn() { boolean b = false; try { Class.forName(drv).newInstance(); conn = DriverManager.getConnection(url, usr, pwd); b = true; } catch (SQLException e) { } catch (ClassNotFoundException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { } return b;

}

测试路径:

createConn()方法的测试用例

2、 Query()和next()方法测试用例的编写

DBAaccess类的Query()和next()方法是完成与数据库的查询操作和判断是否

有记录,主要包含try,catch语句,因此采用语句覆盖法来设计测试用例比较

适合。

public void query(String sql) { try { stm = conn.createStatement(); rs = stm.executeQuery(sql); } catch (Exception e) { } catch (SQLException e) { e.printStackTrace(); } } public boolean next() { boolean b = false; try { if(rs.next()) b = true; } catch (Exception e) { e.printStackTrace(); }

}

return b;

测试路径:

Query()和next()方法的测试用例

3、 getValue()方法测试用例的编写

DBAaccess类的getValue()方法是用于从对象中取得指定字段的值,主要包

含try,catch语句和条件语句,因此采用语句覆盖法和条件覆盖法来设计测试用例比较适合。

public String getValue(String field) {

String value = ""; try { if(rs!=null)value = rs.getString(field); } catch (Exception e) { e.printStackTrace(); } if (value == null) value = ""; return value; } 测试路径:

getValue()方法的测试用例

4、 update()方法测试用例的编写

DBAaccess类的update()方法是用于通过SQL命令更新、插入和删除库中的数

据,主要包含try,catch语句,因此采用语句覆盖法来设计测试用例比较适合。 public boolean update(String sql) { boolean b = false; try {

stm = conn.createStatement(); stm.executeUpdate(sql); b = true; } catch (Exception e) { System.out.println(e.toString()); } return b; } 测试路径:

update()方法的测试用例

读一读:

任务2:编写Userbean类的单元测试的测试用例

CMMI3中推荐的测试用例的格式

Userbean类主要提供系统用户管理的相关操作,主要包括:验证明户是否

合法、查询拽定用户是否存在和添加用户的方法。

1、valid()方法测试用例的编写 Userbean类的valid()方法根据用户名和密码验证此用户是否合法,主要包

含2个if语句,因此采用条件组合覆盖法来设计测试用例比较适合。 源程序:

public boolean valid(String username, String password) { boolean isValid = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where

user_name='"+username+"' and user_pass='"+password+"'"; db.query(sql); if(db.next()) { isValid = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isValid; } 测试路径:

2、isExist()方法测试用例的编写

Userbean类的isExist()方法是在数据库中查询指定的用户名是否已存在,主要包含2个if语句,因此采用条件组合覆盖法来设计测试用例比较适合。

public boolean isExist(String username) { boolean isExist = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where user_name='"+username+"'"; db.query(sql); if(db.next()) { isExist = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isExist; } 测试路径:

isExist()的测试用例:

3、add()方法测试用例的编写

Userbean类的add()方法用于向数据库中添加指定的用户名,主要包含1个if语句,因此采用条件覆盖法来设计测试用例比较适合。

public void add(String username, String password) { DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "insert into

user(user_id,user_name,user_pass,user_qx)

values(null,'"+username+"','"+password+"',2)"; db.update(sql); db.closeStm(); db.closeConn(); } } 测试路径:

add ()的测试用例:

模块4:用Junit单元测试工具测试登录模块

学习目标

工作任务

1、建立Eclipse+JAVA+MYSQL测试环境

2、根据编写的DBAaccess类测试用例,用Junit测试DBAaccess类 3、根据编写的Userbean类测试用例,用Junit测试Userbean类

任务1:建立Eclipse+JAVA+MYSQL测试环境 一、安装MYSQL5.1

1、安装MYSQL5.1(参考MYSQL的相关资料) 2、MYSQL5.1配置

MySQL提供了 “Developer Machine(开发测试类,mysql 占用很少资源)”、“Server Machine(服务器类型,mysql占用较多资源)”、“Dedicated MySQL Server Machine(专门的数据库服务器,mysql占用所有可用资源)”3种服务器类型。对于系统开发和测试一般选“Developer Machine”。

MySQL数据库的用途有:“Multifunctional Database(通用多功能型,好)”、“Transactional Database Only(服务器类型,专注于事务处理,一般)”、“Non-Transactional Database Only(非事务处理型,较简单,主要做一些监控、记数用,对MyISAM数据类型的支持仅限于non-transactional)。对于系统开发和测试一般选“Transactional Database Only(服务器类型,专注于事务处理,一般)”。

设置MsySql使用的字符集,如图2-6。对于中文环境一般选“Manual Selected 1、掌握Eclipse+JAVA+MYSQL测试环境的建立 2、掌握Junit单元测试工具的使用 2、能根据测试用例编写测试驱动程序

Default Character Set/Collation”,然后在Character Set 那里选择或填入“gbk”。

对于Windows测试环境,应该设置为“Insrall As windowsa Service”安装

为windows 服务并给这个服务命名。

设置root 用户(超级管理)的密码(默认为空),在“New root password”中填入新密码,按“Execute”使设置生效。

图2-6 MySQL设置字符集

二、首先安装JDK1.5

参考JAVA相关书籍中的JDK安装方法

三、安装Eclipse

Eclipse是java开发工具,无须安装,只需要将其解压缩到适当的目录即可。

四、加载指定的JAVA项目

启动Eclipse,在Package Explorer窗体中,单击右键(或者单击“File”菜

单项),选择“Import„„”菜单项,如图2-7:

图2-7在Eclipse中添加已存在的JAVA项目

显示“Import对话框”,展开“General”项,选取“Exisiting Projects into Workspace”项,如图2-8:

图2-8选择项目的类型

单击“Browse„„”按钮,选取JAVA工程所在的文件平,单击确定。 五、安装MYSQL的JAVA驱动包

下载MYSQL的JAVA驱动包:mysql-connector-java-5.0.8-bin.jar

启动Eclipse,在项目上单击右键,选择“Build Path”,选取“Configure Build

Path”项。显示图2-9:

图2-9 设置JAVA项目的mysql库文件

在对话框中选择Libraries“选项卡”,单击“Add External JARs„„”按钮,在显示的文件对话框中,选择 mysql-connector-java-5.0.8-bin.jar包所在文夹,选择mysql-connector-java-5.0.8-bin.jar文件包,单击“打开”按钮。

任务2:根据编写的DBAaccess类测试用例,用Junit测试DBAaccess类

在Eclipse中打开包括DBAaccess类的工程,单击工具的“新建”工具,选择

“Junit Test Case”项,在弹出的对话框中输入“DBAccessTest”类名,单击“Finish”。

在新建立的DBAccessTest.java类中输入如下的内容:

package com.javabean; import junit.framework.*;

public class DBAccessTest extends TestCase {

public void testCreateConn_1() { }

public void test_Q_1() { }

public void test_G_1() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="select * from user where user_id=1"; db.query( Sql_1 );

Assert.assertTrue(db.next());

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess();

Assert.assertTrue(db.createConn());

}

DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="select * from user where user_id=1"; db.query( Sql_1 ); db.next();

String V_1=db.getValue("user_name"); Assert.assertTrue(V_1.equals("admin"));

public void test_G_2() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="select * from user where user_id=1"; db.query( Sql_1 ); db.next();

String V_1=db.getValue("user_pass"); Assert.assertTrue(V_1.equals("admin"));

}

public void test_U_1() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="UPDATE user SET user_name='Jack' WHERE

user_id =9";

db.update( Sql_1 );

String Sql_2="select * from news where id=8"; db.query(Sql_2);

db.next();

String V_1=db.getValue("title");

Assert.assertTrue(V_1.equals("Jack"));

}

public void test_U_2() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="delete from user where user_id =8"; db.update( Sql_1 );

String Sql_2="select * from user where user_id=8"; db.query(Sql_2);

Assert.assertTrue(!db.next());

}

public void test_I_2() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="insert into user( user_name ,user_pass )

values ('user_10','user_10')";

db.update( Sql_1 );

String Sql_2="select * from user where

user_name='user_10'"; }

}

db.query(Sql_2);

Assert.assertTrue(db.next());

执行为这个测试类:单击工具栏中的“运行”工具,选择“Run As”,选择

“Junit Test”。

测试结果如图2-10,显示测试的脚本数和正确、错误、失败的数量,在明细列表中打上钩的为测试通过,打叉的表示错误,以及测试所用的时间。

图2-10 DBAccessTest的测试报告

任务3、根据编写的Userbean类测试用例,用Junit测试Userbean类

根据任务2的操作方式,在Eclipse中建立测试类UserBeanTest,根据模块

二中建立的测试用例,编写测试驱动程序代码,部分参考代码如下: package com.javabean;

import junit.framework.Assert; import junit.framework.TestCase;

public class UserBeanTest extends TestCase {

public void testValid_1() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

}

Assert.assertTrue(U_1.valid("admin", "admin"));

public void testValid_2() { }

public void testValid_3() { }

public void testIsExist_1() { }

public void testIsExist_2() { }

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.isExist("user_10")); DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.isExist("admin")); DBAccess.drv="cm.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.valid("user_10", "user_10")); DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.valid("user_10", "user_10"));

}

public void testAdd_1() { }

public void testAdd_2() { }

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean(); U_1.add("user_a","");

Assert.assertTrue(U_1.valid("user_a", "")); DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean(); U_1.add("Nice","Nice");

Assert.assertTrue(U_1.valid("Nice", "Nice"));

执行测试的结果如图-11。

图2-11 UserBeanTest测试结果

模块4:缺陷管理并完成测试报告

任务一:用EXCEL对测试中发现的缺陷进行管理 对于模块3中发现的缺陷,要填写如下的表格:

Bug管理表

注:

Bug编号:一般采用模块名+序号的方式编排,模块名在详细设计中确定 Bug描述:对Bub进行具体描述,包括是哪个测试用例发现的Bug

Bug严重程序:根据Bug对系统的影响程度,一般由测试主管确定严重程序 Bug优先级:解决Bug的先后顺序。

状态:如果再次测试通过了,状态为关闭,如果再次测试没通过则为打开

读一读: 软件缺陷 回归测试

任务2:根据测试的结果,完成单元测试报告

单元测试完成后,要根据测试的结果填写下面的单元测试报告: 1、项目说明

(对测试对象和测试范围进行简要说明。) 2、测试依据

(本次测试依据的相关项目文档和通用标准。) 3、人员及进度

4、测试概要 4.1测试环境

(简要介绍测试环境及其配置。 4.2测试用例

(简要介绍测试用例的设计方法。) 4.3测试方法

简要介绍测试中采用的方法(和工具)。主要是黑盒测试,测试方法可以写上测试的重点和采用的测试模式。工具为可选项,当使用到测试工具和相关工具时,要说明。 5、 覆盖分析 5.1需求覆盖

需求覆盖率是指经过测试的需求/功能和需求规格说明书中所有需求/功能的比值,通常情况下要达到100%的目标。

需求覆盖率计算:测试通过数目/需求总数 ×100% 5.2测试覆盖

测试覆盖率计算

:执行数/用例总数 ×100% 6、 缺陷统计 6.1缺陷汇总

按阶段测试统计

按缺陷严重程度 6.2缺陷分析

缺陷密度 = 缺陷总数/功能点总数 严重缺陷摘要:

6.3遗留缺陷

7、 测试结论与建议 7.1测试结论

a) 测试执行是否充分(可以增加对安全性、可靠性、可维护性和

功能性描述)

b) 对测试风险的控制措施和成效 c) 测试目标是否完成 d) 测试是否通过

e) 是否可以进入下一阶段项目目标 7.2测试建议

a) 对系统存在问题的说明,描述测试所揭露的软件缺

陷和不足,

以及可能给软件实施和运行带来的影响 b) 可能存在的潜在缺陷和后续工作 c) 对缺陷修改和产品设计的建议 d) 对过程改进方面的建议 8、 评审意见

项目

2

企业网站单元测试项目

企业网站开发项目组为了提高软件开发的质量,最近要进行单元测试。根

据项目经理的安排,开发组的程序员小张,下周要对同事小王用JAVA编写的企业网站登录模块的类代码进行测试。根据详细设计说明书,登录模块主要的类有:DBAccess、Userbean二个类。小张应该从哪些方面、采用哪些工具,对小王编写的代码进行单元测试呢?

项目目标与要求

 能根据JAVA编码规范检查用户登录模块相关类的代码  能根据系统详细设计编写登录模块相关类的测试用例

 能熟练使用JNIT工具,根据测试用例对登录模块相关类进行测

 能熟练使用EXCEL工具管理测试中发现的缺陷(BUG)  能写单元测试报告

项目工作任务

 阅读企业网站的开发计划、需求分析、系统概要设计和系统详细设计,制订单元测试计划

 根据JAVA编码规范,检查DBAccess、Userbean二个类的代码(代码是否符合编码规范),并填写检查记录表

 根据详细设计说明书对DBAccess类的主要方法(验证、查询、更新、删除)进行走查(算法分析)

 根据系统详细设计说明书编写企业网站登录模块的单元测试用例

 用EXCEL软件完成测试工作日志,用EXCEL软件管理测试中发现的软件缺陷,并完成单元测试的测试报告

项目任务书

模块一:理解企业网站设计

学习目标

工作任务

1、阅读系统开发计划和需求分析报告 2、阅读登录模块的系统详细设计说明书 3、绘制登录模块单元测试计划甘特图

任务1:阅读系统开发计划和需求分析报告

做一做:

1、打开项目经理提供的项目开发计划,了解单元测试的具体时间安排。

1、理解企业网站开发的计划书和需求分析报告 2、理解登录模块的详细设计说明书 3、能编制登录模块的单元测试计划

4、掌握用PROJECT软件绘制单元测试的甘特图

图2-1企业网站单元测试甘特图

2、打开项目经理提供的企业网站需求分析报告,了解用户对登录的具体需求。

登录模块的具体功能:

输入用户名和密码可以登录到系统,显示系统欢迎页面,如果用户名与

密码不对则显示出错页面

在登录模块中可以进行新用户的注册,单击注册,则显示注册页面,输

入用户、密码和重复密码,系统能够查找是否已注册,如有是显示出错信息,如果没有则写和数据库,显示注册成功信息。

读一读:

任务2:阅读登录模块的系统详细设计说明书

1、打开项目经理提供的企业网站详细设计说明书,分析DBAccess、Userbean

单元测试的概念

单元测试的主要内容和过程 系统不要提供修改密码的功能。

类的类图,登录和注册过程的时序图。

A、类图:

图2-2 系统类图

B、登录的时序图

图2-3 系统登录的时序图

注册用户的时序图

图2-4 系统注册的时序图

主要方法的伪代码: 连接数据库的方法的方法

createConn() { 建立逻辑型就是 b,初设值为假; try { 加载drv成员变量指定的数据库驱动; conn =通过系统方法,根据url, usr, pwd 成员变量的值取得连接对象; b = true;//链接成功 } catch (捕获数据库访问错误) {

}

} catch (捕获驱动类找不到错误) { }

返回 b;

在数据库中查询数据的方法

query(select语句串) { try { stm = conn对象的方法建设命令对象; rs = 执行stm对象的方法执行传入的select语句串; } catch (错误捕获) { } }

验证指定用户名、密码是否存在的方法

valid(用户名串, 密码串) { 建立逻辑变量isValid,并设为假 db =用new操作建立数据库访问对象; if(在数据库对象db执行连接方法) { sql = "select * from user where user_name='"+用户名+"' and user_pass='"+密码+"'";//生成执行的SQL命令 在db对象上执行sql查询; if(db.是否存在记录) { 有记录isValid为真; } 调用db的关闭记录对象; 调用db的关闭命令对象; 调用db的关闭连接对象; } 返回 isValid; }

添加新用户的方法

add(用户名串, 密码串) { db =用new操作建立数据库访问对象; if(在数据库对象db执行连接方法) { String sql = "insert into user(user_id,user_name,user_pass,user_qx) values(null,'"+用户名+"',user_pass='"+密码+"'",2)"; //生成执行的insert命令 在db对象上执行update更新操作; 调用db的关闭命令对象; 调用db的关闭连接对象; } }

读一读:

任务3:绘制登录模块单元测试计划的甘特图

1、根据开发计划,编写登录模块单元测试的计划。

类图 时序图

2、在Project中绘制登录模块单元测试计划的甘特图。

图2-5 登录模块单元测试甘特图

操作步骤:

(1) 启动Project,打开项目计划.mpp文件

(2) 选择“网站模块二”任务项,单击“插入菜单”,选取“插入任务” (3) 输入在任务名称栏中输入“理解项目计划与系统设计”,将工期改为0.4 (4) 单击工具栏的“下移”工具按钮

(5) 反复(2),(3),(4)步骤,分别建立“编写单元测试计划”、“代码检查”、

“重要算法代码走查”、“编写单元测试用例”、“在Junit中执行测试”和“编写测试报告”任务

(6) 选取刚才添加的7个任务项,单击工具栏的“链接”按钮

(7) 设置显示比例:选择“登录模块单元测试”任务项,单击“视图”菜单,

选择“显示比例”菜单子项,在显示比例对话框中选取“选择任务”项,

单击确认。

读一读:

甘特图

Project2003的使用

模块二:检查DBAccess、Userbean类的代码

学习目标

工作任务

1、阅读JAVA编码规范 2、检查DBAccess类的代码 3、检查Userbean类的代码 1、掌握JAVA代码的格式要求 2、掌握JAVA代码的命名要求 3、掌握JAVA代码的注释要求

任务1:阅读JAVA编码规范

1、掌握JAVA代码的格式要求

Java源文件还遵循以下规则:

(1) 开头注释(参见"开头注释")

(2) 包和引入语句(参见"包和引入语句") (3) 类和接口声明(参见"类和接口声明")

类/接口声明的各部分 注解

(1) 类/接口文档注释(/**„„*/) 该注释中所需包含的信息,参见"

文档注释"

(2) 类或接口的声明

(3) 类/接口实现的注释(/*„„*/)如果有必要的话 该注释应包含任

何有关整个类或接口的信息,而这些信息又不适合作为类/接口文档注释。

(4) 类的(静态)变量 首先是类的公共变量,随后是保护变量,再后是

包一级别的变量(没有访问修饰符,access modifier),最后是私有变量。

(5) 实例变量 首先是公共级别的,随后是保护级别的,再后是包一级

别的(没有访问修饰符),最后是私有级别的。 (6) 构造器

(7) 方法 这些方法应该按功能,而非作用域或访问权限,分组。例如,

一个私有的类方法可以置于两个公有的实例方法之间。其目的是为了更便于阅读和理解代码。

4个空格常被作为缩进排版的一个单位。

尽量避免一行的长度超过80个字符,因为很多终端和工具不能很好处理之。

当一个表达式无法容纳在一行内时,可以依据如下一般规则断开之:

(1) 在一个逗号后面断开 (2) 在一个操作符前面断开

(3) 宁可选择较高级别(higher-level)的断开,而非较低级别(lower-level)

的断开

(4) 新的一行应该与上一行同一级别表达式的开头处对齐

(5) 如果以上规则导致你的代码混乱或者使你的代码都堆挤在右边,

那就代之以缩进8个空格。

只在代码块的开始处声明变量,尽量在声明局部变量的同时初始化,推荐

一行一个声明,因为这样以利于写注释。

复合语句是包含在大括号中的语句序列,形如"{ 语句 }"。例如下面各段。 (1) 被括其中的语句应该较之复合语句缩进一个层次

(2) 左大括号"{"应位于复合语句起始行的行尾;右大括号"}"应另起一行并

与复合语句首行对齐。

(3) 大括号可以被用于所有语句,包括单个语句,只要这些语句是诸如

if-else或for控制结构的一部分。这样便于添加语句而无需担心由于忘了加括号而引入bug。

下列情况应该总是使用两个空行:

(1) 一个源文件的两个片段(section)之间 (2) 类声明和接口声明之间 下列情况应该总是使用一个空行: (1) 两个方法之间

(2) 方法内的局部变量和方法的第一条语句之间

(3) 块注释(参见"5.1.1")或单行注释(参见"5.1.2")之前

一个方法内的两个逻辑段之间,用以提高可读性,若没有足够理由,不要

把实例或类变量声明为公有;

避免用一个对象访问一个类的静态变量和方法;

一般而言,在含有多种运算符的表达式中使用圆括号来避免运算符优先级

问题,是个好方法;

不要使用内嵌(embedded)赋值运算符试图提高运行时的效率; 不要将赋值运算符用在容易与相等关系运算符混淆的地方; 避免在一个语句中给多个变量赋相同的值。

2、掌握JAVA代码的命名要求

包(Packages) 一个唯一包名的前缀总是全部小写的ASCII字母并且是一个

顶级域名,通常是com,edu,gov,mil,net,org,或1981年ISO 3166标准所指定的标识国家的英文双字符代码。包名的后续部分根据不同机构各自内部的命名规范而不尽相同。这类命名规范可能以特定目录名的组成来区分部门;

类(Classes) 命名规则:类名是个一名词,采用大小写混合的方式,每个单

词的首字母大写;

方法(Methods) 方法名是一个动词,采用大小写混合的方式,第一个单词的

首字母小写,其后单词的首字母大写。

变量(Variables) 除了变量名外,所有实例,包括类,类常量,均采用大小写混合的方式,第一个单词的首字母小写,其后单词的首字母大写。变量名不应以下划线或美元符号开头,尽管这在语法上是允许的。

变量名应简短且富于描述。变量名的选用应该易于记忆,即,能够指出其

用途。尽量避免单个字符的变量名,除非是一次性的临时变量。临时变量通常被取名为i,j,k,m和n,它们一般用于整型;c,d,e,它们一般用于字符型。

实例变量(Instance Variables) 大小写规则和变量名相似,除了前面需要一个

下划线;

常量(Constants) 类常量和ANSI常量的声明,应该全部大写,单词间用下

划线隔开。

3、掌握JAVA代码的注释要求

实现注释是那些在C++中见过的,使用/*...*/和//界定的注释。文档注释(被

称为"doc comments")是Java独有的,并由/**...*/界定。文档注释可以通过javadoc工具转换成HTML文件。

实现注释用以注释代码或者实现细节。文档注释从实现自由

(implementation-free)的角度描述代码的规范。它可以被那些手头没有源码的开发人员读懂。

注释应被用来给出代码的总括,并提供代码自身没有提供的附加信息。注

释应该仅包含与阅读和理解程序有关的信息。

文档注释描述Java的类、接口、构造器,方法,以及字段(field)。每个文档注释都会被置于注释定界符/**...*/之中,一个注释对应一个类、接口或成员。该注释应位于声明之前。

描述类和接口的文档注释的第一行(/**)不需缩进;随后的文档注释每行都

缩进1格(使星号纵向对齐)。成员,包括构造函数在内,其文档注释的第一行缩进4格,随后每行都缩进5格。

类、接口、变量或方法的信息,而这些信息又不适合写在文档中,则可使

用实现块注释(见5.1.1)或紧跟在声明后面的单行注释(见5.1.2)。例如,有关一个类实现的细节,应放入紧跟在类声明后面的实现块注释中,而不是放在文档注释中。

块注释通常用于提供对文件,方法,数据结构和算法的描述。块注释被置

于每个文件的开始处以及每个方法之前。它们也可以被用于其他地方,比如方法内部。在功能和方法内部的块注释应该和它们所描述的代码具有一样的缩进格式。

极短的注释可以与它们所要描述的代码位于同一行,但是应该有足够的空白来分开代码和注释。若有多个短注释出现于大段代码中,它们应该具有相同的缩进。 读一读:

编码规范 驼峰命名法则 注释的重要性

任务2:检查DBAccess类的代码

DBAccess类的代码如下:

package com.javabean;

import java.sql.Connection;

import java.sql.DriverManager; import java.sql.ResultSet;

import java.sql.SQLException; import java.sql.Statement;

public class DBAccess { public static String drv ; public static String url ; public static String usr ; public static String pwd ; private Connection conn = null; private Statement stm = null; private ResultSet rs = null; public boolean createConn() { boolean b = false; try { Class.forName(drv).newInstance(); conn = DriverManager.getConnection(url, usr, pwd); b = true; } catch (SQLException e) { } catch (ClassNotFoundException e) { } catch (InstantiationException e) {

}

}

return b;

public boolean update(String sql) { boolean b = false; try { stm = conn.createStatement(); stm.executeUpdate(sql); b = true; } catch (Exception e) { System.out.println(e.toString()); } return b; }

public void query(String sql) { try { stm = conn.createStatement(); rs = stm.executeQuery(sql); } catch (Exception e) { } }

public boolean next() { boolean b = false; try { if(rs.next()) b = true; } catch (Exception e) { } return b; }

public String getValue(String field) { String value = ""; try { if(rs!=null)value = rs.getString(field); } catch (Exception e) { e.printStackTrace(); } if (value == null) value = ""; return value; }

public void closeConn() { try { if (conn != null) conn.close(); } catch (SQLException e) { } }

public void closeStm() { try { if (stm != null) stm.close(); } catch (SQLException e) {

}

}

public void closeRs() { try { if (rs != null) rs.close(); } catch (SQLException e) { } }

1、 检查代码书写格式是否附合要求

代码的总体结构 空行的使用 {}的使用 空格的使用 缩进的使用 2、

检查代码中类、属性、方法、变量的命名是否附合要求

类的命名 成员属性的命名 成员方法的命名 临时变量的命名 3、

检查代码中的注释是否附合要求

文件注释 类注释

成员变量的注释 成员方法的注释 重点条件语句的注释 4、 填写DBAccess类检查结果汇总表

任务3:检查Userbean类的代码

Userbean类的代码

package com.javabean;

public class UserBean { public boolean valid(String username, String password) { boolean isValid = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where

user_name='"+username+"' and user_pass='"+password+"'"; db.query(sql); if(db.next()) { isValid = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isValid; } public boolean isExist(String username) { boolean isExist = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where user_name='"+username+"'"; db.query(sql); if(db.next()) { isExist = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isExist; } public void add(String username, String password) { DBAccess db = new DBAccess(); if(db.createConn()) {

String sql = "insert into

user(user_id,user_name,user_pass,user_qx)

values(null,'"+username+"','"+password+"',2)"; db.update(sql); db.closeStm(); db.closeConn(); } } }

1、

检查代码书写格式是否附合要求

代码的总体结构 空行的使用 {}的使用 空格的使用 缩进的使用 2、

检查代码中类、属性、方法、变量的命名是否附合要求

类的命名 成员属性的命名 成员方法的命名 临时变量的命名 3、

检查代码中的注释是否附合要求

文件注释 类注释

成员变量的注释 成员方法的注释 重点条件语句的注释 4、 填写Userbean类检查结果汇总表

模块三:编写测试用例

学习目标

工作任务

1、编写DBAaccess类的单元测试的测试用例

任务1:编写DBAaccess类的单元测试的测试用例

DBAaccess类主要用于系统对数据库的底层访问,提供了连接、查询、是2、编写Userbean类的单元测试的测试用例 1、测试用例的一般格式

2、掌握用条件组合覆盖法编写测试用例 3、掌握用基本路径法编写测试用例

否为纪录尾、取得当前记录指定字段的值、更新、关闭记录、关闭命令、关闭连接等方法。

1、createConn()方法的测试用例设计 DBAaccess类的createConn()方法是完成与数据库的链接操作,主要包含try,catch语句,因此采用语句覆盖法来设计测试用例比较适合。

public boolean createConn() { boolean b = false; try { Class.forName(drv).newInstance(); conn = DriverManager.getConnection(url, usr, pwd); b = true; } catch (SQLException e) { } catch (ClassNotFoundException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { } return b;

}

测试路径:

createConn()方法的测试用例

2、 Query()和next()方法测试用例的编写

DBAaccess类的Query()和next()方法是完成与数据库的查询操作和判断是否

有记录,主要包含try,catch语句,因此采用语句覆盖法来设计测试用例比较

适合。

public void query(String sql) { try { stm = conn.createStatement(); rs = stm.executeQuery(sql); } catch (Exception e) { } catch (SQLException e) { e.printStackTrace(); } } public boolean next() { boolean b = false; try { if(rs.next()) b = true; } catch (Exception e) { e.printStackTrace(); }

}

return b;

测试路径:

Query()和next()方法的测试用例

3、 getValue()方法测试用例的编写

DBAaccess类的getValue()方法是用于从对象中取得指定字段的值,主要包

含try,catch语句和条件语句,因此采用语句覆盖法和条件覆盖法来设计测试用例比较适合。

public String getValue(String field) {

String value = ""; try { if(rs!=null)value = rs.getString(field); } catch (Exception e) { e.printStackTrace(); } if (value == null) value = ""; return value; } 测试路径:

getValue()方法的测试用例

4、 update()方法测试用例的编写

DBAaccess类的update()方法是用于通过SQL命令更新、插入和删除库中的数

据,主要包含try,catch语句,因此采用语句覆盖法来设计测试用例比较适合。 public boolean update(String sql) { boolean b = false; try {

stm = conn.createStatement(); stm.executeUpdate(sql); b = true; } catch (Exception e) { System.out.println(e.toString()); } return b; } 测试路径:

update()方法的测试用例

读一读:

任务2:编写Userbean类的单元测试的测试用例

CMMI3中推荐的测试用例的格式

Userbean类主要提供系统用户管理的相关操作,主要包括:验证明户是否

合法、查询拽定用户是否存在和添加用户的方法。

1、valid()方法测试用例的编写 Userbean类的valid()方法根据用户名和密码验证此用户是否合法,主要包

含2个if语句,因此采用条件组合覆盖法来设计测试用例比较适合。 源程序:

public boolean valid(String username, String password) { boolean isValid = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where

user_name='"+username+"' and user_pass='"+password+"'"; db.query(sql); if(db.next()) { isValid = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isValid; } 测试路径:

2、isExist()方法测试用例的编写

Userbean类的isExist()方法是在数据库中查询指定的用户名是否已存在,主要包含2个if语句,因此采用条件组合覆盖法来设计测试用例比较适合。

public boolean isExist(String username) { boolean isExist = false; DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "select * from user where user_name='"+username+"'"; db.query(sql); if(db.next()) { isExist = true; } db.closeRs(); db.closeStm(); db.closeConn(); } return isExist; } 测试路径:

isExist()的测试用例:

3、add()方法测试用例的编写

Userbean类的add()方法用于向数据库中添加指定的用户名,主要包含1个if语句,因此采用条件覆盖法来设计测试用例比较适合。

public void add(String username, String password) { DBAccess db = new DBAccess(); if(db.createConn()) { String sql = "insert into

user(user_id,user_name,user_pass,user_qx)

values(null,'"+username+"','"+password+"',2)"; db.update(sql); db.closeStm(); db.closeConn(); } } 测试路径:

add ()的测试用例:

模块4:用Junit单元测试工具测试登录模块

学习目标

工作任务

1、建立Eclipse+JAVA+MYSQL测试环境

2、根据编写的DBAaccess类测试用例,用Junit测试DBAaccess类 3、根据编写的Userbean类测试用例,用Junit测试Userbean类

任务1:建立Eclipse+JAVA+MYSQL测试环境 一、安装MYSQL5.1

1、安装MYSQL5.1(参考MYSQL的相关资料) 2、MYSQL5.1配置

MySQL提供了 “Developer Machine(开发测试类,mysql 占用很少资源)”、“Server Machine(服务器类型,mysql占用较多资源)”、“Dedicated MySQL Server Machine(专门的数据库服务器,mysql占用所有可用资源)”3种服务器类型。对于系统开发和测试一般选“Developer Machine”。

MySQL数据库的用途有:“Multifunctional Database(通用多功能型,好)”、“Transactional Database Only(服务器类型,专注于事务处理,一般)”、“Non-Transactional Database Only(非事务处理型,较简单,主要做一些监控、记数用,对MyISAM数据类型的支持仅限于non-transactional)。对于系统开发和测试一般选“Transactional Database Only(服务器类型,专注于事务处理,一般)”。

设置MsySql使用的字符集,如图2-6。对于中文环境一般选“Manual Selected 1、掌握Eclipse+JAVA+MYSQL测试环境的建立 2、掌握Junit单元测试工具的使用 2、能根据测试用例编写测试驱动程序

Default Character Set/Collation”,然后在Character Set 那里选择或填入“gbk”。

对于Windows测试环境,应该设置为“Insrall As windowsa Service”安装

为windows 服务并给这个服务命名。

设置root 用户(超级管理)的密码(默认为空),在“New root password”中填入新密码,按“Execute”使设置生效。

图2-6 MySQL设置字符集

二、首先安装JDK1.5

参考JAVA相关书籍中的JDK安装方法

三、安装Eclipse

Eclipse是java开发工具,无须安装,只需要将其解压缩到适当的目录即可。

四、加载指定的JAVA项目

启动Eclipse,在Package Explorer窗体中,单击右键(或者单击“File”菜

单项),选择“Import„„”菜单项,如图2-7:

图2-7在Eclipse中添加已存在的JAVA项目

显示“Import对话框”,展开“General”项,选取“Exisiting Projects into Workspace”项,如图2-8:

图2-8选择项目的类型

单击“Browse„„”按钮,选取JAVA工程所在的文件平,单击确定。 五、安装MYSQL的JAVA驱动包

下载MYSQL的JAVA驱动包:mysql-connector-java-5.0.8-bin.jar

启动Eclipse,在项目上单击右键,选择“Build Path”,选取“Configure Build

Path”项。显示图2-9:

图2-9 设置JAVA项目的mysql库文件

在对话框中选择Libraries“选项卡”,单击“Add External JARs„„”按钮,在显示的文件对话框中,选择 mysql-connector-java-5.0.8-bin.jar包所在文夹,选择mysql-connector-java-5.0.8-bin.jar文件包,单击“打开”按钮。

任务2:根据编写的DBAaccess类测试用例,用Junit测试DBAaccess类

在Eclipse中打开包括DBAaccess类的工程,单击工具的“新建”工具,选择

“Junit Test Case”项,在弹出的对话框中输入“DBAccessTest”类名,单击“Finish”。

在新建立的DBAccessTest.java类中输入如下的内容:

package com.javabean; import junit.framework.*;

public class DBAccessTest extends TestCase {

public void testCreateConn_1() { }

public void test_Q_1() { }

public void test_G_1() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="select * from user where user_id=1"; db.query( Sql_1 );

Assert.assertTrue(db.next());

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess();

Assert.assertTrue(db.createConn());

}

DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="select * from user where user_id=1"; db.query( Sql_1 ); db.next();

String V_1=db.getValue("user_name"); Assert.assertTrue(V_1.equals("admin"));

public void test_G_2() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="select * from user where user_id=1"; db.query( Sql_1 ); db.next();

String V_1=db.getValue("user_pass"); Assert.assertTrue(V_1.equals("admin"));

}

public void test_U_1() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="UPDATE user SET user_name='Jack' WHERE

user_id =9";

db.update( Sql_1 );

String Sql_2="select * from news where id=8"; db.query(Sql_2);

db.next();

String V_1=db.getValue("title");

Assert.assertTrue(V_1.equals("Jack"));

}

public void test_U_2() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="delete from user where user_id =8"; db.update( Sql_1 );

String Sql_2="select * from user where user_id=8"; db.query(Sql_2);

Assert.assertTrue(!db.next());

}

public void test_I_2() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; DBAccess db =new DBAccess(); db.createConn();

String Sql_1="insert into user( user_name ,user_pass )

values ('user_10','user_10')";

db.update( Sql_1 );

String Sql_2="select * from user where

user_name='user_10'"; }

}

db.query(Sql_2);

Assert.assertTrue(db.next());

执行为这个测试类:单击工具栏中的“运行”工具,选择“Run As”,选择

“Junit Test”。

测试结果如图2-10,显示测试的脚本数和正确、错误、失败的数量,在明细列表中打上钩的为测试通过,打叉的表示错误,以及测试所用的时间。

图2-10 DBAccessTest的测试报告

任务3、根据编写的Userbean类测试用例,用Junit测试Userbean类

根据任务2的操作方式,在Eclipse中建立测试类UserBeanTest,根据模块

二中建立的测试用例,编写测试驱动程序代码,部分参考代码如下: package com.javabean;

import junit.framework.Assert; import junit.framework.TestCase;

public class UserBeanTest extends TestCase {

public void testValid_1() {

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

}

Assert.assertTrue(U_1.valid("admin", "admin"));

public void testValid_2() { }

public void testValid_3() { }

public void testIsExist_1() { }

public void testIsExist_2() { }

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.isExist("user_10")); DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.isExist("admin")); DBAccess.drv="cm.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.valid("user_10", "user_10")); DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean();

Assert.assertTrue(U_1.valid("user_10", "user_10"));

}

public void testAdd_1() { }

public void testAdd_2() { }

DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean(); U_1.add("user_a","");

Assert.assertTrue(U_1.valid("user_a", "")); DBAccess.drv="com.mysql.jdbc.Driver";

DBAccess.url="jdbc:mysql://localhost:3306/student"; DBAccess.usr="root"; DBAccess.pwd="2000zht"; UserBean U_1=new UserBean(); U_1.add("Nice","Nice");

Assert.assertTrue(U_1.valid("Nice", "Nice"));

执行测试的结果如图-11。

图2-11 UserBeanTest测试结果

模块4:缺陷管理并完成测试报告

任务一:用EXCEL对测试中发现的缺陷进行管理 对于模块3中发现的缺陷,要填写如下的表格:

Bug管理表

注:

Bug编号:一般采用模块名+序号的方式编排,模块名在详细设计中确定 Bug描述:对Bub进行具体描述,包括是哪个测试用例发现的Bug

Bug严重程序:根据Bug对系统的影响程度,一般由测试主管确定严重程序 Bug优先级:解决Bug的先后顺序。

状态:如果再次测试通过了,状态为关闭,如果再次测试没通过则为打开

读一读: 软件缺陷 回归测试

任务2:根据测试的结果,完成单元测试报告

单元测试完成后,要根据测试的结果填写下面的单元测试报告: 1、项目说明

(对测试对象和测试范围进行简要说明。) 2、测试依据

(本次测试依据的相关项目文档和通用标准。) 3、人员及进度

4、测试概要 4.1测试环境

(简要介绍测试环境及其配置。 4.2测试用例

(简要介绍测试用例的设计方法。) 4.3测试方法

简要介绍测试中采用的方法(和工具)。主要是黑盒测试,测试方法可以写上测试的重点和采用的测试模式。工具为可选项,当使用到测试工具和相关工具时,要说明。 5、 覆盖分析 5.1需求覆盖

需求覆盖率是指经过测试的需求/功能和需求规格说明书中所有需求/功能的比值,通常情况下要达到100%的目标。

需求覆盖率计算:测试通过数目/需求总数 ×100% 5.2测试覆盖

测试覆盖率计算

:执行数/用例总数 ×100% 6、 缺陷统计 6.1缺陷汇总

按阶段测试统计

按缺陷严重程度 6.2缺陷分析

缺陷密度 = 缺陷总数/功能点总数 严重缺陷摘要:

6.3遗留缺陷

7、 测试结论与建议 7.1测试结论

a) 测试执行是否充分(可以增加对安全性、可靠性、可维护性和

功能性描述)

b) 对测试风险的控制措施和成效 c) 测试目标是否完成 d) 测试是否通过

e) 是否可以进入下一阶段项目目标 7.2测试建议

a) 对系统存在问题的说明,描述测试所揭露的软件缺

陷和不足,

以及可能给软件实施和运行带来的影响 b) 可能存在的潜在缺陷和后续工作 c) 对缺陷修改和产品设计的建议 d) 对过程改进方面的建议 8、 评审意见


相关内容

  • 苏教版初高中中学化学目录
  • 新人教版九年级上册 绪言 化学使世界变得更加绚丽多彩 新教材教师培训材料 第一单元 走进化学世界 课题1 物质的变化和性质 课题2 化学是一门以实验为基础的. 课题3 走进化学实验室 单元综合 第二单元 我们周围的空气 课题1 空气 课题2 氧气 课题3 制取氧气 单元综合 实验活动1 氧气的实验室 ...

  • 小学科学教材目录(苏教版)
  • 小学科学教材目录(苏教版) 三年级上册 第一单元 我们都是科学家 科学是-- 做一位小科学家 本单元综合 第二单元 我眼里的生命世界 寻找有生命的物体 植物的不同与相同 动物的不同与相同 植物.动物.人 本单元综合 第三单元 生命之源-水 生命离不开水 观察水 家乡的水资源 地球上的水 本单元综合 ...

  • 单元测试报告模板
  • 软件测试系列 密 级:普通 文件编号:NO.4 文件类别:测试管理体系文件 发 放 号:1004 应用软件 ×××单元测试报告 北京梅梅出品有限公司 目录 1. 编写目的................................................................. ...

  • .NET单元测试的艺术入门
  • 来源:Edison Chou 链接:http://www.cnblogs.com/edisonchou/p/5437205.html 开篇:最近在看Roy Osherove的<单元测试的艺术>一书,颇有收获.因此,将其记录下来,并分为四个部分分享成文,与各位Share.本篇作为入门,介绍 ...

  • 软件测试各过程的意义
  • 软件测试过程 海辉软件应用测试部门在长期的行业测试经验中,在软件测试过程模型方面总结出了如下图所示的改进W模型: 软件测试改进W模型 相对于传统V模型,W模型更科学,由一个开发的"V"和一个与之并行的测试"V"组成,体现了"尽早地和不断地进行软件测试 ...

  • 科技项目相关测试验收方案
  • 项目测试验收方案 1.1验收流程 在验收阶段,平台系统所有应用系统将按照用户和我公司都认可的<系统需求分析>,组织验收小组,进行功能和性能的验收测试.从系统的实用性.稳定性.可维护性.灵活性.可操作性.和安全性及系统文档.代码.规范及注释说明等方面组织全面验收.验收测试安排分为系统初验和 ...

  • 光缆资源集中监测及管理系统
  • (19)中华人民共和国国家知识产权局*CN102523037A* (10)申请公布号 CN 102523037 A (43)申请公布日 2012.06.27(12)发明专利申请 (21)申请号 [1**********]6.4 (22)申请日 2011.11.23 (71)申请人上海市电力公司 地址 ...

  • 软件测试自学笔记整理
  • 黑盒测试.白盒测试.单元测试.集成测试.系统测试.验收测试的区别 黑盒测试:已知产品的功能设计规格,可以进行测试证明每个实现了的功能是否符合要求. 白盒测试:已知产品的内部工作过程,可以通过测试证明每种内部操作是否符合设计规格要求,所有内部成分是否以经过检查. 软件的黑盒测试意味着测试要在软件的接口 ...

  • 软件测试知识点总结
  • 软件测试知识点总结 第一次课10.7软件测试概述 一 软件测试定义:使用人工或者自动的手段来运行或测定它是 否满足规定的需求,或弄预期结果与实际结果之间的差别. 二 软件测试的分类 1.按照开发阶段划分 a) 单元测试:模块测试,检查每个程序单元嫩否正确实现详细 设计说明中的模块功能等. b) 集成 ...

  • 软件测试规范
  • 软件测试规范 1 目的 确保软件产品质量,使产品能够顺利交付和通过验收的一项重要措施. 2 适用范围 适用于项目开发过程中的单元测试.集成测试.系统测试.业务测试.验收测试以及一些专项测试. 3 职责 项目测试负责人组织编制<测试计划>.<测试方案>,指导和督促 测试人员完成 ...