Added option of multiple test base classes

without this change the user was forced to use a single base class for all of the generated tests. It could become problematic after some time.

With this change we provide a range of options of providing different base classes for different contracts.

fixes #16
This commit is contained in:
Marcin Grzejszczak
2016-09-23 15:39:12 +02:00
parent 82a3da2b37
commit e8917940ec
33 changed files with 746 additions and 33 deletions

View File

@@ -818,4 +818,9 @@ and contracts present under the `com/example/server` will be picked as the ones
tests and the stubs. Due to this convention the producer team will know which consumer teams will be broken
when some incompatible changes are done.
The rest of the flow looks the same.
The rest of the flow looks the same.
===== Can I have multiple base classes for tests?
Yes! Check out the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#different_base_classes_for_contracts[Different base classes for contracts] sections
of either Gradle or Maven plugins.

View File

@@ -182,7 +182,9 @@ contracts {
- **imports** - array with imports that should be included in generated tests (for example ['org.myorg.Matchers']). By default empty array []
- **staticImports** - array with static imports that should be included in generated tests(for example ['org.myorg.Matchers.*']). By default empty array []
- **basePackageForTests** - specifies base package for all generated tests. By default set to org.springframework.cloud.verifier.tests
- **baseClassForTests** - base class for generated tests. By default `spock.lang.Specification` if using Spock tests.
- **baseClassForTests** - base class for all generated tests. By default `spock.lang.Specification` if using Spock tests.
- **packageWithBaseClasses** - instead of providing a fixed value for base class you can provide a package where all the base classes lay. Takes precedence over **baseClassForTests**.
- **baseClassMappings** - explicitly map contract package to a FQN of a base class. Takes precedence over **packageWithBaseClasses** and **baseClassForTests**.
- **ruleClassForTests** - specifies Rule which should be added to generated test classes.
- **ignoredFiles** - Ant matcher allowing defining stub files for which processing should be skipped. By default empty array []
- **contractsDslDir** - directory containing contracts written using the GroovyDSL. By default `$rootDir/src/test/resources/contracts`
@@ -196,7 +198,7 @@ The following properties are used when you want to provide where the JAR with co
- **contractsPath** - if contract deps are downloaded will default to `groupid/artifactid` where `groupid` will be slash separated. Otherwise will scan contracts under provided directory
- **contractsWorkOffline** - in order not to download the dependencies each time you can download them once and work offline afterwards (reuse local Maven repo)
====== Base class for tests
====== Single base class for all tests
When using Spring Cloud Contract Verifier in default MockMvc you need to create a base specification for all generated acceptance tests. In this class you need to point to endpoint which should be verified.
@@ -208,6 +210,43 @@ include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/f
In case of using `Explicit` mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of `JAXRSCLIENT` mode this base class
should also contain `protected WebTarget webTarget` field, right now the only option to test JAX-RS API is to start a web server.
====== Different base classes for contracts
If your base classes differ between contracts you can tell the Spring Cloud Contract plugin which class should get
extended by the autogenerated tests. You have two options:
- follow a convention by providing the `packageWithBaseClasses`
- provide explicit mapping via `baseClassMappings`
*Convention*
The convention is such that if you have a contract under e.g. `src/test/resources/contract/foo/bar/baz/` and provide the value of the `packageWithBaseClasses` property
to `com.example.base` then we will assume that there is a `BarBazBase` class under `com.example.base` package. In other words we take last two parts of package
if they exist and form a class with a `Base` suffix. Takes precedence over **baseClassForTests**. Example of usage in the `contracts` closure:
[source,groovy,indent=0]
----
include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierSpec.groovy[tags=package_with_base_classes,indent=0]
----
*Mapping*
You can manually map a regular expression of the contract's package to fully qualified name of the base class for the matched contract.
Let's take a look at the following example:
[source,groovy,indent=0]
----
include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierSpec.groovy[tags=base_class_mappings,indent=0]
----
Let's assume that you have contracts under
- `src/test/resources/contract/com/`
- `src/test/resources/contract/foo/`
By providing the `baseClassForTests` we have a fallback in case mapping didn't succeed (you could also provide
the `packageWithBaseClasses` as fallback). That way the tests generated from `src/test/resources/contract/com/` contracts
will be extending the `com.example.ComBase` whereas the rest of tests will extend `com.example.FooBase`.
===== Invoking generated tests
To ensure that provider side is complaint with defined contracts, you need to invoke:
@@ -341,6 +380,15 @@ To change default configuration just add `configuration` section to plugin defin
- **baseClassForTests** - base class for generated tests. By default `spock.lang.Specification` if using Spock tests.
- **contractsDir** - directory containing contracts written using the GroovyDSL. By default `/src/test/resources/contracts`.
- **testFramework** - the target test framework to be used; currently Spock and JUnit are supported with JUnit being the default framework
- **packageWithBaseClasses** - instead of providing a fixed value for base class you can provide a package where all the base classes lay.
The convention is such that if you have a contract under `src/test/resources/contract/foo/bar/baz/` and provide the value of this property
to `com.example.base` then we will assume that there is a `BarBazBase` class under `com.example.base` package. Takes precedence
over **baseClassForTests**
- **baseClassMappings** - list of base class mappings that where you have to provide `contractPackageRegex` which is checked
against the package in which the contract lays and `baseClassFQN` that maps to fully qualified name of the base class for the matched
contract. If you have a contract under `src/test/resources/contract/foo/bar/baz/` and map the property `.*` -> `com.example.base.BaseClass` then
the test class generated from these contracts will extend `com.example.base.BaseClass`. Takes precedence over **packageWithBaseClasses**
and **baseClassForTests**.
If you want to download your contract definitions from a Maven repository you can use
@@ -351,7 +399,7 @@ If you want to download your contract definitions from a Maven repository you ca
For complete information take a look at https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/plugin-info.html[Plugin Documentation]
====== Base class for tests
====== Single base class for all tests
When using Spring Cloud Contract Verifier in default MockMvc you need to create a base specification for all generated acceptance tests.
In this class you need to point to endpoint which should be verified.
@@ -373,6 +421,44 @@ class MvcSpec extends Specification {
In case of using `Explicit` mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of `JAXRSCLIENT` mode this base class should also contain `protected WebTarget webTarget` field, right now the only option to test JAX-RS API is to start a web server.
====== Different base classes for contracts
If your base classes differ between contracts you can tell the Spring Cloud Contract plugin which class should get
extended by the autogenerated tests. You have two options:
- follow a convention by providing the `packageWithBaseClasses`
- provide explicit mapping via `baseClassMappings`
*Convention*
The convention is such that if you have a contract under e.g. `src/test/resources/contract/hello/v1/` and provide the value of the `packageWithBaseClasses` property
to `hello` then we will assume that there is a `HelloV1Base` class under `hello` package. In other words we take last two parts of package
if they exist and form a class with a `Base` suffix. Takes precedence over **baseClassForTests**. Example of usage in the `contracts` closure:
[source,xml,indent=0]
----
include::{plugins_path}/spring-cloud-contract-maven-plugin/src/test/projects/basic-generated-baseclass/pom.xml[tags=convention,indent=0]
----
*Mapping*
You can manually map a regular expression of the contract's package to fully qualified name of the base class for the matched contract.
You have to provide a list `baseClassMappings` of `baseClassMapping` that takes a `contractPackageRegex` to `baseClassFQN` mapping.
Let's take a look at the following example:
[source,xml,indent=0]
----
include::{plugins_path}/spring-cloud-contract-maven-plugin/src/test/projects/basic-baseclass-from-mappings/pom.xml[tags=mapping,indent=0]
----
Let's assume that you have contracts under
- `src/test/resources/contract/com/`
- `src/test/resources/contract/foo/`
By providing the `baseClassForTests` we have a fallback in case mapping didn't succeed (you could also provide
the `packageWithBaseClasses` as fallback). That way the tests generated from `src/test/resources/contract/com/` contracts
will be extending the `com.example.ComBase` whereas the rest of tests will extend `com.example.FooBase`.
===== Invoking generated tests
Spring Cloud Contract Verifier Maven Plugin generates verification code into directory `/generated-test-sources/contractVerifier` and attach this directory to `testCompile` goal.