使用JUnitParams进行参数化的JUnit测试

参数化的单元测试用于在不同条件下测试相同的代码。 借助参数化的单元测试,我们可以建立一种测试方法,该方法从某些数据源中检索数据。 该数据源可以是测试数据对象,外部文件甚至数据库的集合。 一般的想法是使使用相同的单元测试方法测试不同的条件变得容易,这将限制我们需要编写的源代码并使测试代码更健壮。 我们可以将这些测试称为数据驱动的单元测试。 junit-logo

在JUnit中实现数据驱动的单元测试的最佳方法是使用JUnit的自定义运行器- Parameterized或JUnitParams的 JUnitParamsRunner 。 使用JUnit的方法可能在许多情况下都可行,但是后者似乎更易于使用且功能更强大。

基本例子

在我们的示例中,一个扑克骰子,我们需要计算满屋的得分。 就像纸牌扑克一样,“满座”是一副掷骰子,您同时拥有3个和一对。 为了简单起见,分数是一卷中所有骰子的总和。 因此,让我们看一下代码:

class FullHouse implements Scoreable {@Overridepublic Score getScore(Collection dice) {Score pairScore = Scorables.pair().getScore(dice);Score threeOfAKindScore = Scorables.threeOfAKind().getScore(pairScore.getReminder());if (bothAreGreaterThanZero(pairScore.getValue(), threeOfAKindScore.getValue())) {return new Score(pairScore.getValue() + threeOfAKindScore.getValue()); // no reminder}return new Score(0, dice);}private boolean bothAreGreaterThanZero(int value1, int value2) {return value1 > 0 && value2 > 0;}
}

我想确保该掷骰正确得分(当然我已经对Pair和ThreeOfAKind进行了单元测试)。 因此,我想测试以下条件:

  • 分数是11:1、1、3、3、3
  • 2、2、2、1、1的得分是8
  • 分数是0代表:2、3、4、1、1
  • 分数是25,表示:5、5、5、5、5

让我们研究为该方法编写数据驱动的测试的两种可能方法。 首先, JUnit的参数化

@RunWith(Parameterized.class)
public class FullHouseTest {private Collection rolled;private int score;public FullHouseTest(Collection rolled, int score) {this.rolled = rolled;this.score = score;}@Testpublic void fullHouse() {assertThat(new FullHouse().getScore(rolled).getValue()).isEqualTo(score);}@Parameterized.Parameterspublic static Iterable data() {return Arrays.asList(new Object[][]{{roll(1, 1, 3, 3, 3), score(11)},{roll(2, 2, 2, 1, 1), score(8)},{roll(2, 3, 4, 1, 1), score(0)},{roll(5, 5, 5, 5, 5), score(25)}});}private static int score(int score) {return score;}
}

另一个是JUnitParams

@RunWith(JUnitParamsRunner.class)
public class FullHouseTest {@Test@Parameterspublic void fullHouse(Collection rolled, int score) {assertThat(new FullHouse().getScore(rolled).getValue()).isEqualTo(score);}public Object[] parametersForFullHouse() {return $($(roll(1, 1, 3, 3, 3), score(11)),$(roll(2, 2, 2, 1, 1), score(8)),$(roll(2, 3, 4, 1, 1), score(0)),$(roll(5, 5, 5, 5, 5), score(25)));}private static int score(int score) {return score;}
}

乍一看,两者看起来非常相似。 没错 那么JUnit Parameterized (1)和JUnitParams(2)之间有什么区别? 最重要的一种是传递参数的方法,因此实际上是解决方案的体系结构。 在(1)中,参数在构造函数中传递,而在(2)中,参数直接传递到测试方法。 我应该在乎吗? 是。 原因之一是,在(2)中,我们可以有多个参数化测试方法,每种方法的数据都不同,如以下示例所示:

@RunWith(JUnitParamsRunner.class)
public class NumberOfAKindTest {@Test@Parameterspublic void pair(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(2);doTest(rolled, expected, score, sut);}@Test@Parameterspublic void threeOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(3);doTest(rolled, expected, score, sut);}public Object[] parametersForPair() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1), score(2)),$(roll(2, 1, 1, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 4, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 5, 5, 5), hand(5, 5), score(10)),$(roll(2, 1, 5, 4, 3), null, score(0)));}public Object[] parametersForThreeOfAKind() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1, 1), score(3)),$(roll(2, 1, 1, 1, 3), hand(1, 1, 1), score(3)),$(roll(2, 3, 1, 1, 1), hand(1, 1, 1), score(3)),$(roll(2, 3, 5, 5, 5), hand(5, 5, 5), score(15)),$(roll(2, 5, 5, 5, 6), hand(5, 5, 5), score(15)),$(roll(2, 2, 5, 5, 3), null, score(0)));}private static int[] hand(int... dice) {return dice;}private static int score(int score) {return score;}}

在更简单的示例中,可以通过值方法直接在@Parameters批注中将参数定义为String数组。 我们还可以将数据提取到一个外部类中,并使我们的测试更加清晰易读。 NumberOfAKind的完整测试如下:

@RunWith(JUnitParamsRunner.class)
public class NumberOfAKindTest {@Test@Parameters(source = NumberOfAKindProvider.class, method = "providePair")public void pair(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(2);doTest(rolled, expected, score, sut);}@Test@Parameters(source = NumberOfAKindProvider.class, method = "provideThreeOfAKind")public void threeOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(3);doTest(rolled, expected, score, sut);}@Test@Parameters(source = NumberOfAKindProvider.class, method = "provideFourOfAKind")public void fourOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(4);doTest(rolled, expected, score, sut);}@Test@Parameters(source = NumberOfAKindProvider.class, method = "provideFiveOfAKind")public void fiveOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(5);doTest(rolled, expected, score, sut);}private void doTest(Collection rolled, int[] expected, int score, NumberOfAKind sut) {Collection consecutiveDice = sut.getConsecutiveDice(rolled);assertDiceContainsValues(consecutiveDice, expected);assertThat(sut.getScore(rolled).getValue()).isEqualTo(score);}private void assertDiceContainsValues(Collection dice, int[] expected) {Collection values = toInts(dice);if (expected == null) {assertThat(values).isEmpty();return;}for (int i = 0; i < expected.length; i++) {assertThat(values).hasSize(expected.length).contains(expected[i]);}}private Collection toInts(Collection dice) {return Collections2.transform(dice, new Function() {@Overridepublic Integer apply(Dice input) {return input.getValue();}});}}

每个方法都指定提供程序类和提供程序的方法名称。 查看以下提供者:

public class NumberOfAKindProvider {public static Object[] providePair() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1), score(2)),$(roll(2, 1, 1, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 4, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 5, 5, 5), hand(5, 5), score(10)),$(roll(2, 1, 5, 4, 3), null, score(0)));}public static Object[] provideThreeOfAKind() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1, 1), score(3)),$(roll(2, 1, 1, 1, 3), hand(1, 1, 1), score(3)),$(roll(2, 3, 1, 1, 1), hand(1, 1, 1), score(3)),$(roll(2, 3, 5, 5, 5), hand(5, 5, 5), score(15)),$(roll(2, 5, 5, 5, 6), hand(5, 5, 5), score(15)),$(roll(2, 2, 5, 5, 3), null, score(0)));}public static Object[] provideFourOfAKind() {return $($(roll(1, 1, 1, 1, 3), hand(1, 1, 1, 1), score(4)),$(roll(2, 1, 1, 1, 1), hand(1, 1, 1, 1), score(4)),$(roll(2, 5, 5, 5, 5), hand(5, 5, 5, 5), score(20)),$(roll(2, 3, 4, 5, 5), null, score(0)));}public static Object[] provideFiveOfAKind() {return $($(roll(1, 1, 1, 1, 1), hand(1, 1, 1, 1, 1), score(5)),$(roll(6, 6, 6, 6, 6), hand(6, 6, 6, 6, 6), score(30)),$(roll(6, 6, 6, 6), null, score(0)),$(roll(2, 3, 4, 6, 6), null, score(0)));}private static int[] hand(int... dice) {return dice;}private static int score(int score) {return score;}
}

摘要

对我来说, JUnitParams是编写良好的数据驱动的单元测试的更好的解决方案。 但是上面介绍的并不是库必须提供给开发人员的所有内容。 还有更多功能。 参数可以作为CSV字符串传递,我们可以混合参数化测试和非参数化测试,仅举几例。

请访问该项目的网站以了解有关此库的更多信息: https : //code.google.com/p/junitparams

参考:来自Codeleak.pl博客的JCG合作伙伴 Rafal Borowiec的JUnitParams 参数化JUnit测试 。

翻译自: https://www.javacodegeeks.com/2013/12/parameterized-junit-tests-with-junitparams.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js webpack 解决跨域问题_webpack-dev-server 作代理解决跨域,让你的本地开发飞起来...

最近在接到一个需求是做一个可视化的监控系统&#xff0c;mock数据来开发的话实在不太方便&#xff0c;况且数据量之大。查了一下资料&#xff0c;可以用webpack-dev-server作为代理&#xff0c;直接请求线上&#xff0c;哈哈哈&#xff0c;是不是很方便。### 目前我用的是webp…

代码片段 欢迎补充 一起共享

python&#xff1a; https://github.com/Lj-github/pythonTool转载于:https://www.cnblogs.com/liujiang04/p/9787486.html

实现用户操作指引功能

主要是通过定位找到需要指引的目标元素&#xff0c;然后再在蒙版上画一个div&#xff0c;设置为白色&#xff0c;定位到目标元素位置。思路大概就是这样。 图一&#xff1a; ![](https://img2018.cnblogs.com/blog/1354858/201811/1354858-20181105141942044-1763163359.png) 图…

扩展Guava缓存溢出到磁盘

缓存使您可以轻松地显着加速应用程序。 Java平台的两种出色的缓存实现是Guava缓存和Ehcache 。 尽管Ehcache功能丰富得多&#xff08;例如其Searchable API &#xff0c;将缓存持久化到磁盘或溢出到大内存的可能性&#xff09;&#xff0c;但与Guava相比&#xff0c;它也带来了…

磁盘

我们现在计算机的瓶颈在磁盘上 CPU运算速率已达到5.0GHz 1GHz10亿次每秒&#xff08;计算速度&#xff09; 硬盘 MB 软盘——>碟片&#xff08;100MB&#xff09;——>芯片ssd&#xff08;500MB~2000MB&#xff09; 存储程序的方式&#xff1a; 磁盘与内存想比较 能够用…

java gson fromjson,Gson的fromJson()方法

Gson提供了fromJson()方法来实现从Json相关对象到java实体的方法。在日常应用中&#xff0c;我们一般都会碰到两种情况&#xff0c;转成单一实体对象和转换成对象列表或者其他结构。先来看第一种&#xff1a;比如json字符串为&#xff1a;[{“name”:”name0”,”age”:0}]Pers…

python文件的读取与写入_python中文件的读取与写入以及os模块

1.文件读取的三部曲&#xff1a;打开 ---> 操作 ----> 关闭r(默认参数)&#xff1a;-只能读&#xff0c;不能写-读取文件不存在 会报错FileNotFoundError: [Errno 2] No such file or directory: /tmp/westosw(д)-write only-文件不存在的时候&#xff0c;会自动创建新的…

vue2.0 element-ui中的el-select选择器无法显示选中的内容

我使用的是element-ui V2.2.3。代码如下&#xff0c;当我选择值得时候&#xff0c;el-select选择器无法显示选中的内容&#xff0c;但是能触发change方法&#xff0c;并且能输出选择的值。 select.vue文件 <template><div><div class"row" v-for&quo…

Gradle接口:Gradle构建元数据

正如我之前在“ 识别Gradle约定 ”和“ 从Ant Build演变Gradle构建&#xff1a;导入Ant构建文件 ”之类的文章中所显示的那样&#xff0c;可以通过Groovy访问Gradle的API来收集有关Gradle构建的重要信息。 在本文中&#xff0c;我演示了如何通过Gradle接口访问基本的Gradle构建…

字符串(string)的常用语法和常用函数

在python中&#xff0c;加了引号&#xff08;单引号、双引号、三引号&#xff09;的字符就是字符串类型&#xff0c;python并没有字符类型。 字符串也是很常用的数据类型&#xff0c;这里介绍一些用的较多的语法和方法&#xff0c;直接以代码示例展示。 1 str helloworld2 str…

os 模块 和 os模块下的path模块

import os # os 主要用于与操作系统进行交互 #获取当前的工作目录 print&#xff08;os.getcwd&#xff08;&#xff09;&#xff09; #切换工作目录 os .chdir("D:\上海python全栈4期\day20\pack") #print(os.getcwd()) #当前目录 是一个点 #print&#xff08;os.cu…

php 工资 2018,佛山市2018年平均工资(社平工资)

2018年佛山市城镇非私营单位就业人员年平均工资为79824元(折合月平均工资6652)。2018年佛山市在岗职工年平均工资为80288元(折合月平均工资6691&#xff0c;四舍五入)。2018年佛山市城镇私营单位就业人员年平均工资为57297元(折合月平均工资4775)。广东地区2019年7月1日起市平均…

oj运行时错误如何查找原因_VLOOKUP又失灵?避免这四种错误类型

说起函数&#xff0c;你第一个想到什么&#xff1f;那绝对是表界曝光率最高的函数——VLOOKUP 了&#xff01;什么&#xff0c;你还不知道 VLOOKUP&#xff1f;那今天这篇文章&#xff0c;你可千万不能错过&#xff01;&#xff01;根据编号匹配姓名&#xff1b;根据评分匹配等…

Table Dragger - 简单的 JS 拖放排序表格插件

Table Dragger 是一个极简的实现拖放排序的表格插件&#xff0c;纯 JavaScript 库&#xff0c;不依赖 jQuery。用于构建操作方便的拖放排序功能&#xff0c;超级容易设置&#xff0c;有平滑的动画&#xff0c;支持触摸事件。 在线演示 免费下载 您可能感兴趣的相关文章网…

使用正则表达式在Java中悬挂缩进段落

这篇文章显示了如何使用正则表达式将缩进的长段落挂起。 该方法将考虑单词边界&#xff0c;这意味着它将不会破坏缩进单词。 为了说明此问题&#xff0c;请考虑以下示例&#xff1a; 近年来&#xff0c;人们越来越努力从自然语言文本中提取实体之间的关系。 在这篇论文中&…

在linux上cuda9.0 cudnn7.* 安装python3.6 tensorflow 1.5.1

链接&#xff1a;https://www.jianshu.com/p/bcf37d0e4e9b 为了入门机器学习的小伙伴能安装好工具&#xff0c;特制作此教程 按照 Anaconda 下载网站上的说明下载并安装 Anaconda。 调用以下命令创建名为 tensorflow 的 conda 环境&#xff1a; conda create -n tensorflow pi…

[Swift]遍历集合类型(数组、集合和字典)

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号&#xff1a;山青咏芝&#xff08;shanqingyongzhi&#xff09;➤博客园地址&#xff1a;山青咏芝&#xff08;https://www.cnblogs.com/strengthen/ &#xff09;➤GitHub地址&…

config.cfg.php,PHP:使用给定的结构获取变量形式的config.cfg

对于专业人士来说这可能是一个愚蠢的问题&#xff0c;但即使经过几个小时的谷歌搜索&#xff0c;我也找不到解决方案&#xff1a;我有一个共享config.cfg与以下结构(所以我不能做任何关于结构)&#xff1a;[config]fileExtensions"JPEG|JPG|jpg|jpeg|png|gif"content…

沣东新城镐京遗址规划_沣东新城房价为啥这么高?

沣东房价为啥2万&#xff0c;为啥超越曲江浐灞&#xff0c;为啥和高新差不多&#xff1f;很多论坛 账号 抖音 喋喋不休&#xff0c;那么说说到底为啥这么贵1、从2018年开始&#xff0c;沣东新城商品房住宅用地&#xff0c;几乎容积率都在2.8以上&#xff0c;90%以上容积率在2.5…

前端工程师和设计师必读文章推荐【系列三十六】

《Web 前端开发精华文章推荐》自2011年6月20号发布第一期以来&#xff0c;历经五年半&#xff0c;总共发布了30多期。今天这篇是2017年第2期&#xff08;总第36期&#xff09;&#xff0c;希望你能在这里发现有用的资料。 梦想天空专注前端开发技术&#xff0c;分享提升网站用户…