添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
鬼畜的绿豆  ·  Prevent Cross-Site ...·  2 年前    · 
腼腆的机器猫  ·  python ...·  2 年前    · 
怕老婆的黑框眼镜  ·  pytest配置 - 简书·  2 年前    · 
几乎每个编程语言里都有JUnit的复制品,比如在.NET里NUnit,在C++里有CPPUnit。此外还有CUnit , PyUnit ,PHPUnit, OCUnit, DUnit, JSUnit 等等。 JUnit的诞生也足够传奇。 有一次坐飞机的时候Eric Gamma偶遇Kent Beck,两位大牛见面寒暄过以后就觉得很无聊了。旅途漫漫,干点啥好呢? Kent Beck当时力推测试驱动开发(TDD),  但是没有一个工具或者框架能让大家轻松愉快的写测试,并且自动的运行测试。 两位大牛决定撸起袖子自己写一个,正好也可以实践一下XP里的结对编程 。等到飞机落地的时候,一个划时代的单元测试工具就新鲜出炉了,它的名字叫做JUnit。 Eric Gamma是设计模式四人帮(GoF)之一,后来还主导创建了Eclipse和Visual Studio Code。Kent Beck,是极限编程(XP)和测试驱动开发(TDD)的创建者。可以通过下面的图片领略一下两位大佬的风采。 image.png image.png 多年前,我学习了Kent Beck的TDD后,十分依赖JUnit了。然而,当我第一次看到Spock的时,马上就移情别恋了。我喜欢Spock是因为: 不用再为测试的方法名命名而发愁了 我喜欢BDD的风格,尤其是生成的测试报告 表格化的数据驱动的测试太吸引人了 我喜欢Groovy,Spock是基于Groovy写的,Groovy所有的简洁魔幻的语法都可以使用;Spock的语法糖加上Groovy的语法糖,可以让测试代码减少一半儿,带来的简洁明了十分酸爽撩人 但是JUnit还是有Spock不及的优势的: 第一个就是“流行”,这意味着学习成本低,培训成本低,毕竟软件开发还是整个团队的事情,不是所有人愿意学习Spock的 也不是所有人愿意学习Groovy,但Java开发者都会Java,JUnit是基于Java的。另外,Java的强类型对IDE也特别友好,我一般实践TDD的时候,先用JUnit写测试代码,出错后敲击"option+回车",IntelliJ IDEA就会自动修复(比如生成还没有的类、方法等),过程十分流畅。而使用Spock后,IDE对Groovy这种动态语言的支持还是很不足的,这种行云流水的快感没有了 JUnit丰富的生态和兼容性是Spock所不能比的 image.png TDD所推崇的先写测试代码,出现错误(编译错误或测试失败)IDE提示变红后,再写正式代码代码,让错误消失,IDE提示变绿。 在JUnit4的时代,我一有机会还是会选择Spock。但是,当JUnit5,这个下一代的JUnit版本正式发布后,也许可以重新选择JUnit了。 下面我们看看,JUnit5是怎么实现Spock的那些撩人的测试案例的。
assertThat(account.getBalance()).isEqualTo(new Amount(99));
assertThat(account.getConsumeRecords())
    .hasSize(1)
    .hasOnlyOneElementSatisfying(record ->
         assertThat(record.getAmount())
         .isEqualTo(new Amount(1)));
		BDD风格 
		Spock最大亮点之一,Given-When-Than,不解释,代码一目了然:
def "HashMap accepts null key"() {
  given:"一个HashMap"
  def map = new HashMap()
  when:"给它添加null元素"
  map.put(null, "elem")
  then:"不抛出异常"
  notThrown(NullPointerException)
		可以实现“Specifications as Documentation”的效果,也可以生成非常好的报告。
		JUnit5使用@Displayname和@Nested也可以勉强应对吧:
image.png
		运行结果:
image.png
image.png
		数据驱动测试 
		Spock的另一个大亮点,不解释看代码:
import spock.lang.Unroll
class DataDrivenTest extends Specification {
    @Subject def arithmeticOperation = new ArithmeticOperation()
    @Unroll
    def "can add"() {
        expect:
        arithmeticOperation.add(1, b) >= 2
        where:
        b << [1, 2, 3, 4, 5]
    @Unroll
    def "can add #a to #b and receive #result"() {
        expect:
        arithmeticOperation.add(a, b) == result
        where:
        a  | b  | result
        1  | 3  | 4
        3  | 4  | 7
        10 | 20 | 30
		执行效果:
JUnit5怎么实现呢?
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.util.stream.Stream;
public class DataDrivenTest {
    private final ArithmeticOperation arithmeticOperation = new ArithmeticOperation();
    @ParameterizedTest
    @ValueSource(ints = { 1, 2, 3, 4, 5 })
    void canAdd(int b) {
        assertTrue(arithmeticOperation.add(1, b) >= 2);
    @ParameterizedTest(name = "can add {0} to {1} and receive {2}")
    @MethodSource("additionProvider")
    void canAddAndAssertExactResult(int a, int b, int result) {
        assertEquals(result, arithmeticOperation.add(a, b));
    static Stream<Arguments> additionProvider() {
        return Stream.of(
            Arguments.of(1, 3, 4),
            Arguments.of(3, 4, 7),
            Arguments.of(10, 20, 30)
		运行效果:
image.png
		此外,还有Mock/Stub、按条件执行测试等功能,如果大家有兴趣看的话,后续再写。
		总之,可以看到,JUnit5在表达性上,已经在努力追赶Spock了,但局限于Java语法的局限,还是有不小的差距的。但相对于JUnit4,JUnit5进步已经非常大了。如果你尤其是你的团队不想学习Spock/Groovy的话,或者喜欢IDE对Java更好的提示的话,那最起码可以考虑用JUnit5代替JUnit4了。