Skip to content

Commit

Permalink
Merge pull request #36 from Boavizta/conformity-test
Browse files Browse the repository at this point in the history
Conformity test
  • Loading branch information
youenchene authored Oct 19, 2023
2 parents a2718f9 + fabbb34 commit 177d6c0
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 9 deletions.
9 changes: 9 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ Each service must respect :

Reference implementation is the [golang implementation](./service/go-pgx).

### Acceptance criteria

Service should pass the [conformity tests](./test/check-service-conformity.feature) - For help to execute test go here : https://github.com/karatelabs/karate

Service's docker should have 2 environment variables :

- `DATABASE_URL` : Example of value injected: postgres://postgres:mysecretpassword@database:5432/postgres - url signature can be change for each service
- `DATABASE_POOL_MAX` : setup to 20 by default

#### API Contract

API Contract must respect the following [API Definition documentation](./service/specs.md).
Expand Down
18 changes: 9 additions & 9 deletions service/EcobenchmarkBackEnd-0.0.1-swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ paths:
items:
$ref: '#/components/schemas/AccountStatistic'
/healthcheck:
get:
head:
tags:
- developers
summary: returns the health of the service
Expand Down Expand Up @@ -181,13 +181,13 @@ components:
type: string
format: uuid
example: 276f6a6f-0afa-4e50-9e39-7130f5aea9d2
accountId:
account_id:
type: string
example: d290f1ee-6c54-4b01-90e6-d701748f0851
name:
type: string
example: My Task List
creationDate:
creation_date:
type: string
format: date-time
example: '2022-06-29T13:37:00.001Z'
Expand All @@ -213,7 +213,7 @@ components:
type: string
format: uuid
example: c6516320-e069-4238-a5c3-a57df2c1bc32
listId:
list_id:
type: string
example: 276f6a6f-0afa-4e50-9e39-7130f5aea9d2
name:
Expand All @@ -222,23 +222,23 @@ components:
description:
type: string
example: Just do it !
creationDate:
creation_date:
type: string
format: date-time
example: '2022-06-29T13:37:00.001Z'
AccountStatistic:
type: object
properties:
accountId:
account_id:
type: string
format: uuid
example: d290f1ee-6c54-4b01-90e6-d701748f0851
accountLogin:
account_login:
type: string
example: My Personal Account
listCount:
list_count:
type: number
example: 42
taskAvg:
task_avg:
type: number
example: 1337
17 changes: 17 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Test Script

### Test Script to check the good behavior of each service implementation.

Get help here on how to launch the test : https://github.com/karatelabs/karate/wiki/Get-Started

You have different flavour to launch test.

You can use a plugin on your favorite IDE in order to launch test locally for dev purpose :

- https://github.com/karatelabs/karate/wiki/Get-Started:-Visual-Studio-Code
- https://github.com/karatelabs/karate/wiki/Get-Started:-JetBrains-IntelliJ

Or use command line style for CI integration :

- https://github.com/karatelabs/karate/wiki/Get-Started:-Maven-and-Gradle
- https://github.com/karatelabs/karate/wiki/Get-Started:-Other-Runtime-Options
129 changes: 129 additions & 0 deletions test/check-service-conformity.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
Feature:

Background:
* def now = function(){ return java.lang.System.currentTimeMillis() }
* def account_name = 'Conformity-' + now()
* url 'http://localhost:8080/'

Scenario: Healthcheck
Given path 'healthcheck'
When method head

Scenario: Simple Conformity Scenario - API Behavior and Cache agressive check
# Create an account
Given path 'api/accounts'
And header Content-Type = 'application/json'
And request { login: #(account_name) }
When method post
Then match [200, 201, 204] contains responseStatus
Then match response contains { id: #uuid, login: #(account_name)}
Then def account_id = response.id
# Create list linked to the account
Given path 'api/accounts',account_id,'lists'
And header Content-Type = 'application/json'
And def list_name = 'List-' + now()
And request { name: #(list_name) }
When method post
Then match [200, 201, 204] contains responseStatus
Then match response contains { id: #uuid, name: #(list_name) }
Then def list_id = response.id
# Create 1 task on the list
Given path 'api/lists',list_id,'tasks'
And header Content-Type = 'application/json'
And def task_name = 'Task-' + now()
And def task_description = 'Description-' + now()
And request { name: #(task_name), description: #(task_description) }
When method post
Then match [200, 201, 204] contains responseStatus
Then match response contains { id: #uuid, name: #(task_name), description: #(task_description)}
Then def task_id = response.id
# Check current list content
Given path 'api/accounts',account_id,'lists'
And header Content-Type = 'application/json'
And param page = 0
When method get
Then match [200, 201, 204] contains responseStatus
Then match response[0] contains { id: #(list_id), name: #(list_name), tasks: #notnull }
Then match response[0].tasks[0] contains { id: #(task_id), name: #(task_name), description: #(task_description) }
# Check stats
Given path 'api/stats'
And header Content-Type = 'application/json'
When method get
Then match [200, 201, 204] contains responseStatus
Then def sub_result = karate.filter(response, x => { return x.account_id == account_id } )
Then match sub_result[0] contains { account_id: #(account_id), account_login: #(account_name), list_count:1, task_avg:1 }
# Create a 2nd task on the list
Given path 'api/lists',list_id,'tasks'
And header Content-Type = 'application/json'
And def task_name_2 = 'Task-' + now()
And def task_description_2 = 'Description-' + now()
And request { name: #(task_name_2), description: #(task_description_2) }
When method post
Then match [200, 201, 204] contains responseStatus
Then match response contains { id: #uuid, name: #(task_name_2), description: #(task_description_2) }
Then def task_id_2 = response.id
# Check current list content - should be 2 tasks
Given path 'api/accounts',account_id,'lists'
And header Content-Type = 'application/json'
And param page = 0
When method get
Then match [200, 201, 204] contains responseStatus
Then match response[0] contains { id: #(list_id), name: #(list_name), tasks: #notnull }
Then def r = karate.filter(response[0].tasks, x => { return x.id == task_id } )
Then match r[0] contains { id: #(task_id), name: #(task_name), description: #(task_description) }
Then def r = karate.filter(response[0].tasks, x => { return x.id == task_id_2 } )
Then match r[0] contains { id: #(task_id_2), name: #(task_name_2), description: #(task_description_2) }
# Create a 2nd list on the account
Given path 'api/accounts',account_id,'lists'
And header Content-Type = 'application/json'
And def list_name_2 = 'List-' + now()
And request { name: #(list_name_2) }
When method post
Then match [200, 201, 204] contains responseStatus
Then match response contains { id: #uuid, name: #(list_name_2) }
Then def list_id_2 = response.id
# Check current lists content - should be 2 tasks
Given path 'api/accounts',account_id,'lists'
And header Content-Type = 'application/json'
And param page = 0
When method get
Then match [200, 201, 204] contains responseStatus
Then def lr1 = karate.filter(response, x => { return x.id == list_id } )
Then match lr1[0] contains { id: #(list_id), name: #(list_name), tasks: #notnull }
Then def r = karate.filter(lr1[0].tasks, x => { return x.id == task_id } )
Then match r[0] contains { id: #(task_id), name: #(task_name), description: #(task_description) }
Then def r = karate.filter(lr1[0].tasks, x => { return x.id == task_id_2 } )
Then match r[0] contains { id: #(task_id_2), name: #(task_name_2), description: #(task_description_2) }
Then def lr2 = karate.filter(response, x => { return x.id == list_id_2 } )
Then match lr2[0] contains { id: #(list_id_2), name: #(list_name_2), account_id: #(account_id) }
# Create 1 task on the 2nd list
Given path 'api/lists',list_id_2,'tasks'
And header Content-Type = 'application/json'
And request { name: #(task_name), description: #(task_description) }
When method post
Then match [200, 201, 204] contains responseStatus
Then match response contains { id: #uuid, name: #(task_name), description: #(task_description)}
Then def task_id_1_2 = response.id
# Check current lists content - should be 2 tasks
Given path 'api/accounts',account_id,'lists'
And header Content-Type = 'application/json'
And param page = 0
When method get
Then match [200, 201, 204] contains responseStatus
Then def lr1 = karate.filter(response, x => { return x.id == list_id } )
Then match lr1[0] contains { id: #(list_id), name: #(list_name), tasks: #notnull }
Then def r = karate.filter(lr1[0].tasks, x => { return x.id == task_id } )
Then match r[0] contains { id: #(task_id), name: #(task_name), description: #(task_description) }
Then def r = karate.filter(lr1[0].tasks, x => { return x.id == task_id_2 } )
Then match r[0] contains { id: #(task_id_2), name: #(task_name_2), description: #(task_description_2)}
Then def lr2 = karate.filter(response, x => { return x.id == list_id_2 } )
Then match lr2[0] contains { id: #(list_id_2), name: #(list_name_2), tasks: #notnull }
Then def r = karate.filter(lr2[0].tasks, x => { return x.id == task_id_1_2 } )
Then match r[0] contains { id: #(task_id_1_2), name: #(task_name), description: #(task_description)}
# Check stats
Given path 'api/stats'
And header Content-Type = 'application/json'
When method get
Then match [200, 201, 204] contains responseStatus
Then def sub_result = karate.filter(response, x => { return x.account_id == account_id } )
Then match sub_result[0] contains { account_id: #(account_id), account_login: #(account_name), list_count:2, task_avg:1.5 }

0 comments on commit 177d6c0

Please sign in to comment.