Skip to content

Commit

Permalink
Merge pull request #50 from znsio/docker-docs
Browse files Browse the repository at this point in the history
Documentation Update: Getting Started With Docker and Backward Compatibility Tests Docker Snippets
  • Loading branch information
harikrishnan83 authored Feb 2, 2024
2 parents b00dfbe + b51bcfd commit 4efd5d3
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 21 deletions.
16 changes: 16 additions & 0 deletions _includes/setup_command_line.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ Run specmatic by
``` bash
$ npx specmatic
```
{% endtab %}

{% tab install docker %}

Docker Pull Command for specmatic docker image

``` bash
> docker pull znsio/specmatic
```

Run specmatic by

``` bash
docker run znsio/specmatic
```

{% endtab %}
{% endtabs %}

Expand Down
69 changes: 58 additions & 11 deletions documentation/backward_compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ This contract contains an API for fetching the details of a product.
Let's add a new api to create a product record:
```yaml
# filename api_products_v1-2.yaml
# filename api_products_v2.yaml
openapi: 3.0.0
info:
title: Sample Product API
Expand Down Expand Up @@ -150,13 +150,25 @@ The newer contract is backward compatible with the older, as existing consumers
Run the specmatic compare command to confirm this, and see the result:
{% tabs compare %}
{% tab compare java %}
```bash
java -jar specmatic.jar compare api_products_v1.yaml api_products_v2.yaml
```
{% endtab %}
{% tab compare docker %}
```bash
> java -jar specmatic.jar compare api_products_v1.yaml api_products_v1-2.yaml
docker run -v "/local-directory:/specs" znsio/specmatic compare "/specs/api_products_v1.yaml" "/specs/api_products_v2.yaml"
```
{% endtab %}
{% endtabs %}

You should now see an output as shown below.
```bash
The newer contract is backward compatible
```

Let's change the original contract of square to return "sku" as a numeric value instead of string in the response:
Let's change the original contract of square to return `sku` as a num `integer` instead of `string` in the response:

```yaml
# filename api_products_v2.yaml
Expand Down Expand Up @@ -194,17 +206,28 @@ paths:
properties:
name:
type: string
sku:
sku: #this has changed from string to integer
type: integer
```
Note that the file name of the above file is api_products_v2.yaml.
Now try it again:
{% tabs compare2 %}
{% tab compare2 java %}
```bash
> java -jar specmatic.jar compare api_math_v1.yaml api_math_v2.yaml
java -jar specmatic.jar compare api_products_v1.yaml api_products_v2.yaml
```
{% endtab %}
{% tab compare2 docker %}
```bash
docker run -v "/local-directory:/specs" znsio/specmatic compare "/specs/api_products_v1.yaml" "/specs/api_products_v2.yaml"
```
{% endtab %}
{% endtabs %}

Specmatic will show you an error message, saying that the change is not backward compatible. The reason for this is that existing consumers are expecting a string "sku", but will get an "integer" instead.

```bash
In scenario "Get Products. Response: Returns Product With Id"
API: GET /products/(id:number) -> 200

Expand All @@ -215,34 +238,58 @@ API: GET /products/(id:number) -> 200
The newer contract is not backward compatible.
```

Specmatic will show you an error message, saying that the change is not backward compatible. The reason for this is that existing consumers are expecting a string "sku", but will get an "integer" instead.

If the change is not backward compatible, the compare command exits with exit code 1. You can use this in a script.

## Validating Changes In Git On Your Laptop

If api_products_v1.yaml is in a git repository, and the change is backward compatible, make the change directly to the v1 file instead of creating a new one.
If `api_products_v1.yaml` is part of a git repository, changes can be made directly to this file instead of creating a new one.

Then to confirm that it is a backward compatible change, before committing the change, run this command:

{% tabs git-compare %}
{% tab git-compare java %}
```bash
java -jar specmatic.jar compatible git file ./run/specmatic/examples/api_products_v1.yaml
```
{% endtab %}
{% tab git-compare docker %}
```bash
docker run -v "/git-repo:/git-repo" znsio/specmatic compatible git file "/git-repo/api_products_v1.yaml"
```
{% endtab %}
{% endtabs %}

This command exits with exit code 1 if the change is backward incompatible. It can be configured as a git pre-commit hook.

```bash
The newer contract is backward compatible
```

## Validating Changes In CI

In CI, you will need to compare the changes in a contract from one commit to the next.

You can do this with the following command:

{% tabs ci-compare %}
{% tab ci-compare java %}
```bash
> java -jar specmatic.jar compatible git commits api_products_v1.yaml HEAD HEAD^1
java -jar specmatic.jar compatible git commits api_products_v1.yaml HEAD HEAD^1
```
{% endtab %}
{% tab ci-compare docker %}
```bash
docker run -v "/git-repo:/git-repo" znsio/specmatic compatible git commits "/git-repo/api_products_v1.yaml" HEAD HEAD^1
```
{% endtab %}
{% endtabs %}

You can even use commit hashes here if you wish to compare any other pair of commits.

```bash
The newer contract is backward compatible
```

This command exits with exit code 1 if the change is backward incompatible.

## Handling Contracts In Progress
Expand Down
75 changes: 65 additions & 10 deletions getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ specmatic test service.yaml --testBaseURL=https://my-json-server.typicode.com/zn
npx specmatic test service.yaml --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% tab test docker %}
```shell
docker run -v "/local-directory/service.yaml:/service.yaml" znsio/specmatic test "/service.yaml" --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% endtabs %}

This should print out a result that looks something like this.
Expand Down Expand Up @@ -132,23 +137,48 @@ Tests run: 1, Successes: 1, Failures: 0, Errors: 0

How did Specmatic know to make the exact request to ```GET /znsio/specmatic-documentation/pets/1``` with petId as "1"? And not just any other number?

If you notice the OpenAPI, we have an example section for PetId which sets up our petId as per the test data.
In the OpenAPI spec you may have noticed that there is an examples section for petid.

```yaml
- name: "petid"
in: "path"
required: true
schema:
type: "number"
type: "number"
examples:
200_OKAY:
200_OKAY:
value: 1
```
Try removing this example value and try running the specmatic test command again.
Remove the examples section such that the `petid` param look as shown below.

```yaml
- name: "petid"
in: "path"
required: true
schema:
type: "number"
```

And try running the specmatic test command again.

{% tabs test3 %}
{% tab test3 java %}
```shell
specmatic test service.yaml --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% tab test3 npm %}
```shell
npx specmatic test service.yaml --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% tab test3 docker %}
```shell
docker run -v "/local-directory/service.yaml:/service.yaml" znsio/specmatic test "/service.yaml" --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% endtabs %}

Specmatic will generate a random petId based on the datatype of the petId path parameter which results in a 404 since test data does not exist.
```shell
Expand Down Expand Up @@ -177,6 +207,11 @@ specmatic test service.yaml --testBaseURL=https://my-json-server.typicode.com/zn
npx specmatic test service.yaml --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% tab test2 docker %}
```shell
docker run -v "/local-directory/service.yaml:/service.yaml" znsio/specmatic test "/service.yaml" --testBaseURL=https://my-json-server.typicode.com/znsio/specmatic-documentation
```
{% endtab %}
{% endtabs %}
This time around the test fails because the response from our sample app is not in line with the OpenAPI Specification.
```shell
Expand Down Expand Up @@ -224,6 +259,11 @@ specmatic stub service.yaml
npx specmatic stub service.yaml
```
{% endtab %}
{% tab stub docker %}
```shell
docker run -v "/local-directory/service.yaml:/service.yaml" -p 9000:9000 znsio/specmatic stub "/service.yaml"
```
{% endtab %}
{% endtabs %}

This should start your stub server on port 9000 by default (you can switch the port number by adding ```--port <port of your choice>``` to the above command) as below.
Expand All @@ -233,10 +273,15 @@ Loading service.yaml
Stub server is running on http://0.0.0.0:9000. Ctrl + C to stop.
```

Once the stub server is running you can verify the API by accessing it through Postman, Chrome, Curl etc. to see the response.
Once the stub server is running you can verify the API by accessing it through Postman, Chrome, Curl etc.

```shell
curl http://localhost:9000/pets/123
```

You should now be able to see the response that matches the schema defined in your OpenAPI spec.

```shell
{
"id": 864,
"name": "VRIQA",
Expand All @@ -246,8 +291,8 @@ curl http://localhost:9000/pets/123
```

The response contains auto-generated values that adhere to the data type defined in the contract. In above output petid "864" is generated by specmatic and will vary with every execution. If you would like to control the value that is being returned you can set up stub / canned responses.
* Create a folder named service_data in the same folder as your service.yaml file (_data suffix is a naming convention that tell Specmatic to look for canned responses in that directory)
* Create a json file with the name scooby.json and add below contents to it
* Create a folder named `service_data` in the same folder as your `service.yaml` file (`_data` suffix is a naming convention that tell Specmatic to look for canned responses in that directory)
* Create a json file with the name `scooby.json` and add below contents to it

```json
{
Expand Down Expand Up @@ -280,6 +325,14 @@ specmatic stub service.yaml
npx specmatic stub service.yaml
```
{% endtab %}
{% tab stub2 docker %}
```shell
# Please note docker command here has to volume map the directory containing service.yaml
# to a directory within the container so that both service.yaml and folder service_data along
# with scooby.json are available to Specmatic docker container
docker run -v "/local-directory/:/specs" -p 9000:9000 znsio/specmatic stub "/specs/service.yaml"
```
{% endtab %}
{% endtabs %}

This time you should see Specmatic load your canned response file also.
Expand All @@ -294,6 +347,10 @@ Stub server is running on http://0.0.0.0:9000. Ctrl + C to stop.
And let us now run the curl command.
```shell
curl http://localhost:9000/pets/1
```

Specmatic will now return your canned response for petId 1. For any other petId it will continue to return generated values.
```shell
{
"id": 1,
"name": "Scooby",
Expand All @@ -302,11 +359,9 @@ curl http://localhost:9000/pets/1
}
```

Specmatic will now return your canned response for petId 1. For any other petId it will continue to return generated values.

So what is so smart about Specmatic Smart Mocks.

Let us try a few experiments. Remove the "status" field in scooby.json and run the stub command again. You should an output like below.
Let us try a few experiments. Remove the `status` field within http-response body in `scooby.json` and run the stub command again. You should an output like below.
```shell
Loading service.yaml
Loading stub expectations from /<dir with service.yaml>/service_data
Expand Down

0 comments on commit 4efd5d3

Please sign in to comment.