计算某天的下一天:黑盒测试之等价类划分+JUnit参数化测试
题目要求
测试以下程序:该程序有三个输入变量month、day、year(month、day和year均为整数值,并且满足:1≤month≤12、1≤day≤31和1900≤year≤2050),分别作为输入日期的月份、日、年份,通过程序可以输出该输入日期在日历上隔一天的日期。例如,输入为2004年11月30日,则该程序的输出为2004年12月1日。
- 划分等价类,按照等价类划分法设计测试用例;
- 编写getNextDate函数;
- 掌握Junit4的用法,使用Junit4测试getNextDate函数。
等价类表
假设输入格式为year,month,day,且三个输入变量year、month和day均被输入。
year要区分闰年和平年,其中闰年还可以分为世纪闰年和普通闰年,且year要属于[1900,2050]。
month要根据该月有几天来进行区分,并且需要考虑是否向year进位,且month要属于[1,12]。
day要根据月份来判断天数是否合法,并且需要考虑是否向month进位,且day要属于[1,31]。
等价类划分如下。
测试用例
有效等价类测试用例
共有5个有效等价类测试用例。
测试数据 | 期望结果 | 覆盖范围 |
---|---|---|
2004/12/25 | 2004/12/26 | 2,10,14 |
2001/2/28 | 2001/3/1 | 3,7,15 |
2000/2/29 | 2000/3/1 | 1,7,16 |
2001/4/30 | 2001/5/1 | 3,8,17 |
2001/5/31 | 2001/6/1 | 3,9,18 |
无效等价类测试用例
共有12个有效等价类测试用例。
测试数据 | 期望结果 | 覆盖范围 |
---|---|---|
1899/6/1 | year非法 | 4 |
2051/6/1 | year非法 | 5 |
a/6/1 | year非法 | 6 |
1999/0/1 | month非法 | 11 |
1999/13/1 | month非法 | 12 |
1999/a/1 | month非法 | 13 |
1999/1/0 | day非法 | 19 |
1999/1/32 | day非法 | 20 |
1999/1/a | day非法 | 21 |
2001/2/29 | day非法 | 22 |
2000/2/30 | day非法 | 23 |
2001/4/31 | day非法 | 24 |
源代码
项目结构如下图所示
DateUtil.java
package com.company;
public class DateUtil {
// 有31天的月份
private static int[] monthOfThirtyOne = new int[]{1,3,5,7,8,10,12};
// 有30天的月份
private static int[] monthOfThirty = new int[]{4,6,9,11};
// 年月日
private int year;
private int month;
private int day;
// 最终实现的功能,输入是一个“年/月/日”格式的字符串;
// 如果函数运行成功,输出则是相同格式的下一天,否则是错误信息
public String getNextDate(String dateStr){
String updateResult = this.updateDate(dateStr);
// 如果输入合法
if (updateResult.equals("success")){
String checkResult = this.checkDate();
// 如果输入合法
if (checkResult.equals("valid")){
// 计算明天的日期
return this.calcNextDate();
}
return checkResult;
}
return updateResult;
}
// 根据输入字符串转换并更新年月日
private String updateDate(String dateStr){
// 获取年月日
String[] numbers = dateStr.split("/");
try{
this.year = Integer.parseInt(numbers[0]);
}catch (NumberFormatException e){
return "year非法";
}
try{
this.month = Integer.parseInt(numbers[1]);
}catch (NumberFormatException e){
return "month非法";
}
try{
this.day = Integer.parseInt(numbers[2]);
}catch (NumberFormatException e){
return "day非法";
}
return "success";
}
// 检查日期是否合法
private String checkDate(){
String valid = "valid";
String yearInvalid = "year非法";
String monthInvalid = "month非法";
String dayInvalid = "day非法";
// year合法
if (year>=1900&&year<=2050){
// month合法
if (month>=1&&month<=12){
// day小于1
if (day<=0){
return dayInvalid;
}
// 至此能保证day大于0
// 是2月
if (month==2){
// 闰年
if (yearIsLeap(year)){
// 1-29
if (day<=29){
return valid;
}else{
return dayInvalid;
}
}
// 平年2月
else{
// 1-28
if (day<=28){
return valid;
}else{
return dayInvalid;
}
}
}
// 至此能保证不是2月
// 是否为31天的月
for(int i=0;i<7;++i){
if (month==monthOfThirtyOne[i]){
// 1-31
if (day<=31){
return valid;
}else{
return dayInvalid;
}
}
}
// 至此能保证不是2月和31天的月
// 是否为30天的月
for(int i=0;i<4;++i){
if (month==monthOfThirty[i]){
// 1-30
if (day<=30){
return valid;
}else{
return dayInvalid;
}
}
}
}
// month非法
else{
return monthInvalid;
}
}
// year非法
return yearInvalid;
}
// 计算下一天
private String calcNextDate(){
int yearNext;
int monthNext;
int dayNext=day+1;
int dayCarry=0;
int monthCarry=0;
// 处理day
// 是2月
if (month==2){
// 闰年
if (yearIsLeap(year)){
// 1-29
if (day==29){
dayNext = 1;
dayCarry = 1;
}
}
// 平年2月
else{
// 1-28
if (day==28){
dayNext = 1;
dayCarry = 1;
}
}
}
// 不是2月
else{
boolean isThirtyOne= false;
// 是否为31天的月
for(int i=0;i<7;++i){
if (month==monthOfThirtyOne[i]){
isThirtyOne = true;
// 1-31
if (day==31){
dayNext = 1;
dayCarry = 1;
}
break;
}
}
// 至此能保证是30天的月
if (!isThirtyOne){
// 1-30
if (day==30){
dayNext = 1;
dayCarry = 1;
}
}
}
// 处理月
if (month+dayCarry>12){
monthNext = 1;
monthCarry = 1;
}else{
monthNext = month+dayCarry;
}
// 处理年
yearNext = year+monthCarry;
return yearNext +"/"+ monthNext +"/"+ dayNext;
}
// 判断某一年是否为闰年
private boolean yearIsLeap(int year){
// 普通闰年和世纪闰年
if ((year%4==0&&year%100!=0)||(year%400==0)){
return true;
}
// 平年
return false;
}
}
DateUtilTest.java
package com.test;
import com.company.DateUtil;
import static org.junit.Assert.*;
import org.junit.Test;
//1、参数化测试:引入相关的包和类
import java.util.Collection;
import java.util.Arrays;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class) //2、参数化测试:更改测试运行器为RunWith(Parameterized.class)
public class DateUtilTest {
//3、参数化测试:声明变量用来存放预期值与结果值
private DateUtil util = new DateUtil();
private String date;
private String except;
//4、参数化测试:声明一个返回值为 Collection 的公共静态方法,并使用@Parameters 进行修饰
@Parameters
public static Collection data(){
return Arrays.asList(new Object[][]{
{"2004/12/25", "2004/12/26"},
{"2001/2/28", "2001/3/1"},
{"2000/2/29", "2000/3/1"},
{"2001/4/30", "2001/5/1"},
{"2001/5/31", "2001/6/1"},
{"1899/6/1", "year非法"},
{"2051/6/1", "year非法"},
{"a/6/1", "year非法"},
{"1999/0/1", "month非法"},
{"1999/13/1", "month非法"},
{"1999/a/1", "month非法"},
{"1999/1/0", "day非法"},
{"1999/1/32", "day非法"},
{"1999/1/a", "day非法"},
{"2001/2/29", "day非法"},
{"2000/2/30", "day非法"},
{"2001/4/31", "day非法"},
});
}
//5、参数化测试:为测试类声明一个带有参数的公共构造方法,并在其中为声明变量赋值
public DateUtilTest(String date, String except){
this.date = date;
this.except = except;
}
@Test
public void testGetNextDate(){
assertEquals(except, util.getNextDate(date));
}
}
测试结果
如下图所示,17个测试用例均测试成功,程序实际输出与期望值相同。
实验总结
本次实验的主要目的是巩固黑盒测试方法中的等价类划分法的知识,练习JUnit的参数化测试。在本次实验中,我认为我的getNextDate函数的实现并不是很优雅,比较过程化。写这个函数花了我很多时间,主要问题在于我没有抓住一些关键的、抽象的逻辑和子函数,比如天向月份进位和月份向年份完全可以参照加法器的循环、可以写一个函数根据年份和月份判断出天数的最大值等等。
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!
计算某天的下一天:黑盒测试之等价类划分+JUnit参数化测试的更多相关文章
- 黑盒测试用例设计方法&理论结合实际 -> 等价类划分
一. 概念 等价类划分法是把程序的输入域划分成若干部分(子集),然后从每个部分中选取少数代表性数据作为测试用例.每一类的代表性数据在测试中的作用等价于这一类中的其他值. 二. 等价类划分的应用 等价类 ...
- ios小数向上、下取整,计算结果向上、下取整
[摘要:小数背上与整,指小数局部间接进1 x=3.14, ceilf (x)=4 小数背下与整,指间接往失落小数局部 x=3.14,floor(x)=3 盘算效果背上与整 A被除数,B除数 ,(AB- ...
- 计算纯文本情况下RichTextBox实际高度的正确方法(.NET)
2016-07-17重大更新 其实有更好.更系统的方法,也是最近才发现的,分享给大家!! /// <summary> /// /// </summary> ...
- 大数据入门第五天——离线计算之hadoop(下)hadoop-shell与HDFS的JavaAPI入门
一.Hadoop Shell命令 既然有官方文档,那当然先找到官方文档的参考:http://hadoop.apache.org/docs/current/hadoop-project-dist/had ...
- Linux 计算某文件夹下的所有文件的md5值
使用find 命令 find /root -type f -print0 |xargs -0 md5sum >a.md5 校验的话 md5sum -c a.md5
- js计算指定日期的下一年的日期
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Ubuntu下caffe:用自己的图片训练并测试AlexNet模型
参考博客:https://blog.csdn.net/eereere/article/details/79118645#commentBox 目录 1.准备图片 2. 将 图片路径写入txt 参考 这 ...
- 大数据时代下的SQL Server第三方负载均衡方案----Moebius测试
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius( ...
- (转)大数据时代下的SQL Server第三方负载均衡方案----Moebius测试
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius( ...
随机推荐
- 深入调研Linq to Objects Join Linq to Entity
最近工作中遇到数据库组合查询带来的一些问题,因此有必要调研一下Linq to Objects Join Linq to Entity.参考一些网友的代码案例,深入实践了一下使用EntityFramew ...
- Conda安装包错误-CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://conda.anaconda.org/r/win-64/repodata.json> Elapsed:
可能是防火墙问题:conda config --set ssl_verify false 安装 openssl . 换源: cmd输入conda config --add channels r 进入C ...
- [vijos1725&bzoj2875]随机数生成器<矩阵乘法&快速幂&快速乘>
题目链接:https://vijos.org/p/1725 http://www.lydsy.com/JudgeOnline/problem.php?id=2875 这题是前几年的noi的题,时间比较 ...
- 如何理解EventLoop--浏览器篇
前言 最近在准备春招,刷到了JS中的主要运行机制--Event Loop,觉得它的实现思路有必要整理一下,以防忘记.关于它在浏览器上的实现,我结合了自己的理解以及示例代码,想用最通俗的语言表达出来.如 ...
- B 基因改造
时间限制 : - MS 空间限制 : - KB 问题描述 "人类智慧的冰峰,只有萌萌哒的我寂寞地守望."--TBTB正走在改造人类智慧基因的路上.TB发现人类智慧基因一点也不 ...
- Docker的MySQL镜像, 实行数据,配置信息,日志持久化
Docker的MySQL8镜像, 实行数据持久化 使用Docker的MySQL8.0.17实例化一个容器之后需要对其进行数据持久化操作, 使用 docker docker run -p 7797:33 ...
- Three.js 中的参数调试控制插件dat.GUI.JS - [Three.js] - [dat.GUI]
不论是处于特殊功能的需要,还是处于效果调试方便,我们可能都需要修改模型中的参数值.在Three.js中,谷歌提供了一个js库,即dat.GUI.js用于处理这种需求. 通过该库,我们就不需要通过手动修 ...
- IIS 组成
HTTP.sys http.sys 侦听来自网络的 HTTP 请求,将它们传递到 IIS 并返回响应. 它是一种可以从命令行停止和启动的服务. "NET STOP HTT ...
- HDU1074:Doing Homework(状压DP)
Doing Homework Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- Golang笔记集
学习Golang了, 下面分享我的, 还有我收集的Golang的学习资料 我的基础笔记地址: https://github.com/zhuchangwu/go-study-notes 其他参考: Go ...