Introduction and use of Spock test framework

Using groovy to simplify testing in Java projects and spock as a java project testing framework

brief introduction

Spock framework is a groovy grammar-based testing framework. Because of groovy, it is more flexible to use than junit, and the writing of test cases is more simple and easy to understand at a glance.

If you have used junit, spock is easy to learn by analogy.

Use

The following is a direct example of spock usage:

1. Adding dependencies

        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-core</artifactId>
            <version>1.2-groovy-2.4</version>
            <scope>test</scope>
        </dependency>
        <!-- Spock Necessary groovy rely on -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.15</version>
        </dependency>
        <!-- spring boot spock -->
        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-spring</artifactId>
            <version>1.2-groovy-2.4</version>
            <scope>test</scope>
        </dependency>

2. Life Cycle of Testing Methods

In the use of junit, the following annotations are used to mark the methods of test classes:

@ Test: Mark the test methods that need to be run. There can be multiple @Test methods in a test class.
@ Before/@After: The tagged method runs once before/after each test method runs;
@ BeforeClass/@AfterClass: The tagged method runs when the test class is initialized/destroyed;

Spoke does not use the above annotation form, but the test class needs to inherit the Specification parent class and override the following methods in the parent class to customize the lifetime of the test method:

def setup() {}         // run before every feature method
def cleanup() {}       // run after every feature method
def setupSpec() {}     // run before the first feature method
def cleanupSpec() {}   // run after the last feature method

So there are the following test codes:

package com.yawn.spock

import spock.lang.Shared
import spock.lang.Specification

/**
 * spock test
 * @author yawn
 *     2019/6/10 9:43
 */
class CalculateSpec extends Specification {

    // Initialization
    def setupSpec() {
        calculateService = new CalculateService()
        println ">>>>>>   setupSpec"
    }
    def setup() {
        println ">>>>>>   setup"
    }
    def cleanup() {
        println ">>>>>>   cleanup"
    }
    def cleanupSpec() {
        println ">>>>>>   cleanupSpec"
    }

    def "test life cycle"() {
        given:
        def a = 1
        def b = 2

        expect:
        a < b

        println "test method finished!"
    }
}

The results are as follows:

Lifecycle method execution sequence for spock testing

3. Format of test methods

(1) given... expect... Format:

given statement block is the condition, expect is the expected result of the test, and true is the result of the test. The example above is in this format.

(2)given ... when ... then ...

class CalculateSpec extends Specification {
    @Shared
    CalculateService calculateService

    // Initialization
    def setupSpec() {
        calculateService = new CalculateService()
    }
    // test method
    def "test plus 1"() {
        given: "Preparing data"
        def a = 1
        def b = 2

        when: "test method"
        def c = calculateService.plus(a, b)

        then: "Verification results"
        c == 4 - 1
    }

The @Share annotation represents an instance shared by each test method. This instance is initialized in the setupSpec() method.

(3)when ... then ...

Semantic Ibid.

(4)given ... expect ... where ...

def "test1"() {
    given: "Prepare data"

    expect: Test Method
    z == calculateService.plus(x, y)

    where: "Check results"
    x | y || z
    1 | 0 || 1
    2 | 1 || 3
}

Expct is the core test verification statement block. where is an intuitive way to list multiple test cases.

The semantics of the above test methods are as follows: z is the result of method plus() operation of X and y. Now, two sets of values of x, y and z are listed to test whether the relationship is satisfied.

Because there are two test cases, the plus() method runs here twice.

(5)expect ... where ...

Ditto.

(6)expect ...

Ditto. Test the validity of a single statement.

4.where test case enumeration format:

where can list a number of test cases, with the following different formats:

// 1 mapping format
    def "length of Spock's and his friends' names"() {
        expect:
        name.size() == length
        where:
        name     | length
        "Spock"  | 5
        "Kirk"   | 4
        "Scotty" | 6
    }
    // 2 Array list format (each array order can not be confused)
    def "length of Yawn's and his friends' names"() {
        expect:
        name.size() == length

        where:
        name << ["Yawn", "Tim"]
        length << [4, 3]
    }

5. VeryAll checks multiple expression results

    def "Parametric verifyAll"() {
        when:
        int z1 = calculateService.plus(1, 1)
        int z2 = calculateService.plus(1, 2)
        int z3 = calculateService.plus(1, 3)

        then:
        verifyAll {
            z1 == 1
            z2 == 3
            z3 == 3
        }
    }

The verifyAll statement block can verify the results of multiple Booleans separately.

6.with() and verifyAll() take the value of the object property

    def "test person use with(p)"() {
        given: "init a person"
        Date now = new Date()
        Person p = new Person(name: "yawn", age: 18, birthday:   now)

        expect: "test p"
        with(p) {
            name == "yawn"
            age < 20
            birthday == now
        }
    }

    def "Test usage of multiple expected values verifyAll()"() {
        when:
        Person p = new Person(name: "yawn", age: 18)

        then:
        verifyAll(p) {
            name == "yawn"
            age < 20
        }
    }

    static class Person {
        private String name
        private int age
        private Date birthday
    }

with() and verifyAll() passed into the object, its attribute values can be used directly.

7. Execute the tested statements many times:

def "Multiple Execution Test Statements" (){
        given:
        def a = 0

        expect: "aaa"
        3 * calculateService.plusPlus(a) == 3

        // After three executions, the result was 3.
    }

"3 *" means that the statement will be executed three times, and then compared with the three following "==".

The next blog will introduce you. Test pileUse And How to use spock in spring environment.

This article is from the java technology sharing station (jvm123.com) http://jvm123.com/2019/08/spock.html.

Tags: Programming Java Junit Spring Attribute

Posted on Mon, 09 Sep 2019 23:50:53 -0700 by t31os