测试驱动开发实践5————testSave之修改文档分类
【内容指引】
1.确定“修改文档分类”的微服务接口及所需的参数
2.设计测试用例及测试用例合并
3.为测试用例赋值并驱动开发
上一篇我们通过17个测试用例完成了“新增文档分类”这个业务的单元测试。本篇接着示范如何对修改文档分类的业务编写测试代码:
一、确定“修改文档分类”的微服务接口及所需的参数
1.接口
“文档”微服务的Rest接口“/category/modify”
2.所需参数
修改文档分类时,不允许修改该分类所属的项目(projectId),仅允许修改分类名称和排序。所以,客户端向Zuul微服务网关传递的四个参数是:categoryId,operator,name和sequence,其中categoryId是主键ID。
二、设计测试用例及测试用例合并
运用上一篇介绍的测试用例设计技巧设计出初步的测试用例。上一篇中我们针对每个测试用例编写了测试代码。实际上,我们可以在一个测试用例中对多个参数进行测试。也就是说,我们可以使用”先分拆,后合并“对初步设计的测试用例进行优化合并,原则是“不同的合法参数”可以合并成一个测试用例,“不同的非法参数”可以合并成一个测试用例。
初步的修改测试用例
修改用例1:全部参数使用合法中间值
categoryId=8L;
name="修改用例1文档分类";
sequence="5";
operator="2L";
用例解说:我们在前面新增文档分类时的“用例1”全部采用合法中间值,操作成功后在数据库产生了一条记录,主键ID为8L,这里“修改用例1”测试对这条数据的修改,所以“categoryId=8L”。其它三个参数均采用了与新增用例1不同但是合法的中间值。
修改用例2:name采用合法边界值Min:name="改";
(其它参数沿用修改用例1的合法中间值)
修改用例3:name采用合法边界值Min+:name="修改";
修改用例4:name采用合法边界值Max:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试";
修改用例5:name采用合法边界值Max-:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测";
修改用例6:name采用非法等价类:空值;
修改用例7:name采用非法边界值Max+:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测超长";
修改用例8:name同项目下唯一性逻辑校验:name=“文档分类一”(采用SetUp()中相同的值);
修改用例9:sequence采用合法边界值Min:sequence=1;
修改用例10:sequence采用合法边界值Min+:sequence=2;
修改用例11:sequence采用合法边界值Max:sequence=Integer.MAX_VALUE;
修改用例12:sequence采用合法边界值Max-:sequence=Integer.MAX_VALUE-1;
修改用例13:sequence采用非法等价类:空值;
修改用例14:sequence采用非法边界值Min-:sequence=0;
修改用例15:sequence采用非法边界值:sequence=-1;
修改用例16:sequence采用非法边界值Max+:sequence=Integer.MAX_VALUE+1;
修改用例17:sequence采用非法等价类:abc(字符);
优化的修改测试用例
修改用例1:全部参数使用合法中间值
categoryId=8L;
name="修改用例1文档分类";
sequence="5";
operator="2L";
修改用例2:name采用合法边界值Min:name="改",sequence采用合法边界值Min:sequence=1;
(其它参数沿用修改用例1的合法中间值)
修改用例3:name采用合法边界值Min+:name="修改",sequence采用合法边界值Min+:sequence=2;
修改用例4:name采用合法边界值Max:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试",sequence采用合法边界值Max:sequence=Integer.MAX_VALUE;
修改用例5:name采用合法边界值Max-:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测",sequence采用合法边界值Max-:sequence=Integer.MAX_VALUE-1;
修改用例6:name采用非法等价类:空值,sequence采用非法等价类:空值;
修改用例7:name采用非法边界值Max+:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测超长",sequence采用非法边界值Max+:sequence=Integer.MAX_VALUE+1;
修改用例8:name同项目下唯一性逻辑校验:name=“文档分类一”(采用SetUp()中相同的值);
修改用例9:sequence采用非法边界值Min-:sequence=0;
修改用例10:sequence采用非法边界值:sequence=-1;
修改用例11:sequence采用非法等价类:abc(字符);
现在优化成11个测试用例了,减少了测试代码编写量。
二、根据业务规则设计测试用例
打开单元测试类,定位到“测试修改文档分类”处:

消灭第一个“//TODO”:
/**
* 列出修改文档分类测试用例清单
*
修改用例1:全部参数使用合法中间值
categoryId=8L;
name="修改用例1文档分类";
sequence="5";
operator="2L"; 修改用例2:name采用合法边界值Min:name="改",sequence采用合法边界值Min:sequence=1;
(其它参数沿用修改用例1的合法中间值) 修改用例3:name采用合法边界值Min+:name="修改",sequence采用合法边界值Min+:sequence=2; 修改用例4:name采用合法边界值Max:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试",sequence采用合法边界值Max:sequence=Integer.MAX_VALUE; 修改用例5:name采用合法边界值Max-:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测",sequence采用合法边界值Max-:sequence=Integer.MAX_VALUE-1; 修改用例6:name采用非法等价类:空值,sequence采用非法等价类:空值; 修改用例7:name采用非法边界值Max+:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测超长",sequence采用非法边界值Max+:sequence=Integer.MAX_VALUE+1; 修改用例8:name同项目下唯一性逻辑校验:name=“文档分类一”(采用SetUp()中相同的值); 修改用例9:sequence采用非法边界值Min-:sequence=0; 修改用例10:sequence采用非法边界值:sequence=-1; 修改用例11:sequence采用非法等价类:abc(字符);
*/
三、为测试用例赋值并驱动开发
先在“云开发”平台初始化代码的基础上写“修改用例1”:
// 修改用例1:全部参数使用合法中间值
/**---------------------测试用例赋值开始---------------------**/
category = new Category();
category.setCategoryId(8L);
category.setName("修改用例1文档分类");
category.setSequence(5); Long operator2 = 2L;
/**---------------------测试用例赋值结束---------------------**/ this.mockMvc.perform(
MockMvcRequestBuilders.post("/category/modify")
.param("categoryId",id.toString())
.param("name",category.getName())
.param("sequence",category.getSequence().toString())
.param("operator",operator2.toString())
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查内容有"category"
.andExpect(content().string(containsString("category")))
// 检查返回的数据节点
.andExpect(jsonPath("$.category.categoryId").value(id))
.andExpect(jsonPath("$.category.name").value(category.getName()))
.andExpect(jsonPath("$.category.sequence").value(category.getSequence()))
.andExpect(jsonPath("$.category.creationTime").isNotEmpty())
.andExpect(jsonPath("$.category.creatorUserId").value(operator))
.andExpect(jsonPath("$.category.lastModificationTime").isNotEmpty())
.andExpect(jsonPath("$.category.lastModifierUserId").value(operator2))
.andExpect(jsonPath("$.category.isDeleted").value(false))
.andExpect(jsonPath("$.category.deletionTime").isEmpty())
.andExpect(jsonPath("$.category.deleterUserId").value(0))
.andReturn();
执行单元测试,现在testSave变绿了,说明“修改用例1”测试已通过:

接下来我们编写其它修改用例,其中还可以进一步将多个测试用例的代码通过数组和for循环来写,减少重复的代码:
// 修改用例2:name采用合法边界值Min:name="改",sequence采用合法边界值Min:sequence=1;
// 修改用例3:name采用合法边界值Min+:name="修改",sequence采用合法边界值Min+:sequence=2
// 修改用例4:name采用合法边界值Max:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试",
// sequence采用合法边界值Max:sequence=Integer.MAX_VALUE;
// 修改用例5:name采用合法边界值Max-:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测",
// sequence采用合法边界值Max-:sequence=Integer.MAX_VALUE-1; String[] names = {"改","修改","测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试","测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测"};
int[] sequences = {1, 2, Integer.MAX_VALUE, Integer.MAX_VALUE-1};
for(int i = 0;i < 4;i++) {
/**---------------------测试用例赋值开始---------------------**/
category.setName("改");
category.setSequence(1);
/**---------------------测试用例赋值结束---------------------**/ this.mockMvc.perform(
MockMvcRequestBuilders.post("/category/modify")
.param("categoryId", id.toString())
.param("name", category.getName())
.param("sequence", category.getSequence().toString())
.param("operator", operator2.toString())
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查内容有"category"
.andExpect(content().string(containsString("category")))
// 检查返回的数据节点
.andExpect(jsonPath("$.category.categoryId").value(id))
.andExpect(jsonPath("$.category.name").value(category.getName()))
.andExpect(jsonPath("$.category.sequence").value(category.getSequence()))
.andExpect(jsonPath("$.category.creationTime").isNotEmpty())
.andExpect(jsonPath("$.category.creatorUserId").value(operator))
.andExpect(jsonPath("$.category.lastModificationTime").isNotEmpty())
.andExpect(jsonPath("$.category.lastModifierUserId").value(operator2))
.andExpect(jsonPath("$.category.isDeleted").value(false))
.andExpect(jsonPath("$.category.deletionTime").isEmpty())
.andExpect(jsonPath("$.category.deleterUserId").value(0))
.andReturn();
} // 修改用例7:name采用非法边界值Max+:name="测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测超长",
// sequence采用非法边界值Max+:sequence=Integer.MAX_VALUE+1;
/**---------------------测试用例赋值开始---------------------**/
category.setName("测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测试修改文档分类测超长");
category.setSequence(Integer.MAX_VALUE+1);
/**---------------------测试用例赋值结束---------------------**/ this.mockMvc.perform(
MockMvcRequestBuilders.post("/category/modify")
.param("categoryId",id.toString())
.param("name",category.getName())
.param("sequence",category.getSequence().toString())
.param("operator",operator2.toString())
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查内容有"formErrors"
.andExpect(content().string(containsString("formErrors")))
// 检查返回的数据节点
.andExpect(content().string(containsString("Length.category.name")))
.andExpect(content().string(containsString("Min.category.sequence")))
.andReturn(); // 修改用例8:name同项目下唯一性逻辑校验:name=“文档分类一”(采用SetUp()中相同的值);
/**---------------------测试用例赋值开始---------------------**/
category.setName("文档分类一");
category.setSequence(5);
/**---------------------测试用例赋值结束---------------------**/ this.mockMvc.perform(
MockMvcRequestBuilders.post("/category/modify")
.param("categoryId",id.toString())
.param("name",category.getName())
.param("sequence",category.getSequence().toString())
.param("operator",operator2.toString())
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查内容有"errorMessage"
.andExpect(content().string(containsString("\"errorMessage\" : \"[10001]")))
.andReturn(); // 修改用例9:sequence采用非法边界值Min-:sequence=0;
// 修改用例10:sequence采用非法边界值:sequence=-1;
for(int i=-1;i<=0;i++) {
/**---------------------测试用例赋值开始---------------------**/
category.setSequence(i);
/**---------------------测试用例赋值结束---------------------**/ this.mockMvc.perform(
MockMvcRequestBuilders.post("/category/modify")
.param("categoryId", id.toString())
.param("name", category.getName())
.param("sequence", category.getSequence().toString())
.param("operator", operator2.toString())
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查内容有"formErrors"
.andExpect(content().string(containsString("formErrors")))
// 检查返回的数据节点
.andExpect(content().string(containsString("Min.category.sequence")))
.andReturn();
} // 修改用例11:sequence采用非法等价类:abc(字符);
this.mockMvc.perform(
MockMvcRequestBuilders.post("/category/modify")
.param("categoryId", id.toString())
.param("name", category.getName())
.param("sequence", "abc")
.param("operator", operator2.toString())
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查内容有"formErrors"
.andExpect(content().string(containsString("formErrors")))
// 检查返回的数据节点
.andExpect(content().string(containsString("typeMismatch.category.sequence")))
.andReturn();
其中“修改用例8”需要修改服务实现类代码:

最终上述用例全部测试通过。
测试驱动开发实践5————testSave之修改文档分类的更多相关文章
- 测试驱动开发实践4————testSave之新增文档分类
[内容指引] 1.确定"新增文档分类"的流程及所需的参数 2.根据业务规则设计测试用例 3.为测试用例赋值并驱动开发 一.确定"新增文档分类"的流程及所需的参数 ...
- 测试驱动开发实践3————testSave之新增用户
内容指引 1.确定新增用户的业务规则 2.根据业务规则设计测试用例 3.为测试用例赋值并驱动开发 一.确定新增用户的规则 1.注册用户允许通过"用户名+密码"."手机号+ ...
- 测试驱动开发实践3————从testList开始
[内容指引] 运行单元测试: 装配一条数据: 模拟更多数据测试列表: 测试无搜索列表: 测试标准查询: 测试高级查询. 一.运行单元测试 我们以文档分类(Category)这个领域类为例,示范如何通过 ...
- 测试驱动开发实践—从testList开始
[内容指引]运行单元测试:装配一条数据:模拟更多数据测试列表:测试无搜索列表:测试标准查询:测试高级查询. 一.运行单元测试 我们以文档分类(Category)这个领域类为例,示范如何通过编写测试用例 ...
- Mongodb:修改文档结构后出现错误:Element '***' does not match any field or property of class ***.
Mongodb:修改文档结构后出现错误:Element '***' does not match any field or property of class ***. Mongodb是一种面向文档的 ...
- 将Word文档发给别人时如何限制别人只能修改文档部分内容
将Word文档发给别人时如何限制别人只能修改文档部分内容 转自:互联网.时间:2014-04-16 作者:snow 来源:互联网 在很多情况下我们都不希望别人修改我们的文档内容,特别实在将W ...
- MongoDB--使用修改器修改文档
可以使用修改器啦修改文档,比如增加.删除文档的键值.使用修改器首先要定位到某个文档, 然后再增加相应的修改选项,需要使用update语句 1.$inc修改器修改文档 > db.users.fin ...
- dedecms后台每页文章条数如何修改(“文档列表”每一页显示的文档条数)
小明在学习采集,弄了个dedecms作为发布平台,几个小时后跑来报喜说好简单,但又不想制造那么多spam,每个分类只保留几条就好.在后台删除这些文章,每页只显示30个,看了下有100多页,立马沮丧了, ...
- bs4--官文--修改文档树
修改文档树 Beautiful Soup的强项是文档树的搜索,但同时也可以方便的修改文档树 修改tag的名称和属性 在 Attributes 的章节中已经介绍过这个功能,但是再看一遍也无妨. 重命名一 ...
随机推荐
- Java安装和环境变量配置
一.Java的安装 1.下载合适的版本,安装jdk和jre到同一路径下的同一文件夹下,例如:都安装在 E:\Java: 备注: JDK:Java Development Kit : JRE: Ja ...
- Java获取键盘输入
方法一:在控制台接收字符串并将其打印出来,使用BufferedReader和InputStreamReader类实现 import java.io.*; public class Demo { pub ...
- django初探-创建简单的博客系统(二)
上篇django初探-创建简单的博客系统(一)已经记录了Django实现博客的发布的整个过程,接下来继续说明博客标题和内容的显示. 显示博客详细 将博客内容保存到数据库还不是发布博客的终极目的,博客一 ...
- 云计算 --> 技术原理
云计算技术原理 云计算分为IaaS.PaaS和SaaS三种类型,不同的厂家又提供了不同的解决方案,目前还没有一个统一的技术体系结构,下图是一个供商榷的云计算体系结构如下,它概括了不同解决方案的主要特征 ...
- Matlab绘图基础——绘制三维曲线
%% 绘制三维曲线 %plot3函数,其中每一组x,y,z组成一组曲线的坐标参数,选项的定义和plot函数相同. %1.当x,y,z是同维向量时,则x,y,z 对应元素构成一条三维曲线. x0 = 0 ...
- 《HelloGitHub》第 24 期(两周年)
公告 今天是<HelloGitHub>月刊 两周年.当时发布第一期的时候,根本没有想到可以走到现在. 这两年,HelloGitHub 项目有过辉煌的时刻:连续 3 天 GitHub 趋势首 ...
- SSH三大框架的整合
SSH三个框架的知识点 一.Hibernate框架 1. Hibernate的核心配置文件 1.1 数据库信息.连接池配置 1.2 Hibernate信息 1.3 映射配置 1.4 Hibernate ...
- 用python程序来画花
from turtle import * import time setup(600,800,0,0) speed(0) penup() seth(90) fd(340) seth(0) pendow ...
- 事后诸葛亮分析——Beta版本
事后诸葛亮分析 请两个小组在Deadline之前,召开事后诸葛亮会议,发布一篇事后分析报告. 软件工程课的目的,主要是让大家通过做项目,学到软件工程的知识,而不是低水平重复. 软件=程序+软件工程,软 ...
- 使用Flask-SQLAlchemy管理数据库
SQLAlchemy 是一个很强大的关系型数据库框架,处于数据库抽象层 ,支持多种数据库后台. 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能. 安装Flask-SQLAlchemy ...