提起单元测试(这里特指Java的单元测试),很多人可能第一时间想到的是junit、mockito等等的框架,或者可能压根你的项目都没写过单测,得益于本地可以方便的运行项目,所以很多人就直接人肉测试了一下就交给QA了,然后被各种bug劈头盖脸而来。倒不是说写单元测试可以完全规避bug,能规避50%以上吧,而且对于后续的改动是持续有效的,因为很多人会觉得我就改了一行代码,怎么会有问题呢?往往问题就来自于此。
单元测试的价值我也无需多言,今天主要是安利一个单测的新势力框架——spock。单元测试的框架层出不穷,最终的目的就是让开发者可以方便的验证自己的代码。这可能是Java领域为数不多的可以不用标榜性能的框架了,因为单测最重要的是方便,方便的运行、方便的mock、方便的开发,慢点真倒不重要。junit相对原始一些,可能也是众多框架中最靠近java语法的,mockito之类的就封装了很多方法,也可以称之为DSL,一系列的give,when等等方法,给人最简单的直觉,减少了代码量,也更容易书写和理解。
方便就是单测框架的发展方向,而今天要介绍的spock更是把这一理念又想向前推进了一大步。spock的官网是这么形容自己的:
What makes it stand out from the crowd is its beautiful and highly expressive specification language.
spock是基于行为驱动开发(BDD)的思想,提供了各种标签,并采用简单、通用、结构化的描述语言(DSL),甚至直接使用了groovy作为单测的开发语言。不用担心学习成本,几乎是看一眼就可以学会的语法,甚至可以认为没有语法。下面举一个简单的例子来说明为什么spock很好用。
这是一个典型的if/else场景,也不知道为了什么很多人都很讨厌if/else,写if/else很low吗?只要逻辑清晰,也没什么问题吧。这是计算个人所得税的案例,不用if/else能用什么呢?
public double calc(double income) {
BigDecimal tax;
BigDecimal salary = BigDecimal.valueOf(income);
if (income <= 0) {
return 0;
}
if (income > 0 && income <= 3000) {
BigDecimal taxLevel = BigDecimal.valueOf(0.03);
tax = salary.multiply(taxLevel);
} else if (income > 3000 && income <= 12000) {
BigDecimal taxLevel = BigDecimal.valueOf(0.1);
BigDecimal base = BigDecimal.valueOf(210);
tax = salary.multiply(taxLevel).subtract(base);
} else if (income > 12000 && income <= 25000) {
BigDecimal taxLevel = BigDecimal.valueOf(0.2);
BigDecimal base = BigDecimal.valueOf(1410);
tax = salary.multiply(taxLevel).subtract(base);
} else if (income > 25000 && income <= 35000) {
BigDecimal taxLevel = BigDecimal.valueOf(0.25);
BigDecimal base = BigDecimal.valueOf(2660);
tax = salary.multiply(taxLevel).subtract(base);
} else if (income > 35000 && income <= 55000) {
BigDecimal taxLevel = BigDecimal.valueOf(0.3);
BigDecimal base = BigDecimal.valueOf(4410);
tax = salary.multiply(taxLevel).subtract(base);
} else if (income > 55000 && income <= 80000) {
BigDecimal taxLevel = BigDecimal.valueOf(0.35);
BigDecimal base = BigDecimal.valueOf(7160);
tax = salary.multiply(taxLevel).subtract(base);
} else {
BigDecimal taxLevel = BigDecimal.valueOf(0.45);
BigDecimal base = BigDecimal.valueOf(15160);
tax = salary.multiply(taxLevel).subtract(base);
}
return tax.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
}
对于这个方法的test case用spock写是这样的:
@Unroll
def "个税计算,收入:#income, 个税:#result"() {
expect: "when + then 的组合"
CalculateTaxUtils.calc(income) == result
where: "表格方式测试不同的分支逻辑"
income || result
-1 || 0
0 || 0
2999 || 89.97
3000 || 90.0
3001 || 90.1
11999 || 989.9
12000 || 990.0
12001 || 990.2
24999 || 3589.8
25000 || 3590.0
25001 || 3590.25
34999 || 6089.75
35000 || 6090.0
35001 || 6090.3
54999 || 12089.7
55000 || 12090
55001 || 12090.35
79999 || 20839.65
80000 || 20840.0
80001 || 20840.45
}
这样简单快捷的单测写法,节省时间又大幅降低出bug的概率,不尝试一下吗?
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理