Статьи

Spock VW: написание собственных расширений Spock Framework

Платформа Spock имеет несколько встроенных расширений, которые поддерживают множество основных функций, таких как аннотации @Ignore и @Timeout . Но что более важно, разработчикам рекомендуется писать свои собственные расширения. Например, SpringExtension прекрасно интегрирует Spock с Spring Framework. Написание пользовательских расширений не очень хорошо документировано. В этой статье мы напишем очень простое расширение. Это не всеобъемлющее руководство, а просто забавная витрина.

Представляем расширение Spock VW

В некоторых инженерных отраслях [1] строгие тесты должны проходить только при проведении внешнего аудита. В программировании это будет сервер непрерывной интеграции. Расширение Spock VW гарантирует, что все тесты пройдут на сервере CI, даже если они не пройдут на компьютере разработчика или на производстве. Идея в значительной степени вдохновлена phpunit-vw . Давайте возьмем этот простой, полностью составленный тест, который не может быть успешным:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Unroll
class EmissionsSpec extends Specification {
  
    def 'nitrogen oxide emission (#emission) in #model must not exceed #allowed'() {
        expect:
            emission <= allowed
        where:
            model    | emission || allowed
            'Jetty'  | 1.5      || 0.022
            'Pascal' | 0.67     || 0.016
    }
  
    def 'carbon dioxide'() {
        expect:
            105 < 130
    }
}

Первый тест, очевидно, не удался для обоих примеров, но мы можем прозрачно добавить расширение Spock, которое гарантирует, что ни один CI-сервер никогда не уловит эту проблему. Расширение просто проверяет все системные свойства и переменные среды, пытаясь выяснить, является ли среда хоста на самом деле CI-сервером:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.nurkiewicz.vw
  
import org.spockframework.runtime.extension.IGlobalExtension
import org.spockframework.runtime.model.SpecInfo
  
  
class VwExtension implements IGlobalExtension {
  
    private static final CONTROLLED_ENV = [
            'bamboo.buildKey',
            'BUILD_ID', 'BUILD_NUMBER', 'BUILDKITE',
            'CI', 'CIRCLECI',
            'CONTINUOUS_INTEGRATION',
            'GOCD_SERVER_HOST',
            'HUDSON_URL', 'JENKINS_URL',
            'TEAMCITY_VERSION',
            'TRAVIS',
    ]
  
    private static final boolean EVERYTHING_IS_FINE =
            CONTROLLED_ENV.any {prop ->
                System.getProperty(prop) || System.getenv(prop)}
  
    @Override
    void visitSpec(SpecInfo spec) {
        if (EVERYTHING_IS_FINE) {
            spec.features*.skipped = true
        }
    }
}

VwExtension подобен аспекту каждой Specification VwExtension в вашей кодовой базе. Он проверяет список известных переменных среды и, если они any() (постоянная EVERYTHING_IS_FINE ), все features (тесты) в этой Spec пропускаются. Еще кое-что. Расширения не обнаруживаются автоматически, необходимо создать специальный файл org.spockframework.runtime.extension.IGlobalExtension каталоге META-INF/services на CLASSPATH (конечно, он может находиться в другом JAR-файле). Содержимое этого файла — это просто полное имя класса расширения, например com.nurkiewicz.vw.VwExtension .

Вот и все, счастливого тестирования!