diff --git a/docs/src/main/asciidoc/verifier/contract.adoc b/docs/src/main/asciidoc/verifier/contract.adoc index 165d669e28..021bef0799 100644 --- a/docs/src/main/asciidoc/verifier/contract.adoc +++ b/docs/src/main/asciidoc/verifier/contract.adoc @@ -36,6 +36,27 @@ WARNING: Due to the fact that JSON structure can have any form it's sometimes im the `value(consumer(...), producer(...))` notation when using that in GString. That's why we highly recommend using the Groovy Map notation. +==== Common Top-Level elements + +===== Description + +You can add a `description` to your contract that is nothing else but an arbitrary text. Example: + +[source,groovy,indent=0] +---- +include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=description,indent=0] +---- + +===== Ignoring contracts + +If you want to ignore a contract you can either set a value of ignored contracts in the plugin configuration +or just set the `ignored` property on the contract itself: + +[source,groovy,indent=0] +---- +include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=ignored,indent=0] +---- + ==== HTTP Top-Level Elements Following methods can be called in the top-level closure of a contract definition. Request and response are mandatory, priority is optional. diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/Contract.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/Contract.groovy index 6db92a53a7..5e34b90bb3 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/Contract.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/Contract.groovy @@ -34,6 +34,11 @@ import org.springframework.cloud.contract.spec.internal.Response @ToString(includeFields = true, includePackage = false, includeNames = true) class Contract { + /** + * You can set the level of priority of this contract. If there are two contracts + * mapped for example to the same endpoint, then the one with greater priority should + * take precedence + */ Integer priority Request request Response response @@ -42,6 +47,11 @@ class Contract { Input input OutputMessage outputMessage + /** + * Whether the contract should be ignored or not + */ + boolean ignored + protected Contract() {} /** @@ -90,4 +100,8 @@ class Contract { closure() } + void ignored() { + this.ignored = true + } + } diff --git a/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy b/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy index 6ba474381e..a5207545a0 100644 --- a/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy +++ b/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy @@ -77,4 +77,29 @@ class ContractSpec extends Specification { then: (property.serverValue as String).matches(/[0-9]{5}/) } + + def 'should set a description'() { + given: + // tag::description[] + org.springframework.cloud.contract.spec.Contract.make { + description(''' +given: + An input +when: + Sth happens +then: + Output +''') + } + // end::description[] + } + + def 'should mark a contract ignored'() { + given: + // tag::ignored[] + org.springframework.cloud.contract.spec.Contract.make { + ignored() + } + // end::ignored[] + } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy index c6ca7fcc3d..60927dde38 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy @@ -58,7 +58,7 @@ class MethodBuilder { log.debug("Stub content Groovy DSL [$stubContent]") } String methodName = NamesUtil.camelCase(NamesUtil.toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator))) - return new MethodBuilder(methodName, stubContent, configProperties, contract.ignored) + return new MethodBuilder(methodName, stubContent, configProperties, contract.ignored || stubContent.ignored) } /** diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy index 42437f9fed..a226611c2f 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy @@ -60,10 +60,6 @@ class SingleTestGenerator { } } - if (listOfFiles.ignored.find { it }) { - clazz.addImport(configProperties.targetFramework.getIgnoreClass()) - } - if (configProperties.staticImports) { configProperties.staticImports.each { clazz.addStaticImport(it) @@ -80,6 +76,7 @@ class SingleTestGenerator { Map contracts = mapContractsToTheirTestTypes(listOfFiles) boolean conditionalImportsAdded = false + boolean toIgnore = listOfFiles.ignored.find { it } contracts.each { ParsedDsl key, TestType value -> if (!conditionalImportsAdded) { if (contracts.values().contains(TestType.HTTP)) { @@ -109,9 +106,15 @@ class SingleTestGenerator { addMessagingRelatedEntries(clazz) } conditionalImportsAdded = true + toIgnore = toIgnore ? true: key.groovyDsl.ignored } clazz.addMethod(MethodBuilder.createTestMethod(key.contract, key.stubsFile, key.groovyDsl, configProperties)) } + + if (toIgnore) { + clazz.addImport(configProperties.targetFramework.getIgnoreClass()) + } + return clazz.build() } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockStubStrategy.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockStubStrategy.groovy index efc95211d8..9a01ed02b8 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockStubStrategy.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockStubStrategy.groovy @@ -40,6 +40,7 @@ class WireMockStubStrategy { private final Integer priority private final ContractMetadata contract private final String rootName + private final Contract groovyDsl WireMockStubStrategy(String rootName, ContractMetadata contract, Contract groovyDsl) { this.rootName = rootName @@ -47,6 +48,7 @@ class WireMockStubStrategy { this.wireMockRequestStubStrategy = new WireMockRequestStubStrategy(groovyDsl) this.wireMockResponseStubStrategy = new WireMockResponseStubStrategy(groovyDsl) this.priority = groovyDsl.priority + this.groovyDsl = groovyDsl } /** @@ -69,6 +71,10 @@ class WireMockStubStrategy { return '' } + if (groovyDsl.ignored || contract.ignored) { + return '' + } + if (contract.order != null) { stubMapping.scenarioName = "Scenario_" + rootName stubMapping.requiredScenarioState = contract.order == 0 ? STEP_START : STEP_PREFIX + contract.order diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy index f201949740..5bc5a668ec 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy @@ -1,7 +1,7 @@ /* * Copyright 2013-2016 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * @@ -29,10 +29,10 @@ import java.nio.file.Path */ @CompileStatic class ContractMetadata { - final Path path; - final boolean ignored; + final Path path + final boolean ignored final int groupSize - final Integer order; + final Integer order ContractMetadata(Path path, boolean ignored, int groupSize, Integer order) { this.groupSize = groupSize @@ -48,6 +48,6 @@ class ContractMetadata { ", ignored=" + ignored + ", groupSize=" + groupSize + ", order=" + order + - '}'; + '}' } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy index 23d0e35430..8db73be660 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy @@ -21,6 +21,7 @@ import org.junit.rules.TemporaryFolder import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.config.TestMode import org.springframework.cloud.contract.verifier.file.ContractMetadata +import spock.lang.Issue import spock.lang.Specification import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT @@ -145,5 +146,44 @@ class SingleTestGeneratorSpec extends Specification { SPOCK | spockClassStrings } + @Issue('#30') + def "should ignore a test if the contract is ignored in the dsl"() { + given: + File secondFile = tmpFolder.newFile() + secondFile.write(""" + org.springframework.cloud.contract.spec.Contract.make { + ignored() + request { + method 'PUT' + url 'url' + } + response { + status 200 + } + } + """) + and: + ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(); + properties.targetFramework = testFramework + and: + ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, 2) + contract2.ignored >> false + contract2.order >> 2 + and: + SingleTestGenerator testGenerator = new SingleTestGenerator(properties) + + when: + String clazz = testGenerator.buildClass([contract2], "test", "test", 'com/foo') + + then: + classStrings.each { clazz.contains(it) } + clazz.contains('@Ignore') + + where: + testFramework | classStrings + JUNIT | jUnitClassStrings + SPOCK | spockClassStrings + } + } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy index 118f338920..244799d239 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy @@ -1575,4 +1575,57 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie and: stubMappingIsValidWireMockStub(json) } + + @Issue('#30') + def "should not create a stub for a skipped contract"() { + given: + org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make { + request { + ignored() + method 'GET' + urlPath ('/some/api') { + queryParameters { + parameter 'size': value( + consumer(regex('[0-9]+')), + producer(1) + ) + } + } + } + response { + status 200 + body('') + } + } + when: + def json = toWireMockClientJsonStub(groovyDsl) + then: + json == '' + } + + @Issue('#30') + def "should not create a stub for a contract matching ignored pattern"() { + given: + org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make { + request { + method 'GET' + urlPath ('/some/api') { + queryParameters { + parameter 'size': value( + consumer(regex('[0-9]+')), + producer(1) + ) + } + } + } + response { + status 200 + body('') + } + } + when: + def json = new WireMockStubStrategy("Test", new ContractMetadata(null, true, 0, null), groovyDsl).toWireMockClientStub() + then: + json == '' + } }