Skip to content

Commit d841052

Browse files
openapi: lazy init; relative http spec url (#808)
1 parent c79e70a commit d841052

17 files changed

Lines changed: 244 additions & 53 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2021 webtau maintainers
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package listeners
18+
19+
import org.testingisdocumenting.webtau.cli.CliBackgroundCommand
20+
import org.testingisdocumenting.webtau.reporter.TestListener
21+
import org.testingisdocumenting.webtau.utils.RegexpUtils
22+
import org.testingisdocumenting.webtau.version.WebtauVersion
23+
24+
import static org.testingisdocumenting.webtau.WebTauGroovyDsl.*
25+
26+
class ServerAutoStartListener implements TestListener {
27+
CliBackgroundCommand server
28+
29+
@Override
30+
void beforeFirstTest() {
31+
def jarName = "webtau-testapp-${WebtauVersion.version}-exec.jar"
32+
server = cli.runInBackground("java -jar ../webtau-testapp/target/${jarName} --server.port=0 --spring.profiles.active=qa")
33+
server.output.waitTo(contain("Tomcat started on port(s)"), 10_000)
34+
35+
def port = RegexpUtils.extractByRegexp(server.output.get(), /Tomcat started on port\(s\): (\d+)/)
36+
cfg.baseUrl = "http://localhost:${port}"
37+
}
38+
39+
@Override
40+
void afterAllTests() {
41+
if (server) {
42+
server.stop()
43+
}
44+
}
45+
}

webtau-feature-testing/examples/scenarios/rest/openapi/openApiHttpSpec.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ import static org.testingisdocumenting.webtau.WebTauGroovyDsl.*
44

55
scenario("open api validation") {
66
http.post("/employee", [firstName: 'First']) {
7-
// ...
7+
statusCode.shouldBe > 0
88
}
99
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2021 webtau maintainers
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package scenarios.rest.springboot
18+
19+
import static org.testingisdocumenting.webtau.WebTauGroovyDsl.*
20+
21+
scenario("list customers on started server as part of listeners") {
22+
http.get("/customers") {
23+
body.should == []
24+
}
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package scenarios.rest.springboot
2+
3+
import listeners.ServerAutoStartListener
4+
5+
testListeners = [ServerAutoStartListener]
6+
7+
openApiSpecUrl = "/v3/api-docs"

webtau-feature-testing/src/test/groovy/org/testingisdocumenting/webtau/featuretesting/WebTauRestFeaturesTest.groovy

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ class WebTauRestFeaturesTest {
100100
@Test
101101
void "open api http spec"() {
102102
runCli('openapi/openApiHttpSpec.groovy', 'openapi/webtau.httpspec.cfg.groovy',
103-
"--url=${testRunner.testServer.uri}",
104-
"--openApiSpecUrl=${testRunner.testServer.uri}/v3/api-docs")
103+
"--url=${customersBaseUrl}",
104+
"--openApiSpecUrl=/v3/api-docs")
105105
}
106106

107107
@Test
@@ -137,7 +137,10 @@ class WebTauRestFeaturesTest {
137137

138138
@Test
139139
void "list contain"() {
140-
http.post(customersUrl(), [firstName: 'FN1', lastName: 'LN1'])
140+
OpenApi.withoutValidation {
141+
http.post(customersUrl(), [firstName: 'FN1', lastName: 'LN1'])
142+
}
143+
141144
runCli('springboot/listContain.groovy', 'springboot/webtau.cfg.groovy', "--url=$customersBaseUrl")
142145
}
143146

@@ -153,6 +156,11 @@ class WebTauRestFeaturesTest {
153156
runCli('springboot/listMatchByKey.groovy', 'springboot/webtau.cfg.groovy', "--url=$customersBaseUrl")
154157
}
155158

159+
@Test
160+
void "start server before first test and stop after"() {
161+
runCli("springboot/startAndStopAsPartOfSuite.groovy", "springboot/webtau-auto-start.groovy")
162+
}
163+
156164
@Test
157165
void "recursive scenario discovery"() {
158166
testRunner.runCli("recursive/scenarios", "urlOnly.cfg.groovy", "--url=${testRunner.testServer.uri}")

webtau-feature-testing/test-expectations/scenarios/rest/openapi/openApiHttpSpec/run-details.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"scenario" : "open api validation",
44
"shortContainerId" : "openApiHttpSpec.groovy",
55
"stepsSummary" : {
6-
"numberOfSuccessful" : 2
6+
"numberOfSuccessful" : 3
77
}
88
} ],
99
"exitCode" : 0
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"scenarioDetails" : [ {
3+
"scenario" : "before first test",
4+
"shortContainerId" : "Setup",
5+
"stepsSummary" : {
6+
"numberOfSuccessful" : 2
7+
}
8+
}, {
9+
"scenario" : "after all tests",
10+
"shortContainerId" : "Teardown",
11+
"stepsSummary" : {
12+
"numberOfSuccessful" : 2
13+
}
14+
}, {
15+
"scenario" : "list customers on started server as part of listeners",
16+
"shortContainerId" : "startAndStopAsPartOfSuite.groovy",
17+
"stepsSummary" : {
18+
"numberOfSuccessful" : 4
19+
}
20+
} ],
21+
"exitCode" : 0
22+
}

webtau-graphql/src/main/java/org/testingisdocumenting/webtau/graphql/GraphQLSchemaLoader.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.stream.Stream;
3939

4040
import static org.testingisdocumenting.webtau.graphql.GraphQL.GRAPHQL_URL;
41-
import static org.testingisdocumenting.webtau.graphql.GraphQL.reset;
4241
import static org.testingisdocumenting.webtau.http.Http.http;
4342

4443
public class GraphQLSchemaLoader {

webtau-open-api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<artifactId>webtau-open-api</artifactId>
2929

3030
<properties>
31-
<swagger.validator.version>2.11.0</swagger.validator.version>
31+
<swagger.validator.version>2.15.1</swagger.validator.version>
3232
</properties>
3333

3434
<dependencies>

webtau-open-api/src/main/java/org/testingisdocumenting/webtau/openapi/OpenApi.java

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,68 @@
1717

1818
package org.testingisdocumenting.webtau.openapi;
1919

20+
import java.util.concurrent.atomic.AtomicReference;
21+
2022
public class OpenApi {
21-
private static OpenApiSpec spec;
22-
private static OpenApiSpecValidator validator;
23-
private static OpenApiCoverage coverage;
23+
private static final ValidationMode DEFAULT_MODE = ValidationMode.ALL;
2424

25-
static OpenApiSpec getSpec() {
26-
return spec;
27-
}
25+
private static final AtomicReference<OpenApiSpec> spec = new AtomicReference<>();
26+
private static final AtomicReference<OpenApiSpecValidator> validator = new AtomicReference<>();
27+
private static final AtomicReference<OpenApiCoverage> coverage = new AtomicReference<>();
28+
29+
static final ThreadLocal<ValidationMode> validationMode = ThreadLocal.withInitial(() -> DEFAULT_MODE);
2830

29-
static OpenApiSpecValidator getValidator() {
30-
return validator;
31+
synchronized static OpenApiSpecValidator getValidator() {
32+
if (validator.get() == null) {
33+
initialize();
34+
}
35+
36+
return validator.get();
3137
}
3238

33-
static OpenApiCoverage getCoverage() {
34-
return coverage;
39+
synchronized static OpenApiCoverage getCoverage() {
40+
if (coverage.get() == null) {
41+
initialize();
42+
}
43+
44+
return coverage.get();
3545
}
3646

3747
public static void withoutValidation(Runnable code) {
38-
OpenApiResponseValidator.withMode(ValidationMode.NONE, code);
48+
withMode(ValidationMode.NONE, code);
3949
}
4050

4151
public static void responseOnlyValidation(Runnable code) {
42-
OpenApiResponseValidator.withMode(ValidationMode.RESPONSE_ONLY, code);
52+
withMode(ValidationMode.RESPONSE_ONLY, code);
4353
}
4454

4555
public static void requestOnlyValidation(Runnable code) {
46-
OpenApiResponseValidator.withMode(ValidationMode.REQUEST_ONLY, code);
56+
withMode(ValidationMode.REQUEST_ONLY, code);
57+
}
58+
59+
static void withMode(ValidationMode mode, Runnable code) {
60+
validationMode.set(mode);
61+
try {
62+
code.run();
63+
} finally {
64+
validationMode.set(DEFAULT_MODE);
65+
}
4766
}
4867

4968
static void reset() {
50-
spec = new OpenApiSpec(OpenApiSpecConfig.getSpecFullPathOrUrl());
51-
validator = new OpenApiSpecValidator(spec, validationConfig());
52-
coverage = new OpenApiCoverage(spec);
69+
spec.set(null);
70+
validator.set(null);
71+
coverage.set(null);
72+
}
73+
74+
static void initialize() {
75+
if (validationMode.get() == ValidationMode.NONE) {
76+
return;
77+
}
78+
79+
spec.set(new OpenApiSpec(OpenApiSpecConfig.determineSpecFullPathOrUrl()));
80+
validator.set(new OpenApiSpecValidator(spec.get(), validationConfig()));
81+
coverage.set(new OpenApiCoverage(spec.get()));
5382
}
5483

5584
private static OpenApiValidationConfig validationConfig() {
@@ -58,5 +87,4 @@ private static OpenApiValidationConfig validationConfig() {
5887

5988
return config;
6089
}
61-
6290
}

0 commit comments

Comments
 (0)