Spocklight:优化运行顺序测试方法

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

Spock 能够改变规范中测试方法的执行顺序。我们可以告诉 Spock 在成功的方法之前重新运行失败的方法。如果我们有多个失败或成功的测试,那么首先运行最快的方法,然后是较慢的方法。这样,当我们重新运行规范时,我们会立即看到失败的方法,并且可以停止执行并修复错误。我们必须在 Spock 配置文件的 runner 配置中设置属性 optimizeRunOrder 。一个名为 SpockConfig.groovy 的 Spock 配置文件可以放在我们测试执行的类路径或我们的 USER_HOME/.spock 目录中。我们还可以使用 Java 系统属性 spock.configuration 并分配我们的 Spock 配置文件的文件名。

在下面的示例中,我们有一个规范,其中包含不同的方法,这些方法可以成功或失败,并且在执行时具有不同的持续时间:


 package com.mrhaki.spock

import spock.lang.Specification import spock.lang.Subject

class SampleSpec extends Specification {

@Subject
private Sample sample = new Sample()

def "spec1 - slowly should return name property value"() {
    given:
    sample.name = testValue

    expect:
    sample.slowly() == testValue

    where:
    testValue = 'Spock rules'
}

def "spec2 - check name property"() {
    given:
    sample.name = testValue

    expect:
    sample.name == testValue

    where:
    testValue = 'Spock is gr8'
}

def "spec3 - purposely fail test at random"() {
    given:
    sample.name = testValues[randomIndex]

    expect:
    sample.name == testValues[0]

    where:
    testValues = ['Spock rules', 'Spock is gr8']
    randomIndex = new Random().nextInt(testValues.size())
}

def "spec4 - purposely fail test slowly"() {
    given:
    sample.name = 'Spock is gr8'

    expect:
    sample.slowly() == 'Spock rules'
}

def "spec5 - purposely fail test"() {
    given:
    sample.name = 'Spock rules'

    expect:
    sample.name == 'Spock is gr8'
}

}

class Sample { String name

String slowly() {
    Thread.sleep(2000)
    name
}

}

让我们在没有优化运行顺序的地方运行我们的测试。我们看到这些方法按照规范中的定义执行:

接下来我们创建一个包含以下内容的 Spock 配置文件:


 package com.mrhaki.spock

import spock.lang.Specification import spock.lang.Subject

class SampleSpec extends Specification {

@Subject
private Sample sample = new Sample()

def "spec1 - slowly should return name property value"() {
    given:
    sample.name = testValue

    expect:
    sample.slowly() == testValue

    where:
    testValue = 'Spock rules'
}

def "spec2 - check name property"() {
    given:
    sample.name = testValue

    expect:
    sample.name == testValue

    where:
    testValue = 'Spock is gr8'
}

def "spec3 - purposely fail test at random"() {
    given:
    sample.name = testValues[randomIndex]

    expect:
    sample.name == testValues[0]

    where:
    testValues = ['Spock rules', 'Spock is gr8']
    randomIndex = new Random().nextInt(testValues.size())
}

def "spec4 - purposely fail test slowly"() {
    given:
    sample.name = 'Spock is gr8'

    expect:
    sample.slowly() == 'Spock rules'
}

def "spec5 - purposely fail test"() {
    given:
    sample.name = 'Spock rules'

    expect:
    sample.name == 'Spock is gr8'
}

}

class Sample { String name

String slowly() {
    Thread.sleep(2000)
    name
}

}

如果我们重新运行我们的规范并且在类路径中有这个文件,我们已经看到方法的顺序已经改变了。失败的测试在顶部,成功的测试在底部。最慢的测试方法是最后一个:

另一次重新运行通过在其他失败测试之后运行最慢的失败测试来优化顺序。

Spock 在 USER_HOME/.spock/RunHistory 目录中的一个文件中跟踪失败和成功的方法及其执行时间。要重置信息,我们必须从该目录中删除该文件。

使用 Spock 1.0-groovy-2.4 编写。