当我希望在许多相似的领域执行相同的测试时,如何在 Grails Spock 测试中迭代测试?

How do I iterate over tests in Grails Spock testing when I wish to perform the same tests on many similar fields?

我有一个域 class 有 属性 对:

Boolean statement1
Boolean statement1Missing

这些对数最多为九对。

以下限制适用于每个配对:

    statement1                  nullable: true
    statement1Missing           validator: {val, obj ->
                                    if ( val == true &&
                                        (obj.statement1 == true || obj.statement1 == false)) {
                                        return ['statement.not.missing', 1] 
                                    }
                                    if (obj.statement1 == null && val == false) {
                                        return ['statement.is.missing', 1]
                                    }
                                }

我设计了一个可以容纳一对语句的集成测试:

@Unroll
def "Validation of custom validation for statement1"() {

    given: "New data"
    def participant = new Data(studyId:     "M00001",
                                            formVersion:    Version.get(7)                          
                                           )

    and: "an initial set of test values"
    participant.statement1 = statement1
    participant.statement1Missing = statement1Missing

    when: "the validator is invoked"
    def isValidConsentData = participant.validate()

    then: "the appropriate fields are flagged as errors"
    isValidConsentData == anticipatedValid
    participant.errors.getFieldError(fieldInError)?.code == errorCode

    where:

    statement1  | statement1Missing | anticipatedValid  | fieldInError          | errorCode
    true        | false             | true              | null                  | null
    false       | false             | true              | null                  | null
    null        | true              | true              | null                  | null
    null        | false             | false             | "statement1Missing"   | "statement.is.missing"
    true        | true              | false             | "statement1Missing"   | "statement.not.missing"
    false       | true              | false             | "statement1Missing"   | "statement.not.missing"
}

这处理了我希望测试的语句 1 的所有组合。

我一直在想办法对所有九个语句对重复这个测试。我试过这样循环:

    (1..9).each { statementNo
        ...
        and ...
        participant.("statement" + statementNo) = ("statement" + statementNo)
        ...
        where:
        ("statement" + StatementNo) | ("statement" + StatementNo + Missing) | ...
    }

我以前在想要迭代属性时使用过这种类型的迭代,但它在 Spock 中不起作用。测试被完全忽略。我真的不想为每个语句对重复这段代码。

我研究了这种结构的使用 http://www.christianoestreich.com/2012/11/domain-constraints-grails-spock-updated/ 但这只允许您一次测试一个 属性 值,而我想测试一个 属性 值很多次。

另一种选择是在 'where' 块中明确包含每个 属性 对和每个可能的结果,但这会非常麻烦。

请提供一些关于如何使用迭代结构来执行这些测试的建议。

怎么样:

...    

and: "an initial set of test values"
(1..9).each { statementNo ->
    participant."statement$statementNo" = statement
    participant."statement${statementNo}Missing" = statementMissing
}

when: "the validator is invoked"
def isValidConsentData = participant.validate()

then: "the appropriate fields are flagged as errors"
(1..9).each { statementNo ->
    def fieldInError
    if (anticipatedValid) {
        fieldInError = null
    } else {
        fieldInError = "statement${statementNo}Missing"
    }
    assert isValidConsentData == anticipatedValid
    assert participant.errors.getFieldError(fieldInError)?.code == errorCode
}

where:
statement  | statementMissing | anticipatedValid | errorCode
true       | false            | true             | null
false      | false            | true             | null
null       | true             | true             | null
null       | false            | false            | "statement.is.missing"
true       | true             | false            | "statement.not.missing"
false      | true             | false            | "statement.not.missing"

不确定给定字段没有错误时 getFieldError(fieldName) 的行为方式,因此您可能需要使用 !anticipatedValid 为第二个断言添加一些条件,如果会抛出异常。

重要的是隐式 assert 是必要的,因为 each 是无效的,否则测试根本不会检查任何内容。