Rebranding (#287)

This commit is contained in:
Marcin Grzejszczak
2016-06-19 23:55:09 +02:00
committed by GitHub
parent a562775980
commit 817c232d3f
747 changed files with 13363 additions and 6399 deletions

View File

@@ -4,25 +4,9 @@ dist: trusty
before_install:
- "export JAVA_OPTS='-Xmx1024m -XX:MaxPermSize=256m'"
- "rm -rf $HOME/.m2/repository/io/codearte/accurest/stubs"
- "mkdir $HOME/.m2/repository/io/codearte/accurest/ --parents"
- "cp -r stub-runner/stub-runner-spring/src/test/resources/m2repo/repository/io/codearte/accurest/stubs $HOME/.m2/repository/io/codearte/accurest/"
jdk:
- oraclejdk8
install: ./gradlew assemble -s
script: ./gradlew check funcTest install -s --continue && jdk_switcher use oraclejdk8 && ./scripts/runTests.sh && jdk_switcher use $TRAVIS_JDK_VERSION && ./gradlew uploadSnapshotArchives -x check -s
matrix:
include:
# Automatic snapshot release only in Java 7 build
- jdk: oraclejdk7
env:
- DO_RELEASE=true
env:
global:
- secure: NbEQ9t5nGKW0LKmOSV4rTiEbYJARM2rynQBdSXkoILbp+nNaCD6uN41tUu8HrjgbjUDMepFUU+hmGQ47Q2vz5L3NzvW+oHBLgrIu6uAimpdR8qyBE899MBKPE19LsvUOeE9B9TydJgYlY+UEYgxwssUwxsN0RqyY4EErQWMNC8k=
- secure: zCjkMhjF5TbZehNmOK7EV68J35tuc0etWG/ia0eVTjgIv2kp9islJZ3+Jm/gDgkcv2Ydq3oAU2jFbVkUPSSstV3L5KANsighm2qn9tVzRrbTCfM55zcBhnoE0oZHTPNrLoScz0X5sM8Xuvi6ChjGf+lqAxnFW6tFMjx+1uhUIXU=
script: ./gradlew check funcTest install -s --continue && jdk_switcher use oraclejdk8 && ./scripts/runTests.sh

190
README.adoc Normal file
View File

@@ -0,0 +1,190 @@
// Do not edit this file (e.g. go instead to src/main/asciidoc)
:core_path: ../../../..
:verifier_root_path: {core_path}/spring-cloud-contract-verifier
:verifier_core_path: {verifier_root_path}/spring-cloud-contract-verifier-core
:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner
:documentation_url: http://codearte.github.io/accurest
= Spring Cloud Contract Verifier
== Introduction
Just to make long story short - Spring Cloud Contract Verifier is a tool that enables Consumer Driven Contract (CDC) development of JVM-based applications. It is shipped
with __Contract Definition Language__ (DSL). Contract definitions are used to produce following resources:
* JSON stub definitions to be used by Wiremock when doing integration testing on the client code (__client tests__).
Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier.
* Messaging routes if you're using one. We're integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to
* Acceptance tests (in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (__server tests__).
Full test is generated by Spring Cloud Contract Verifier.
Spring Cloud Contract Verifier moves TDD to the level of software architecture.
=== Why?
Let us assume that we have a system comprising of multiple microservices:
image::Deps.png[Microservices Architecture]
==== Testing issues
If we wanted to test the application in top left corner if it can communicate with other services then we could do one of two things:
- deploy all microservices and perform end to end tests
- mock other microservices in unit / integration tests
Both have their advantages but also a lot of disadvantages. Let's focus on the latter.
*Deploy all microservices and perform end to end tests*
Advantages:
- simulates production
- tests real communication between services
Disadvantages:
- to test one microservice we would have to deploy 6 microservices, a couple of databases etc.
- the environment where the tests would be conducted would be locked for a single suite of tests (i.e. nobody else would be able to run the tests in the meantime).
- long to run
- very late feedback
- extremely hard to debug
*Mock other microservices in unit / integration tests*
Advantages:
- very fast feedback
- no infrastructure requirements
Disadvantages:
- the implementor of the service creates stubs thus they might have nothing to do with the reality
- you can go to production with passing tests and failing production
To solve the aforementioned issues Spring Cloud Contract Verifier with Stub Runner were created. Their main idea is to give you very fast feedback, without the need
to set up the whole world of microservices.
image::Stubs1.png[Stubbed Services]
If you work on stubs then the only applications you need are those that your application is using directly.
image::Stubs2.png[Stubbed Services]
Spring Cloud Contract Verifier gives you the certainty that the stubs that you're using were created by the service that you're calling. Also if you can use them it means that they were
tested against the producer's side. In other words - you can trust those stubs.
=== Purposes
The main purposes of Spring Cloud Contract Verifier with Stub Runner are:
- to ensure that WireMock / Messaging stubs (used when developing the client) are doing exactly what actual server-side implementation will do,
- to promote ATDD method and Microservices architectural style,
- to provide a way to publish changes in contracts that are immediately visible on both sides,
- to generate boilerplate test code used on the server side.
=== Client Side
During the tests you want to have a Wiremock instance / Messaging route up and running that simulates the service Y.
You would like to feed that instance with a proper stub definition. That stub definition would need
to be valid and should also be reusable on the server side.
__Summing it up:__ On this side, in the stub definition, you can use patterns for request stubbing and you need exact
values for responses.
=== Server Side
Being a service Y since you are developing your stub, you need to be sure that it's actually resembling your
concrete implementation. You can't have a situation where your stub acts in one way and your application on
production behaves in a different way.
That's why from the provided stub acceptance tests will be generated that will ensure
that your application behaves in the same way as you define in your stub.
__Summing it up:__ On this side, in the stub definition, you need exact values as request and can use patterns/methods
for response verification.
=== Dependencies
Spring Cloud Contract Verifier and Stub Runner are using the following libraries
- http://wiremock.org/[WireMock]
- https://github.com/jayway/JsonPath[Jayway JSONPath]
- https://github.com/marcingrzejszczak/jsonassert[JSONAssert from Marcin Grzejszczak]
=== Additional links
Below you can find some resources related to Spring Cloud Contract Verifier and Stub Runner. Note that some can be outdated since the Spring Cloud Contract Verifier project
is under constant development.
==== Videos
*Olga Maciaszek-Sharma talking about Accurest (Spring Cloud Contract Verifier predecessor)*
video::daafmTYFoDU[youtube]
*Marcin Grzejszczak and Jakub Kubryński talking about Accurest (Spring Cloud Contract Verifier predecessor)*
video::130779882[vimeo]
==== Readings
- http://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura[Slides from Marcin Grzejszczak's talk about Accurest]
- http://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog]
=== Samples
Here you can find some https://github.com/Codearte/accurest-samples[working samples]. Check the readme of each project for more information.
== Documentation
You can read more about Spring Cloud Contract Verifier by reading the {documentation_url}[docs]
== Contributing
Spring Cloud is released under the non-restrictive Apache 2.0 license,
and follows a very standard Github development process, using Github
tracker for issues and merging pull requests into master. If you want
to contribute even something trivial please do not hesitate, but
follow the guidelines below.
=== Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to sign the
https://support.springsource.com/spring_committer_signup[contributor's agreement].
Signing the contributor's agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and you will get an
author credit if we do. Active contributors might be asked to join the core team, and
given the ability to merge pull requests.
=== Code of Conduct
This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of
conduct]. By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.
=== Code Conventions and Housekeeping
None of these is essential for a pull request, but they will all help. They can also be
added after the original pull request but before a merge.
* Use the Spring Framework code format conventions. If you use Eclipse
you can import formatter settings using the
`eclipse-code-formatter.xml` file from the
https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
Cloud Build] project. If using IntelliJ, you can use the
http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
Plugin] to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
`@author` tag identifying you, and preferably at least a paragraph on what the class is
for.
* Add the ASF license header comment to all new `.java` files (copy from existing files
in the project)
* Add yourself as an `@author` to the .java files that you modify substantially (more
than cosmetic changes).
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests would help a lot as well -- someone has to do it.
* If no-one else is using your branch, please rebase it against the current master (or
other target branch in the main project).
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
message (where XXXX is the issue number).

View File

@@ -1,47 +0,0 @@
Accurest
========
[![Build Status](https://travis-ci.org/Codearte/accurest.svg?branch=master)](https://travis-ci.org/Codearte/accurest) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.codearte.accurest/accurest-gradle-plugin/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.codearte.accurest/accurest-gradle-plugin)
[![Join the chat at https://gitter.im/Codearte/accurest](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Codearte/accurest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Consumer Driven Contracts verifier for Java
To make a long story short - Accurest is a tool for Consumer Driven Contract (CDC) development. Accurest ships an easy DSL for describing REST contracts for JVM-based applications.
Since version 1.0.7 it also supports messaging.
The contract DSL is used by Accurest for two things:
1. generating WireMock's JSON stub definitions / stubbed messaging endpoints, allowing rapid development of the consumer side,
generating JUnit / Spock's acceptance tests for the server - to verify if your API implementation is compliant with the contract.
2. moving TDD to an architecture level.
For more information please go to the [Documentation](http://codearte.github.io/accurest/)
## Requirements
### Wiremock
In order to use Accurest with Wiremock you have to have __Wiremock in version at least 2.0.0-beta__ . Of course the higher the better :)
## Additional projects
### Stub Runner
Allows you to download WireMock stubs from the provided Maven repository and runs them in WireMock servers.
### Stub Runner JUnit
Stub Runner with JUnit rules
### Stub Runner Spring
Spring Configuration that automatically starts stubs upon Spring Context build up
### Stub Runner Spring Cloud
Spring Cloud AutoConfiguration that automatically starts stubs upon Spring Context build up and allows you to call the stubs
as if they were registered in your service discovery
### [Accurest Maven Plugin](https://github.com/Codearte/accurest-maven-plugin)
Maven project support with standalone Accurest Stub Runner and Accurest Contracts to Wiremock mappings converter

View File

@@ -1,12 +0,0 @@
package io.codearte.accurest.wiremock
import groovy.transform.CompileStatic
import io.codearte.accurest.AccurestException
@CompileStatic
class ConversionAccurestException extends AccurestException {
ConversionAccurestException(String message, Throwable cause) {
super(message, cause)
}
}

View File

@@ -1,17 +0,0 @@
package io.codearte.accurest.wiremock
import groovy.transform.CompileStatic
import io.codearte.accurest.dsl.WireMockStubStrategy
import io.codearte.accurest.file.Contract
import java.nio.charset.StandardCharsets
@CompileStatic
class DslToWireMockClientConverter extends DslToWireMockConverter {
@Override
String convertContent(String rootName, Contract contract) {
String dslContent = contract.path.getText(StandardCharsets.UTF_8.toString())
return new WireMockStubStrategy(rootName, contract, createGroovyDSLfromStringContent(dslContent)).toWireMockClientStub()
}
}

View File

@@ -1,23 +0,0 @@
package io.codearte.accurest.wiremock
import groovy.transform.CompileStatic
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.util.AccurestDslConverter
@CompileStatic
abstract class DslToWireMockConverter implements SingleFileConverter {
@Override
boolean canHandleFileName(String fileName) {
return fileName.endsWith('.groovy')
}
@Override
String generateOutputFileNameForInput(String inputFileName) {
return inputFileName.replaceAll('.groovy', '.json')
}
protected GroovyDsl createGroovyDSLfromStringContent(String groovyDslAsString) {
return AccurestDslConverter.convert(groovyDslAsString)
}
}

View File

@@ -1,14 +0,0 @@
package io.codearte.accurest.wiremock
import groovy.transform.CompileStatic
import io.codearte.accurest.file.Contract
@CompileStatic
interface SingleFileConverter {
boolean canHandleFileName(String fileName)
String convertContent(String rootName, Contract content)
String generateOutputFileNameForInput(String inputFileName)
}

View File

@@ -1,9 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('POST')
url '/login'
}
response {
status 200
}
}

View File

@@ -1,9 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('GET')
url '/cart'
}
response {
status 200
}
}

View File

@@ -1,9 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('POST')
url '/logout'
}
response {
status 200
}
}

View File

@@ -1,12 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('PUT')
headers {
header 'Content-Type': 'application/json'
}
urlPattern $(client('/[0-9]{2}'), server('/12'))
}
response {
status 200
}
}

View File

@@ -1,12 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('PUT')
headers {
header 'Content-Type': 'application/json'
}
urlPattern $(client('/[0-9]{2}'), server('/12'))
}
response {
status 200
}
}

View File

@@ -1,12 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('PUT')
headers {
header 'Content-Type': 'application/json'
}
urlPattern $(client('/[0-9]{2}'), server('/12'))
}
response {
status 200
}
}

View File

@@ -1,12 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('PUT')
headers {
header 'Content-Type': 'application/json'
}
urlPattern $(client('/[0-9]{2}'), server('/12'))
}
response {
status 200
}
}

View File

@@ -1,15 +0,0 @@
package io.codearte.accurest
/**
* @author Jakub Kubrynski
*/
class AccurestException extends RuntimeException {
AccurestException(String message) {
super(message)
}
AccurestException(String message, Throwable cause) {
super(message, cause)
}
}

View File

@@ -1,65 +0,0 @@
package io.codearte.accurest.builder
import groovy.util.logging.Slf4j
import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.config.TestFramework
import io.codearte.accurest.config.TestMode
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.file.Contract
import io.codearte.accurest.util.NamesUtil
/**
* @author Jakub Kubrynski
*/
@Slf4j
class MethodBuilder {
private final String methodName
private final GroovyDsl stubContent
private final AccurestConfigProperties configProperties
private final boolean ignored
private MethodBuilder(String methodName, GroovyDsl stubContent, AccurestConfigProperties configProperties, boolean ignored) {
this.ignored = ignored
this.stubContent = stubContent
this.methodName = methodName
this.configProperties = configProperties
}
static MethodBuilder createTestMethod(Contract contract, File stubsFile, GroovyDsl stubContent, AccurestConfigProperties configProperties) {
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)
}
void appendTo(BlockBuilder blockBuilder) {
if (configProperties.targetFramework == TestFramework.JUNIT) {
blockBuilder.addLine('@Test')
}
if (ignored) {
blockBuilder.addLine('@Ignore')
}
blockBuilder.addLine(configProperties.targetFramework.methodModifier + "validate_$methodName() throws Exception {")
getMethodBodyBuilder().appendTo(blockBuilder)
blockBuilder.addLine('}')
}
private MethodBodyBuilder getMethodBodyBuilder() {
if (stubContent.input || stubContent.outputMessage) {
if (configProperties.targetFramework == TestFramework.JUNIT){
return new JUnitMessagingMethodBodyBuilder(stubContent)
}
return new SpockMessagingMethodBodyBuilder(stubContent)
}
if (configProperties.testMode == TestMode.MOCKMVC && configProperties.targetFramework == TestFramework.JUNIT){
return new MockMvcJUnitMethodBodyBuilder(stubContent)
}
if (configProperties.testMode == TestMode.JAXRSCLIENT) {
if (configProperties.targetFramework == TestFramework.JUNIT){
return new JaxRsClientJUnitMethodBodyBuilder(stubContent)
}
return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent)
}
return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent)
}
}

View File

@@ -1,46 +0,0 @@
package io.codearte.accurest.builder
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.internal.ExecutionProperty
import io.codearte.accurest.dsl.internal.Header
import java.util.regex.Pattern
/**
* @author Olga Maciaszek-Sharma
* @since 2016-02-17
*/
class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
MockMvcJUnitMethodBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
}
@Override
protected void validateResponseCodeBlock(BlockBuilder bb) {
bb.addLine("assertThat(response.statusCode()).isEqualTo($response.status.serverValue);")
}
@Override
protected void validateResponseHeadersBlock(BlockBuilder bb) {
response.headers?.collect { Header header ->\
processHeaderElement(bb, header.name, header.serverValue)
}
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
blockBuilder.addLine("${exec.insertValue("response.header(\"$property\")")};")
}
}

View File

@@ -1,21 +0,0 @@
package io.codearte.accurest.config
/**
* @author Jakub Kubrynski
*/
enum TestMode {
/**
* Uses Spring's MockMvc
*/
MOCKMVC,
/**
* Uses direct HTTP invocations
*/
EXPLICIT,
/**
* Uses JAX-RS client
*/
JAXRSCLIENT
}

View File

@@ -1,15 +0,0 @@
package io.codearte.accurest.dsl
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
/**
* A better name for GroovyDsl
*
* @author Marcin Grzejszczak
*/
@TypeChecked
@EqualsAndHashCode
@ToString(includeFields = true, includePackage = false, includeNames = true, includeSuper = true)
class Accurest extends GroovyDsl {
}

View File

@@ -1,109 +0,0 @@
package io.codearte.accurest.dsl
import groovy.json.JsonBuilder
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.internal.DslProperty
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.Headers
import io.codearte.accurest.util.ContentType
import io.codearte.accurest.util.ContentUtils
import io.codearte.accurest.util.MapConverter
import java.util.regex.Pattern
import static io.codearte.accurest.util.ContentUtils.extractValue
import static io.codearte.accurest.util.MapConverter.transformValues
@TypeChecked
abstract class BaseWireMockStubStrategy {
protected getStubSideValue(Object object) {
return MapConverter.getStubSideValues(object)
}
private static Closure transform = {
it instanceof DslProperty ? transformValues(it.clientValue, transform) : it
}
protected Map buildClientRequestHeadersSection(Headers headers) {
if (!headers) {
return null
}
return headers.entries.collectEntries { Header entry ->
parseHeader(entry.name, entry.clientValue)
}
}
protected Map buildClientResponseHeadersSection(Headers headers) {
if (!headers) {
return null
}
return headers.entries.collectEntries { Header entry ->
[(entry.name): entry.clientValue]
}
}
protected Map parseHeader(String entryKey, Object entry) {
return [(entryKey): [equalTo: entry]]
}
protected Map parseHeader(String entryKey, String entry) {
return [(entryKey): [equalTo: entry]]
}
protected Map parseHeader(String entryKey, Pattern entry) {
return [(entryKey): [matches: entry.pattern()]]
}
public String parseBody(Object value, ContentType contentType) {
return parseBody(value.toString(), contentType)
}
public Boolean parseBody(Boolean value, ContentType contentType) {
return value
}
public String parseBody(Map map, ContentType contentType) {
def transformedMap = MapConverter.getStubSideValues(map)
return parseBody(toJson(transformedMap), contentType)
}
public String parseBody(List list, ContentType contentType) {
List result = []
list.each {
if (it instanceof Map) {
result += MapConverter.getStubSideValues(it)
} else {
result += parseBody(it, contentType)
}
}
return parseBody(toJson(result), contentType)
}
public String parseBody(GString value, ContentType contentType) {
Object processedValue = extractValue(value, contentType, { DslProperty dslProperty -> dslProperty.clientValue })
if (processedValue instanceof GString) {
return parseBody(processedValue.toString(), contentType)
}
return parseBody(processedValue, contentType)
}
public String parseBody(String value, ContentType contentType) {
return value
}
private static toJson(Object value) {
return new JsonBuilder(value).toString()
}
protected ContentType tryToGetContentType(Object body, Headers headers) {
ContentType contentType = ContentUtils.recognizeContentTypeFromHeader(headers)
if (contentType == ContentType.UNKNOWN) {
if (!body) {
return ContentType.UNKNOWN
}
return ContentUtils.getClientContentType(body)
}
return contentType
}
}

View File

@@ -1,67 +0,0 @@
package io.codearte.accurest.dsl
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.internal.Input
import io.codearte.accurest.dsl.internal.OutputMessage
import io.codearte.accurest.dsl.internal.Request
import io.codearte.accurest.dsl.internal.Response
@TypeChecked
@EqualsAndHashCode
@ToString(includeFields = true, includePackage = false, includeNames = true)
class GroovyDsl {
Integer priority
Request request
Response response
String label
String description
Input input
OutputMessage outputMessage
static GroovyDsl make(Closure closure) {
GroovyDsl dsl = new GroovyDsl()
closure.delegate = dsl
closure()
return dsl
}
void priority(int priority) {
this.priority = priority
}
void label(String label) {
this.label = label
}
void description(String description) {
this.description = description
}
void request(@DelegatesTo(Request) Closure closure) {
this.request = new Request()
closure.delegate = request
closure()
}
void response(@DelegatesTo(Response) Closure closure) {
this.response = new Response()
closure.delegate = response
closure()
}
void input(@DelegatesTo(Input) Closure closure) {
this.input = new Input()
closure.delegate = input
closure()
}
void outputMessage(@DelegatesTo(OutputMessage) Closure closure) {
this.outputMessage = new OutputMessage()
closure.delegate = outputMessage
closure()
}
}

View File

@@ -1,11 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
@CompileStatic
class ClientDslProperty extends DslProperty {
ClientDslProperty(Object singleValue) {
super(singleValue)
}
}

View File

@@ -1,24 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false, includeNames = true)
class DslProperty<T> {
final T clientValue
final T serverValue
DslProperty(T clientValue, T serverValue) {
this.clientValue = clientValue
this.serverValue = serverValue
}
DslProperty(T singleValue) {
this.clientValue = singleValue
this.serverValue = singleValue
}
}

View File

@@ -1,19 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
@CompileStatic
class ExecutionProperty {
private static final String PLACEHOLDER_VALUE = '\\$it'
final String executionCommand
ExecutionProperty(String executionCommand) {
this.executionCommand = executionCommand
}
String insertValue(String valueToInsert) {
return executionCommand.replaceAll(PLACEHOLDER_VALUE, valueToInsert)
}
}

View File

@@ -1,23 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false, includeFields = true, ignoreNulls = true, includeNames = true)
@CompileStatic
class Header extends DslProperty {
String name
Header(String name, DslProperty dslProperty) {
super(dslProperty.clientValue, dslProperty.serverValue)
this.name = name
}
Header(String name, Object value) {
super(value)
this.name = name
}
}

View File

@@ -1,5 +0,0 @@
package io.codearte.accurest.dsl.internal
enum JSONCompareMode {
STRICT, LENIENT, NON_EXTENSIBLE, STRICT_ORDER
}

View File

@@ -1,32 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.json.JsonOutput
import groovy.transform.CompileStatic
import io.codearte.accurest.util.MapConverter
import java.util.regex.Pattern
@CompileStatic
class JsonStructureConverter {
public static final String TEMPORARY_PLACEHOLDER = '###PLACEHOLDER###'
public static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile(TEMPORARY_PLACEHOLDER)
static Object convertJsonStructureToObjectUnderstandingStructure(Object parsedJson,
Closure<Boolean> retrievePlaceholders,
Closure<String> performAdditionalLogicOnSerializedJson,
Closure convertSerializedJsonToSth) {
LinkedList<Object> queue = new LinkedList<>()
def transformedJson = MapConverter.transformValues(parsedJson, {
if(retrievePlaceholders(it)) {
queue.push(it)
return TEMPORARY_PLACEHOLDER
}
return it
})
String jsonAsString = JsonOutput.toJson(transformedJson)
String transformedJsonAsString = performAdditionalLogicOnSerializedJson(jsonAsString)
return convertSerializedJsonToSth(queue, transformedJsonAsString)
}
}

View File

@@ -1,25 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@ToString(includePackage = false, includeFields = true, includeNames = true)
@EqualsAndHashCode(includeFields = true)
@CompileStatic
class NamedProperty {
private static final String NAME = 'name'
private static final String CONTENT = 'content'
DslProperty name
DslProperty value
NamedProperty(DslProperty name, DslProperty value) {
this.name = name
this.value = value
}
NamedProperty(Map<String, DslProperty> namedMap) {
this(namedMap?.get(NAME), namedMap?.get(CONTENT))
}
}

View File

@@ -1,13 +0,0 @@
package io.codearte.accurest.dsl.internal
class OptionalProperty {
final Object value
OptionalProperty(Object value) {
this.value = value
}
String optionalPattern() {
return "($value)?"
}
}

View File

@@ -1,23 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false, includeFields = true, ignoreNulls = true, includeNames = true)
@TypeChecked
class QueryParameters {
List<QueryParameter> parameters = []
void parameter(Map<String, Object> singleParameter) {
Map.Entry<String, Object> first = singleParameter.entrySet().first()
parameters << new QueryParameter(first?.key, first?.value)
}
void parameter(String parameterName, Object parameterValue) {
parameters << new QueryParameter(parameterName, parameterValue)
}
}

View File

@@ -1,15 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class ServerDslProperty extends DslProperty {
ServerDslProperty(Object singleValue) {
super(singleValue)
}
}

View File

@@ -1,32 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import static io.codearte.accurest.util.ValidateUtils.validateServerValueIsAvailable
@ToString(includePackage = false, includeFields = true, includeNames = true)
@EqualsAndHashCode(includeFields = true)
@CompileStatic
class Url extends DslProperty {
QueryParameters queryParameters
Url(DslProperty prop) {
super(prop.clientValue, prop.serverValue)
validateServerValueIsAvailable(prop.serverValue, "Url")
}
Url(Object url) {
super(url)
validateServerValueIsAvailable(url, "Url")
}
void queryParameters(@DelegatesTo(QueryParameters) Closure closure) {
this.queryParameters = new QueryParameters()
closure.delegate = queryParameters
closure()
}
}

View File

@@ -1,20 +0,0 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@ToString(includePackage = false, includeFields = true, includeNames = true)
@EqualsAndHashCode(includeFields = true)
@CompileStatic
class UrlPath extends Url {
UrlPath(String path) {
super(path)
}
UrlPath(DslProperty path) {
super(path)
}
}

View File

@@ -1,30 +0,0 @@
package io.codearte.accurest.file
import java.nio.file.Path
/**
* @author Jakub Kubrynski
*/
class Contract {
final Path path;
final boolean ignored;
final int groupSize
final Integer order;
Contract(Path path, boolean ignored, int groupSize, Integer order) {
this.groupSize = groupSize
this.path = path
this.ignored = ignored
this.order = order
}
@Override
public String toString() {
return "Contract{" +
"fileName=" + path.fileName +
", ignored=" + ignored +
", groupSize=" + groupSize +
", order=" + order +
'}';
}
}

View File

@@ -1,26 +0,0 @@
package io.codearte.accurest.util
import groovy.transform.CompileStatic
import io.codearte.accurest.dsl.GroovyDsl
import org.codehaus.groovy.control.CompilerConfiguration
/**
* Converts to Groovy DSL
*
* @author Marcin Grzejszczak
*/
@CompileStatic
class AccurestDslConverter {
static GroovyDsl convert(String dsl) {
return groovyShell().evaluate(dsl) as GroovyDsl
}
static GroovyDsl convert(File dsl) {
return groovyShell().evaluate(dsl) as GroovyDsl
}
private static GroovyShell groovyShell() {
return new GroovyShell(AccurestDslConverter.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding: 'UTF-8'))
}
}

View File

@@ -1,15 +0,0 @@
package io.codearte.accurest.util
enum ContentType {
JSON("application/json"),
XML("application/xml"),
UNKNOWN("application/octet-stream")
final String mimeType
ContentType(String mimeType) {
this.mimeType = mimeType
}
}

View File

@@ -1,17 +0,0 @@
package io.codearte.accurest.util;
import java.util.LinkedList;
import com.toomuchcoding.jsonassert.JsonVerifiable;
/**
* @author Marcin Grzejszczak
*/
class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
FinishedDelegatingJsonVerifiable(JsonVerifiable delegate,
LinkedList<String> methodsBuffer) {
super(delegate, methodsBuffer);
}
}

View File

@@ -1,6 +0,0 @@
package io.codearte.accurest.util
class JsonPaths extends HashSet<MethodBufferingJsonVerifiable> {
}

View File

@@ -1,9 +0,0 @@
package io.codearte.accurest.util;
/**
* @author Marcin Grzejszczak
*/
public interface MethodBuffering {
String method();
}

View File

@@ -1,60 +0,0 @@
package io.codearte.accurest.util
/**
* @author Jakub Kubrynski
*/
class NamesUtil {
static String beforeLast(String string, String separator) {
if (string?.indexOf(separator) > -1) {
return string.substring(0, string.lastIndexOf(separator))
}
return ''
}
static String afterLast(String string, String separator) {
if (string?.indexOf(separator) > -1) {
return string.substring(string.lastIndexOf(separator) + 1)
}
return string
}
static String afterLastDot(String string) {
return afterLast(string, '.')
}
static String camelCase(String className) {
if (!className) {
return className
}
String firstChar = className.charAt(0).toLowerCase() as String
return firstChar + className.substring(1)
}
static String capitalize(String className) {
if (!className) {
return className
}
String firstChar = className.charAt(0).toUpperCase() as String
return firstChar + className.substring(1)
}
static String toLastDot(String string) {
if (string?.indexOf('.') > -1) {
return string.substring(0, string.lastIndexOf('.'))
}
return string
}
static String packageToDirectory(String packageName) {
return packageName.replace('.' as char, File.separatorChar)
}
static String directoryToPackage(String directory) {
return directory.replace(File.separator, '.')
}
static String convertIllegalPackageChars(String packageName) {
return packageName.replace('-', '_')
}
}

View File

@@ -1,91 +0,0 @@
package io.codearte.accurest.util
import io.codearte.accurest.dsl.internal.DslProperty
import org.codehaus.groovy.runtime.GStringImpl
import java.util.regex.Pattern
import static io.codearte.accurest.util.ContentUtils.extractValue
import static org.apache.commons.lang3.StringEscapeUtils.escapeJson
public class RegexpBuilders {
public static String buildGStringRegexpForStubSide(GString gString) {
new GStringImpl(
gString.values.collect(this.&buildGStringRegexpForStubSide) as Object[],
gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
)
}
public static String buildGStringRegexpForStubSide(Pattern pattern) {
return pattern.pattern()
}
public static String buildGStringRegexpForStubSide(DslProperty dslProperty) {
return buildGStringRegexpForStubSide(dslProperty.clientValue)
}
public static String buildGStringRegexpForStubSide(Object o) {
return escapeSpecialRegexChars(o.toString())
}
public static String buildGStringRegexpForTestSide(GString gString) {
new GStringImpl(
gString.values.collect(this.&buildGStringRegexpForTestSide) as Object[],
gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
)
}
public static String buildGStringRegexpForTestSide(Pattern pattern) {
return pattern.pattern()
}
public static String buildGStringRegexpForTestSide(DslProperty dslProperty) {
return buildGStringRegexpForTestSide(dslProperty.clientValue)
}
public static String buildGStringRegexpForTestSide(Object o) {
return o.toString().replaceAll('\\\\', '\\\\\\\\')
}
private final static Pattern SPECIAL_REGEX_CHARS = Pattern.compile('[{}()\\[\\].+*?^$\\\\|]')
private static String escapeSpecialRegexChars(String str) {
return SPECIAL_REGEX_CHARS.matcher(str).replaceAll('\\\\\\\\$0')
}
private final static String WS = /\s*/
public static String buildJSONRegexpMatch(GString gString) {
return buildJSONRegexpMatch(extractValue(gString, ContentType.JSON, { DslProperty dslProperty -> dslProperty.clientValue }))
}
public static String buildJSONRegexpMatch(Map jsonMap) {
return WS + "\\{" + jsonMap.collect(this.&buildJSONRegexpMatch).join(",") + "\\}" + WS
}
public static String buildJSONRegexpMatch(List jsonList) {
return WS + "\\[" + jsonList.collect(this.&buildJSONRegexpMatch).join(",") + "\\]" + WS
}
public static String buildJSONRegexpMatch(Map.Entry<String, Object> entry) {
return buildJSONRegexpMatchString(escapeJson(entry.key)) + ":" + buildJSONRegexpMatch(entry.value)
}
public static String buildJSONRegexpMatch(Object value) {
return buildJSONRegexpMatchStringOptionalQuotes(escapeJson(value.toString()))
}
public static String buildJSONRegexpMatch(Pattern pattern) {
return buildJSONRegexpMatchStringOptionalQuotes(pattern.pattern())
}
public static String buildJSONRegexpMatchString(String value) {
return WS + '"' + value + '"' + WS
}
public static String buildJSONRegexpMatchStringOptionalQuotes(String value) {
return WS + '"?' + value + '"?' + WS
}
}

View File

@@ -1,12 +0,0 @@
package io.codearte.accurest.util;
/**
* @author Marcin Grzejszczak
*/
class ShouldTraverse {
final Object value;
ShouldTraverse(Object value) {
this.value = value;
}
}

View File

@@ -1,46 +0,0 @@
package io.codearte.accurest.util
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.internal.DslProperty
import io.codearte.accurest.dsl.internal.MatchingStrategy
import java.util.regex.Pattern
import static io.codearte.accurest.dsl.internal.MatchingStrategy.Type.ABSENT
import static io.codearte.accurest.dsl.internal.MatchingStrategy.Type.EQUAL_TO
@TypeChecked
class ValidateUtils {
static Object validateServerValueIsAvailable(Object value) {
validateServerValueIsAvailable(value, "Server value")
return value
}
static Object validateServerValueIsAvailable(Object value, String msg) {
validateServerValue(value, msg)
return value
}
static void validateServerValue(Pattern pattern, String msg) {
throw new IllegalStateException("$msg can't be a pattern for the server side")
}
static List ALLOWED_MATCHING_TYPES_ON_SERVER_SIDE = [EQUAL_TO, ABSENT]
static void validateServerValue(MatchingStrategy matchingStrategy, String msg) {
if (!ALLOWED_MATCHING_TYPES_ON_SERVER_SIDE.contains(matchingStrategy.type)) {
throw new IllegalStateException("$msg can't be of a matching type: $matchingStrategy.type for the server side")
}
validateServerValue(matchingStrategy.serverValue, msg)
}
static void validateServerValue(DslProperty value, String msg) {
validateServerValue(value.serverValue, msg)
}
static void validateServerValue(Object value, String msg) {
// OK
}
}

View File

@@ -1,36 +0,0 @@
package io.codearte.accurest
import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.config.TestFramework
import spock.lang.Specification
class GeneratorScannerSpec extends Specification {
private SingleTestGenerator classGenerator = Mock(SingleTestGenerator)
def "should find all .json files and generate 6 classes for them"() {
given:
File resource = new File(this.getClass().getResource("/directory/with/stubs/stubsRepositoryIndicator").toURI())
AccurestConfigProperties properties = new AccurestConfigProperties()
properties.contractsDslDir = resource.parentFile
TestGenerator testGenerator = new TestGenerator(properties, classGenerator, Stub(FileSaver))
when:
testGenerator.generateTestClasses("com.ofg")
then:
6 * classGenerator.buildClass(_, _, _) >> "qwerty"
}
def "should create class with full package"() {
given:
AccurestConfigProperties properties = new AccurestConfigProperties(targetFramework: TestFramework.SPOCK)
properties.contractsDslDir = new File(this.getClass().getResource("/directory/with/stubs/package").toURI())
TestGenerator testGenerator = new TestGenerator(properties, classGenerator, Stub(FileSaver))
when:
testGenerator.generateTestClasses("com.ofg")
then:
1 * classGenerator.buildClass(_, 'exceptionsSpec', 'com.ofg') >> "spec"
1 * classGenerator.buildClass(_, 'exceptionsSpec', 'com.ofg.v1') >> "spec1"
1 * classGenerator.buildClass(_, 'exceptionsSpec', 'com.ofg.v2') >> "spec2"
}
}

View File

@@ -1,16 +0,0 @@
package io.codearte.accurest
import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.config.TestFramework
import io.codearte.accurest.config.TestMode
class MainTest {
public static void main(String[] args) {
AccurestConfigProperties properties = new AccurestConfigProperties(
contractsDslDir: new File('/home/devel/projects/codearte/accurest/accurest-core/src/test/resources/dsl'),
generatedTestSourcesDir: new File('/tmp/accurest'),
targetFramework: TestFramework.SPOCK, testMode: TestMode.MOCKMVC, basePackageForTests: 'io.test',
staticImports: ['com.pupablada.Test.*'], imports: ['org.innapypa.Test'], excludedFiles: ["**/other"])
println new TestGenerator(properties).generate()
}
}

View File

@@ -1,14 +0,0 @@
package io.codearte.accurest.builder
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned implements Serializable {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -1,22 +0,0 @@
package io.codearte.accurest.dsl
import com.github.tomakehurst.wiremock.stubbing.StubMapping
import io.codearte.accurest.file.Contract
import java.util.regex.Pattern
trait WireMockStubVerifier {
void stubMappingIsValidWireMockStub(String mappingDefinition) {
StubMapping stubMapping = StubMapping.buildFrom(mappingDefinition)
stubMapping.request.bodyPatterns.findAll { it.matches }.every {
Pattern.compile(it.matches)
}
assert !mappingDefinition.contains('io.codearte.accurest.dsl.internal')
}
void stubMappingIsValidWireMockStub(GroovyDsl contractDsl) {
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
}

View File

@@ -1,19 +0,0 @@
package io.codearte.accurest.dsl.internal
import spock.lang.Specification
class ExecutionPropertySpec extends Specification {
def 'should insert passed value in place of $it placeholder'() {
given:
String commandToExecute = 'commandToExecute($it)'
ExecutionProperty executionProperty = new ExecutionProperty(commandToExecute)
and:
String valueToInsert = 'someObject.itsValue'
when:
String commandWithInsertedValue = executionProperty.insertValue(valueToInsert)
then:
'commandToExecute(someObject.itsValue)' == commandWithInsertedValue
}
}

View File

@@ -1,30 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method('PUT')
headers {
header 'Content-Type': 'application/json'
}
body("""\
{
"name": "Jan",
"id": "${value(client('abc'), server('def'))}",
}
"""
)
url $(client('/[0-9]{2}'), server('/12'))
}
response {
status 200
body("""\
{
"name": "Jan",
"id": "${value(client('123'), server('321'))}",
"surname": "${value(client('Kowalsky'), server('$checkIfSurnameValid($value)'))}"
}
"""
)
headers {
header 'Content-Type': 'text/plain'
}
}
}

View File

@@ -1,89 +0,0 @@
package io.codearte.accurest.plugin
import io.codearte.accurest.config.AccurestConfigProperties
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
/**
* @author Jakub Kubrynski
*/
class AccurestGradlePlugin implements Plugin<Project> {
private static final String GENERATE_SERVER_TESTS_TASK_NAME = 'generateAccurest'
private static final String DSL_TO_WIREMOCK_CLIENT_TASK_NAME = 'generateWireMockClientStubs'
private static final Class IDEA_PLUGIN_CLASS = org.gradle.plugins.ide.idea.IdeaPlugin
private static final String GROUP_NAME = "Verification"
private Project project
@Override
void apply(Project project) {
this.project = project
AccurestConfigProperties extension = project.extensions.create('accurest', AccurestConfigProperties)
project.check.dependsOn(GENERATE_SERVER_TESTS_TASK_NAME)
setConfigurationDefaults(extension)
createGenerateTestsTask(extension)
createAndConfigureGenerateWireMockClientStubsFromDslTask(extension)
deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask()
project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.0.10-beta")
project.dependencies.add("testCompile", "com.toomuchcoding.jsonassert:jsonassert:${extension.getJsonAssertVersion()}")
project.dependencies.add("testCompile", "org.assertj:assertj-core:2.3.0")
project.afterEvaluate {
def hasIdea = project.plugins.findPlugin(IDEA_PLUGIN_CLASS)
if (hasIdea) {
project.idea {
module {
testSourceDirs += extension.generatedTestSourcesDir
testSourceDirs += extension.contractsDslDir
}
}
}
}
}
void setConfigurationDefaults(AccurestConfigProperties extension) {
extension.with {
generatedTestSourcesDir = project.file("${project.buildDir}/generated-test-sources/accurest")
contractsDslDir = defaultAccurestContractsDir() //TODO: Use sourceset
basePackageForTests = 'io.codearte.accurest.tests'
}
}
private File defaultAccurestContractsDir() {
project.file("${project.rootDir}/src/test/resources/accurest")
}
private void createGenerateTestsTask(AccurestConfigProperties extension) {
Task task = project.tasks.create(GENERATE_SERVER_TESTS_TASK_NAME, GenerateServerTestsTask)
task.description = "Generate server tests from GroovyDSL"
task.group = GROUP_NAME
task.conventionMapping.with {
contractsDslDir = { extension.contractsDslDir }
generatedTestSourcesDir = { extension.generatedTestSourcesDir }
configProperties = { extension }
}
}
private void createAndConfigureGenerateWireMockClientStubsFromDslTask(AccurestConfigProperties extension) {
Task task = project.tasks.create(DSL_TO_WIREMOCK_CLIENT_TASK_NAME, GenerateWireMockClientStubsFromDslTask)
task.description = "Generate WireMock client stubs from GroovyDSL"
task.group = GROUP_NAME
task.conventionMapping.with {
contractsDslDir = { extension.contractsDslDir }
stubsOutputDir = { extension.stubsOutputDir }
configProperties = { extension }
}
}
private void deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask() {
Task task = project.tasks.create('generateWiremockClientStubs')
task.dependsOn('generateWireMockClientStubs')
task.description = "DEPRECATED - Generates WireMock client stubs. - DEPRECATED - use 'generateWireMockClientStubs' task"
task.group = GROUP_NAME
task.doFirst {logger.warn("DEPRECATION WARNING. Task 'generateWiremockClientStubs' is deprecated. Use 'generateWireMockClientStubs' task instead.")}
}
}

View File

@@ -1,40 +0,0 @@
package io.codearte.accurest.plugin
import io.codearte.accurest.AccurestException
import io.codearte.accurest.TestGenerator
import io.codearte.accurest.config.AccurestConfigProperties
import org.gradle.api.GradleException
import org.gradle.api.internal.ConventionTask
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
class GenerateServerTestsTask extends ConventionTask {
@InputDirectory
File contractsDslDir
@OutputDirectory
File generatedTestSourcesDir
//TODO: How to deal with @Input*, @Output* and that domain object?
AccurestConfigProperties configProperties
@TaskAction
void generate() {
project.logger.info("Accurest Plugin: Invoking test sources generation")
project.sourceSets.test.groovy {
project.logger.info("Registering ${getConfigProperties().generatedTestSourcesDir} as test source directory")
srcDir getConfigProperties().generatedTestSourcesDir
}
try {
//TODO: What with that? How to pass?
TestGenerator generator = new TestGenerator(getConfigProperties())
int generatedClasses = generator.generate()
project.logger.info("Generated {} test classes", generatedClasses)
} catch (AccurestException e) {
throw new GradleException("Accurest Plugin exception: ${e.message}", e)
}
}
}

View File

@@ -1,28 +0,0 @@
package io.codearte.accurest.plugin
import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.wiremock.DslToWireMockClientConverter
import io.codearte.accurest.wiremock.RecursiveFilesConverter
import org.gradle.api.internal.ConventionTask
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
//TODO: Implement as an incremental task: https://gradle.org/docs/current/userguide/custom_tasks.html#incremental_tasks ?
class GenerateWireMockClientStubsFromDslTask extends ConventionTask {
@InputDirectory
File contractsDslDir
@OutputDirectory
File stubsOutputDir
AccurestConfigProperties configProperties
@TaskAction
void generate() {
logger.info("Accurest Plugin: Invoking GroovyDSL to WireMock client stubs conversion")
logger.debug("From '${getContractsDslDir()}' to '${getStubsOutputDir()}'")
RecursiveFilesConverter converter = new RecursiveFilesConverter(new DslToWireMockClientConverter(), getConfigProperties())
converter.processFiles()
}
}

View File

@@ -1 +0,0 @@
implementation-class=io.codearte.accurest.plugin.AccurestGradlePlugin

View File

@@ -1,22 +0,0 @@
package io.codearte.accurest.plugin
import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Ignore
import spock.lang.Specification
/**
* @author Jakub Kubrynski
*/
@Ignore
class AccurestGradlePluginTest extends Specification {
def void greeterPluginAddsGreetingTaskToProject() {
when:
Project project = ProjectBuilder.builder().build()
project.apply plugin: 'accurest'
then:
project.tasks.generateAccurest
}
}

View File

@@ -1,31 +0,0 @@
package io.codearte.accurest.plugin
import spock.lang.Stepwise
@Stepwise
class MessagingProjectSpec extends AccurestIntegrationSpec {
def setup() {
setupForProject("functionalTest/messagingProject")
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('build/libs')
}
def "should pass basic flow for JUnit"() {
given:
runTasksSuccessfully('clean')
assert fileExists('build.gradle')
expect:
switchToJunitTestFramework('io.codearte.accurest.samples.book.MessagingBaseSpec', 'io.codearte.accurest.samples.book.MessagingBaseTest')
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('build/libs')
}
}

View File

@@ -1,30 +0,0 @@
package io.codearte.accurest.plugin
import spock.lang.Stepwise
@Stepwise
class SampleJerseyProjectSpec extends AccurestIntegrationSpec {
def setup() {
setupForProject("functionalTest/sampleJerseyProject")
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('fraudDetectionService/build/libs')
}
def "should pass basic flow for JUnit"() {
given:
switchToJunitTestFramework()
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('fraudDetectionService/build/libs')
}
}

View File

@@ -1,30 +0,0 @@
package io.codearte.accurest.plugin
import spock.lang.Stepwise
@Stepwise
class SampleProjectSpec extends AccurestIntegrationSpec {
def setup() {
setupForProject("functionalTest/sampleProject")
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('fraudDetectionService/build/libs')
}
def "should pass basic flow for JUnit"() {
given:
switchToJunitTestFramework()
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('fraudDetectionService/build/libs')
}
}

View File

@@ -1,30 +0,0 @@
package io.codearte.accurest.plugin
import spock.lang.Stepwise
@Stepwise
class ScenarioProjectSpec extends AccurestIntegrationSpec {
def setup() {
setupForProject("functionalTest/scenarioProject")
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('fraudDetectionService/build/libs')
}
def "should pass basic flow for JUnit"() {
given:
assert fileExists('build.gradle')
expect:
switchToJunitTestFramework()
runTasksSuccessfully('check', "publishToMavenLocal")
jarContainsAccurestContracts('fraudDetectionService/build/libs')
}
}

View File

@@ -1,6 +0,0 @@
groupId=com.ofg
jacksonMapper=1.9.13
restAssuredVersion=2.4.0
springVersion=4.1.7.RELEASE
springBootVersion=1.3.3.RELEASE

View File

@@ -1,6 +0,0 @@
#Sat Feb 21 20:13:29 CET 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip

View File

@@ -1,18 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
priority 2
request {
method 'PUT'
url '/api/12'
headers {
header 'Content-Type': 'application/json'
}
body '''\
[{
"text": "Gonna see you at Warsaw"
}]
'''
}
response {
status 200
}
}

View File

@@ -1,25 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method 'PUT'
url $(client(regex('^/api/[0-9]{2}$')), server('/api/12'))
headers {
header 'Content-Type': 'application/json'
}
body '''\
[{
"text": "Gonna see you at Warsaw"
}]
'''
}
response {
headers {
header 'Content-Type': $(client('application/json'), server(regex('application/json.*')))
header 'Location': $(client('https://localhost:8080'), server(execute('isEmpty($it)')))
}
body (
path: $(client('/api/12'), server(regex('^/api/[0-9]{2}$'))),
correlationId: $(client('1223456'), server(execute('isProperCorrelationId($it)')))
)
status 200
}
}

View File

@@ -1 +0,0 @@
rootProject.name='bootSimple'

View File

@@ -1,23 +0,0 @@
package com.ofg.twitter.places
import com.ofg.twitter.place.PairIdController
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import spock.lang.Specification
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
class AcceptanceSpec extends Specification {
def "should have controller up and running"() {
given:
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new PairIdController()).build()
expect:
mockMvc.perform(put("/api/${1}").
contentType(MediaType.APPLICATION_JSON).
content("""[{"text":"Gonna see you at Warsaw"}]""")).
andExpect(status().isOk())
}
}

View File

@@ -1,23 +0,0 @@
package com.ofg.twitter.places
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
import com.ofg.twitter.place.PairIdController
import spock.lang.Specification
// tag::base_class[]
abstract class BaseMockMvcSpec extends Specification {
def setup() {
RestAssuredMockMvc.standaloneSetup(new PairIdController())
}
void isProperCorrelationId(Integer correlationId) {
assert correlationId == 123456
}
void isEmpty(String value) {
assert value == null
}
}
// end::base_class[]

View File

@@ -1,14 +0,0 @@
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.ConsoleAppender
String console = "CONSOLE"
String logPattern = "%d{yyyy-MM-dd HH:mm:ss.SSSZ, Europe/Warsaw} | %-5level | %X{correlationId} | %thread | %logger{1} | %m%n"
appender(console, ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = logPattern
}
}
root(INFO, [console])
logger("com.ofg", DEBUG)

View File

@@ -1,6 +0,0 @@
groupId=io.codearte
jacksonMapper=1.9.13
restAssuredVersion=2.9.0
springVersion=4.2.3.RELEASE
springBootVersion=1.3.3.RELEASE

View File

@@ -1,6 +0,0 @@
#Sun Apr 17 20:31:11 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip

View File

@@ -1,10 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
url '/foo'
method 'GET'
}
response {
status 200
body 'bar'
}
}

View File

@@ -1,13 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
label 'some_label'
input {
messageFrom('delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}

View File

@@ -1,13 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}

View File

@@ -1,21 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
label 'some_label'
input {
messageFrom('input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}

View File

@@ -1,14 +0,0 @@
package io.codearte.accurest.samples.book
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookDeleted {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookDeleted(String bookName) {
this.bookName = bookName
}
}

View File

@@ -1,14 +0,0 @@
package io.codearte.accurest.samples.book
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -1,22 +0,0 @@
package io.codearte.accurest.samples.book
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ImportResource
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@SpringBootApplication
@RestController
@ImportResource("classpath*:integration-context.xml")
class IntegrationMessagingApplication {
@RequestMapping("/foo")
String foo() {
return "bar"
}
static void main(String[] args) {
SpringApplication.run(IntegrationMessagingApplication.class, args)
}
}

View File

@@ -1,27 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method """PUT"""
url """/fraudcheck"""
body("""
{
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
"loanAmount":99999}
"""
)
headers {
header("""Content-Type""", """application/vnd.fraud.v1+json""")
}
}
response {
status 200
body( """{
"fraudCheckStatus": "${value(client('FRAUD'), server(regex('[A-Z]{5}')))}",
"rejectionReason": "Amount too high"
}""")
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}

View File

@@ -1,28 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method 'PUT'
url '/fraudcheck'
body("""
{
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
"loanAmount":123.123
}
"""
)
headers {
header('Content-Type', 'application/vnd.fraud.v1+json')
}
}
response {
status 200
body(
fraudCheckStatus: "OK",
rejectionReason: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
)
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}

View File

@@ -1,5 +0,0 @@
package com.blogspot.toomuchcoding.frauddetection.model;
public enum FraudCheckStatus {
OK, FRAUD
}

View File

@@ -1,6 +0,0 @@
#Wed Jan 28 00:32:44 CET 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip

View File

@@ -1,14 +0,0 @@
package com.blogspot.toomuchcoding.frauddetection.model;
public class Client {
private String pesel;
public String getPesel() {
return pesel;
}
public void setPesel(String pesel) {
this.pesel = pesel;
}
}

View File

@@ -1,5 +0,0 @@
package com.blogspot.toomuchcoding.frauddetection.model;
public enum FraudCheckStatus {
OK, FRAUD
}

View File

@@ -1,34 +0,0 @@
package com.blogspot.toomuchcoding.frauddetection.model;
import java.math.BigDecimal;
public class FraudServiceRequest {
private String clientPesel;
private BigDecimal loanAmount;
public FraudServiceRequest() {
}
public FraudServiceRequest(LoanApplication loanApplication) {
this.clientPesel = loanApplication.getClient().getPesel();
this.loanAmount = loanApplication.getAmount();
}
public String getClientPesel() {
return clientPesel;
}
public void setClientPesel(String clientPesel) {
this.clientPesel = clientPesel;
}
public BigDecimal getLoanAmount() {
return loanAmount;
}
public void setLoanAmount(BigDecimal loanAmount) {
this.loanAmount = loanAmount;
}
}

View File

@@ -1,36 +0,0 @@
package com.blogspot.toomuchcoding.frauddetection.model;
import java.math.BigDecimal;
public class LoanApplication {
private Client client;
private BigDecimal amount;
private String loanApplicationId;
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getLoanApplicationId() {
return loanApplicationId;
}
public void setLoanApplicationId(String loanApplicationId) {
this.loanApplicationId = loanApplicationId;
}
}

View File

@@ -1,2 +0,0 @@
include ':fraudDetectionService'
include ':loanApplicationService'

View File

@@ -1,27 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method """PUT"""
url """/fraudcheck"""
body("""
{
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
"loanAmount":99999}
"""
)
headers {
header("""Content-Type""", """application/vnd.fraud.v1+json""")
}
}
response {
status 200
body( """{
"fraudCheckStatus": "${value(client('FRAUD'), server(regex('[A-Z]{5}')))}",
"rejectionReason": "Amount too high"
}""")
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}

View File

@@ -1,28 +0,0 @@
io.codearte.accurest.dsl.GroovyDsl.make {
request {
method 'PUT'
url '/fraudcheck'
body("""
{
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
"loanAmount":123.123
}
"""
)
headers {
header('Content-Type', 'application/vnd.fraud.v1+json')
}
}
response {
status 200
body(
fraudCheckStatus: "OK",
rejectionReason: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
)
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}

Some files were not shown because too many files have changed in this diff Show More