Skip to content

Commit 09c114c

Browse files
add znai exported source
1 parent e8a13a7 commit 09c114c

198 files changed

Lines changed: 5170 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

znaisrc/REST/CRUD-separated.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Lazy Resource
2+
3+
One of the benefits of separating one CRUD `scenario` into multiple is to be able to run one test at a time.
4+
In order to do it we will use `createLazyResource`.
5+
6+
:include-file: scenarios/rest/springboot/customerCrudSeparated.groovy {commentsType: "inline", title: "CRUD separated"}
7+
8+
:include-file: scenarios/rest/springboot/Customer.groovy {commentsType: "inline", title: "Customer lazy resource"}
9+
10+
Note: to run one scenario at a time use `sscenario` (additional `s` in front). [Read more](groovy-specific-runner/selective-run)
11+
12+
# Report
13+
14+
As you can see in the report below, each `CRUD` operation has its own entry. If you follow this pattern, then you
15+
can filter tests by `create`, `update`, `read`, `delete` to streamline investigation.
16+
17+
:include-image: doc-artifacts/reports/report-crud-separated-http-calls.png {fit: true}

znaisrc/REST/CRUD.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Example
2+
3+
We have an app that exposes create, read, update, and delete operations for customer records. Records are being served
4+
under `/customers`.
5+
6+
Here is an example of a `CRUD` operations test.
7+
8+
:include-file: scenarios/rest/springboot/customerCrud.groovy {commentsType: "inline"}
9+
10+
# Implicit statusCode Check
11+
12+
If you don't have an explicit `statusCode` validation it will be automatically validated based on the rules below
13+
14+
| Method | Expected Code |
15+
| ------------------ |---------------|
16+
| GET | 200 |
17+
| POST | 201 |
18+
| PUT | 200 |
19+
| PUT (no content) | 204 |
20+
| DELETE | 200 |
21+
| DELETE (no content)| 204 |
22+
23+
# Report
24+
25+
After your test executions a report will be produced.
26+
27+
:include-image: doc-artifacts/reports/report-crud-http-calls.png {fit: true}
28+
29+
Note: asserted values are being tracked and highlighted inside the report
30+
31+
# Spring Boot
32+
33+
WebTau is framework agnostic. However, to make a concrete example, the `/customer` `CRUD` endpoint
34+
is created by using [Spring Boot](https://projects.spring.io/spring-boot/).
35+
36+
Three files are required to have a working REST endpoint with `CRUD` operations.
37+
38+
1. Domain object
39+
40+
:include-file: com/example/demo/springboot/app/data/Customer.java {title: "Customer.java"}
41+
42+
2. Repository
43+
44+
:include-file: com/example/demo/springboot/app/data/CustomerRepository.java {title: "CustomerRepository.java"}
45+
46+
3. Entry point
47+
48+
:include-file: com/example/demo/springboot/app/SpringBootDemoApp.java {title: "SpringBootDemoApp.java"}

znaisrc/REST/JSON-schema.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Validation
2+
3+
Webtau supports validation of objects against [JSON Schema](https://json-schema.org/). It is possible to validate either
4+
the entire body or just a specific field with the `complyWithSchema` matcher as shown in the two examples below:
5+
6+
:include-groovy: doc-artifacts/snippets/json-schema/validateBody.groovy {title: "Validate entire body against JSON schema"}
7+
:include-groovy: doc-artifacts/snippets/json-schema/validateField.groovy {title: "Validate specific field against JSON schema"}
8+
9+
Both examples above validate against the following schema:
10+
11+
:include-json: examples/schemas/valid-schema.json {title: "Correct schema for the example above"}
12+
13+
# Error messages
14+
15+
Using the first example above, an invalid schema will generate an error similar to:
16+
```
17+
invalid schema (examples/scenarios/rest/jsonSchema/validateSchema.groovy)
18+
> executing HTTP GET http://localhost:8080/weather
19+
X failed expecting body to comply with schema invalid-schema.json :
20+
body expected to comply with schema invalid-schema.json
21+
[#: required key [anotherField] not found, #/temperature: expected type: Boolean, found: Integer]
22+
{
23+
"temperature": 88
24+
}
25+
```
26+
27+
The schema used in validation to generate this error is as follows:
28+
29+
:include-json: examples/schemas/invalid-schema.json {title: "Incorrect schema for the example above"}
30+
31+
# Configuration
32+
33+
The path to the schema file specified in `complyWithSchema` can be relative or absolute. If it's relative, it'll be
34+
relative to the `jsonSchemasDir` specified in configuration and if not specified then relative to working directory.
35+
For example:
36+
37+
:include-file: scenarios/rest/jsonSchema/webtau.cfg {title: "Configuration"}

znaisrc/REST/PDF.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Asserting Text
2+
3+
If response contains a pdf file you can assert its content using `pdf(body)` function.
4+
5+
:include-groovy: com/twosigma/webtau/pdf/PdfHttpTest.groovy {entry: "download pdf and assert page text using contains", bodyOnly: true}
6+
7+
If more than one assertion needs to be made, assign `pdf` result to a local variable.
8+
9+
:include-groovy: com/twosigma/webtau/pdf/PdfHttpTest.groovy {entry: "download pdf and assert page text using equal and contains", bodyOnly: true}
10+
11+
Note: use pdf assertions for sanity checks like presence of correct client names or account numbers. Leave comprehensive pdf generation test to unit tests.

znaisrc/REST/complex-types.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Contain
2+
3+
Use `contain` matcher to test scenarios like search or list of recently created entries.
4+
This way you don't have to assume an existing state of your backend under test.
5+
6+
:include-json: doc-artifacts/list-match/response.json {title: "Response"}
7+
8+
Given the response, we want to make sure there is an entry with a specified `firstName` and `lastName`.
9+
10+
:include-file: examples/scenarios/rest/springboot/listContain.groovy
11+
12+
# List Of Objects
13+
14+
If you want to make sure that all the values in the list are what you need - use `TableData`.
15+
16+
:include-file: examples/scenarios/rest/springboot/listMatch.groovy
17+
18+
# Order Agnostic Match
19+
20+
Use `*key` column(s) if list order is not guaranteed
21+
22+
:include-file: examples/scenarios/rest/springboot/listMatchByKey.groovy
23+

znaisrc/REST/data-node.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Special Values
2+
3+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "use groovy closure as validation", bodyOnly: true}
4+
5+
Values that you access inside validation block are special values of `DataNode` type. When you assert them using `should` statement
6+
they act as proxies that record every assertion that you do.
7+
8+
9+
# Extracting Values
10+
11+
As you have seen in [CRUD example](REST/CRUD) you can return values back from a validation block.
12+
13+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "can return simple value from get", bodyOnly: true}
14+
15+
When you return a value from a validation block, it automatically gets converted to its correspondent primitive.
16+
17+
Note: asserting that value after returning will not track and associated assertions with the call anymore. Use it only
18+
to get values required for consequent test calls.
19+
20+
# Properties On Lists
21+
22+
:include-json: objectTestResponse.json
23+
24+
If you have a list of objects like `complexList` above, you can access all its children property value with `complexList.k2`.
25+
26+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy children key shortcut", bodyOnly: true}
27+
28+
# Path based properties access
29+
30+
Primarily for Java users, webtau supports the ability to query properties of a `DataNode` via a path instead of chaining
31+
`get(String name)` calls. For example, to obtain a simple property:
32+
33+
:include-java: com/twosigma/webtau/http/HttpJavaTest.java {entry: "canQueryNodeByPath", bodyOnly: true}
34+
35+
It is also possible to query arrays, including the ability to query for the Nth element from the end:
36+
37+
:include-java: com/twosigma/webtau/http/HttpJavaTest.java {entry: "canQuerySpecificListElementByPath", bodyOnly: true}
38+
39+
Similarly to the Groovy example in [Properties On Lists](REST/data-node#properties-on-lists), it is possible to access
40+
all children property values:
41+
42+
:include-java: com/twosigma/webtau/http/HttpJavaTest.java {entry: "canQueryListByNodePath", bodyOnly: true}
43+
44+
# If-Else Logic
45+
46+
Even though values that you access inside validation block are special values of `DataNode` type, you can still
47+
perform simple `if-else` like logic checks on them. Accessing the values will mark them as "touched" for data coverage statistic.
48+
49+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "if-else logic", bodyOnly: true, title: "simple if-else logic"}
50+
51+
Warning: Comparison of complex values is not properly implemented due to current Groovy API implementation details
52+
53+
# Each
54+
55+
Special values inside assertion block have convenient methods
56+
57+
`each` to iterate over a list
58+
59+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy each on simple list", bodyOnly: true, title: "List of simple values"}
60+
61+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy each on complex list", bodyOnly: true, title: "List of complex values"}
62+
63+
64+
# Find
65+
66+
`find` to find a single value
67+
68+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy find on list", bodyOnly: true}
69+
70+
71+
and `findAll` to find all the values matching predicate
72+
73+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy findAll on list", bodyOnly: true}
74+
75+
Note: While values inside a predicate are normal values, the result of `find` and `findAll` is still `DataNode`
76+
77+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy find on list of objects", bodyOnly: true}
78+
79+
# Collect
80+
81+
Use `collect` to transform a collection of items
82+
83+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy transform list", bodyOnly: true}
84+
85+
# Combine
86+
87+
Methods `find` and `collect` can be chained
88+
89+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "groovy findAll, collect, and sum", bodyOnly: true}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"nodes": [
3+
{
4+
"id": "build",
5+
"label": "Build"
6+
},
7+
{
8+
"id": "deploy",
9+
"label": "Deploy"
10+
},
11+
{
12+
"id": "testrun",
13+
"label": "Test Run",
14+
"highlight": true
15+
},
16+
{
17+
"id": "documentation",
18+
"label": "Documentation"
19+
}
20+
],
21+
"edges": [
22+
["build", "deploy"],
23+
["deploy", "testrun"],
24+
["testrun", "documentation"]
25+
]
26+
}

znaisrc/REST/documentation.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Scenarios
2+
3+
You provide `REST endpoints` so users can execute various scenarios.
4+
You need to test those scenarios and then document them.
5+
6+
To automate the process, let's capture executed scenarios and use them inside your documentation.
7+
8+
# Capturing Test Artifacts
9+
10+
To capture artifacts use `http.doc.capture`:
11+
12+
:include-file: scenarios/rest/simplePost.groovy {title: "test.groovy", commentsType: "inline"}
13+
14+
An `employee-get` directory will be created containing a number of test artifacts.
15+
16+
# Test Artifacts Location
17+
18+
By default, the directory will be created in the current working directory.
19+
To change it add `docPath` to your `webtau.cfg` file.
20+
21+
:include-file: examples/scenarios/rest/docArtifacts.cfg {title: "webtau.cfg"}
22+
23+
# Test Artifacts
24+
25+
A number of artifacts will be created depending on the exact call being captured.
26+
27+
## Request and response payloads
28+
29+
Request bodies are captured in either `request.json`, `request.pdf` or `request.data` depending on the type.
30+
31+
:include-json: doc-artifacts/employee-post/request.json {title: "employee-post/request.json" }
32+
33+
Similarly, response bodies are captured in either `response.json`, `response.pdf` or `response.data`.
34+
35+
:include-json: doc-artifacts/employee-get/response.json {title: "employee-get/response.json" }
36+
37+
## Request and response headers
38+
39+
Just like payloads, request and response headers are captured in `request.header.txt` and `response.header.txt`
40+
respectively. These files contain a header per line with the name and values colon separated. The values
41+
are redacted for any potentially sensitive headers.
42+
43+
:include-json: doc-artifacts/echo-body-and-header-redacted/request.header.txt {title: "redacted request.header.txt"}
44+
45+
## Response body assertions
46+
47+
Any assertions you perform on the response body in your scenarios are captured in a `paths.json` file. This
48+
contains an array with the list of paths within the body whose values were asserted.
49+
50+
:include-json: doc-artifacts/employee-get/paths.json {title: "employee-get/paths.json" }
51+
52+
53+
## Request URLs
54+
55+
The actual request URL is captured in two forms into two different files:
56+
* `request.fullurl.txt` - contains the full URL
57+
* `request.url.txt` - contains only the part specified in the http call in the scenario
58+
59+
:include-file: doc-artifacts/url-capture/request.url.txt {title: "request.url.txt"}
60+
61+
:include-file: doc-artifacts/url-capture/request.fullurl.txt {title: "request.fullurl.txt"}
62+
63+
# Document REST calls
64+
65+
If you have user facing scenario tests, capture them and refer to them inside your documentation.
66+
Set your documentation build pipeline like below.
67+
68+
:include-flow-chart: documentation-flow.json
69+
70+
Combine REST requests and responses with Open API generated specs for complete documentation.

znaisrc/REST/files-upload.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# File System Content
2+
3+
In following examples backend expects a file passed as `multipart/form-data`. File content is expected to be stored in `file` field.
4+
Backend responds with received file name and file description.
5+
6+
To `POST` form data, you need to use the same `http.post` statement as you saw in previous examples.
7+
Second parameter should be `http.formData` instead of a map payload we used for `JSON`.
8+
9+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "file upload example simple", bodyOnly: true}
10+
11+
Use `http.formFile` to override file name that is being sent to the backend.
12+
13+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "file upload example with file name override", bodyOnly: true}
14+
15+
Multiple form fields can be specified like in the example below.
16+
17+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "file upload example multiple fields", bodyOnly: true}
18+
19+
# In-Memory Content
20+
21+
If your test already has content, you can explicitly pass it as is.
22+
23+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "file upload example with in-memory content", bodyOnly: true}
24+
25+
Note: no file name is passed and this particular backend generated file name on your behalf.
26+
27+
Use `http.formFile` to provide a file name
28+
29+
:include-groovy: com/twosigma/webtau/http/HttpGroovyTest.groovy {entry: "file upload example with in-memory content and file name", bodyOnly: true}

0 commit comments

Comments
 (0)