Added features for append/error_malformed, delete/list_order, insert/error_malformed and insert/list_order. Updated append/error_unprocessable and resolve conflicts in list/success.

This commit is contained in:
Héctor Hurtado
2019-08-20 10:36:24 +02:00
14 changed files with 221 additions and 144 deletions
+18 -9
View File
@@ -306,21 +306,27 @@ def delete_route(app):
######################################################################## ########################################################################
async def run_init_script(app, scripts): async def run_init_script(app, scripts, interactive):
""" """
Run the init script if given, then wait for the shell to finish. Run the init script if given, then wait for the shell to finish.
""" """
if not scripts: if not scripts:
# No script given # No script given
cmd = "/bin/bash" if not interactive:
return
else:
cmd = "/bin/bash"
else: else:
def build_filenames(): def build_filenames():
for filename in scripts: for filename in scripts:
yield shlex.quote(filename) yield shlex.quote(filename)
yield "<(echo)" yield "<(echo)"
filenames = " ".join(build_filenames()) filenames = " ".join(build_filenames())
cmd = f"/bin/bash --init-file <(cat {filenames})" if interactive:
cmd = f"/bin/bash --init-file <(cat {filenames})"
else:
cmd = f"/bin/bash <(cat {filenames})"
shell_task = await asyncio.create_subprocess_shell( shell_task = await asyncio.create_subprocess_shell(
cmd, cmd,
@@ -330,16 +336,17 @@ async def run_init_script(app, scripts):
}) })
await shell_task.wait() await shell_task.wait()
await app.cleanup() if interactive:
os._exit(shell_task.returncode) await app.cleanup()
os._exit(shell_task.returncode)
async def start_background_tasks(app): async def start_background_tasks(app):
global loop global loop
app["debug_tasks"] = loop.create_task(run_init_script(app, app["scripts"])) app["debug_tasks"] = loop.create_task(run_init_script(app, app["scripts"], app["interactive"]))
async def start_kapow_server(bind, scripts, certfile=None, keyfile=None): async def start_kapow_server(bind, scripts, certfile=None, interactive=False, keyfile=None):
user_app = web.Application(client_max_size=1024**3) user_app = web.Application(client_max_size=1024**3)
user_runner = web.AppRunner(user_app) user_runner = web.AppRunner(user_app)
await user_runner.setup() await user_runner.setup()
@@ -366,6 +373,7 @@ async def start_kapow_server(bind, scripts, certfile=None, keyfile=None):
web.put('/handlers/{id}/{field:.*}', set_field), web.put('/handlers/{id}/{field:.*}', set_field),
]) ])
control_app["scripts"] = scripts control_app["scripts"] = scripts
control_app["interactive"] = interactive
control_app.on_startup.append(start_background_tasks) control_app.on_startup.append(start_background_tasks)
control_runner = web.AppRunner(control_app) control_runner = web.AppRunner(control_app)
@@ -391,12 +399,13 @@ def kapow(ctx):
@click.option("--certfile", default=None) @click.option("--certfile", default=None)
@click.option("--keyfile", default=None) @click.option("--keyfile", default=None)
@click.option("--bind", default="0.0.0.0:8080") @click.option("--bind", default="0.0.0.0:8080")
@click.option("-i", "--interactive", is_flag=True)
@click.argument("scripts", nargs=-1) @click.argument("scripts", nargs=-1)
def server(certfile, keyfile, bind, scripts): def server(certfile, keyfile, bind, interactive, scripts):
if bool(certfile) ^ bool(keyfile): if bool(certfile) ^ bool(keyfile):
print("For SSL both 'certfile' and 'keyfile' should be provided.") print("For SSL both 'certfile' and 'keyfile' should be provided.")
sys.exit(1) sys.exit(1)
loop.run_until_complete(start_kapow_server(bind, scripts, certfile, keyfile)) loop.run_until_complete(start_kapow_server(bind, scripts, certfile, interactive, keyfile))
loop.run_forever() loop.run_forever()
@kapow.group() @kapow.group()
+3 -3
View File
@@ -12,8 +12,8 @@
"Scenario": 2, "Scenario": 2,
"Background": 2, "Background": 2,
"given": 4, "given": 4,
"when": 6, "when": 4,
"then": 6, "then": 4,
"and": 6, "and": 6,
"but": 6, "but": 6,
"example": 2, "example": 2,
@@ -24,7 +24,7 @@
"new-line-at-eof": ["on", "yes"], "new-line-at-eof": ["on", "yes"],
"no-multiple-empty-lines": "on", "no-multiple-empty-lines": "on",
"no-scenario-outlines-without-examples": "on", "no-scenario-outlines-without-examples": "on",
"name-length": ["on", {"Feature": 50}], "name-length": ["on", {"Feature": 80}],
"no-restricted-tags": ["on", {"tags": ["@watch", "@wip"]}], "no-restricted-tags": ["on", {"tags": ["@watch", "@wip"]}],
"use-and": "on", "use-and": "on",
"no-duplicate-tags": "on", "no-duplicate-tags": "on",
+3 -1
View File
@@ -1,3 +1,5 @@
test: test:
gherkin-lint gherkin-lint
pipenv run behave --no-capture pipenv run behave --no-capture --stop
catalog:
pipenv run behave --steps-catalog
@@ -8,17 +8,17 @@ Feature: Kapow! server reject responses with malformed JSON bodies.
the server will respond with a bad request error. the server will respond with a bad request error.
Given I have a running Kapow! server Given I have a running Kapow! server
When I try to append with this JSON document: When I try to append with this JSON document:
""" """
{ {
"method" "GET", "method" "GET",
"url_pattern": /hello, "url_pattern": /hello,
"entrypoint": null "entrypoint": null
"command": "echo Hello "command": "echo Hello
World | response /body", World | response /body",
"id": "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" "id": "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
} }
""" """
Then I get 400 as response code Then I get 400 as response code
And I get "Malformed JSON" as response phrase And I get "Malformed JSON" as response phrase
And I get an empty response body And I get an empty response body
@@ -9,11 +9,11 @@ Feature: Kapow! server reject responses with semantic errors.
missing fields. missing fields.
Given I have a running Kapow! server Given I have a running Kapow! server
When I append the route: When I append the route:
| entrypoint | command | | entrypoint | command |
| /bin/sh -c | ls -la / \| response /body | | /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code Then I get 422 as response code
And I get "Missing Mandatory Field" as response phrase And I get "Missing Mandatory Field" as response reason phrase
And I get the following entity as response body: And I get the following entity as response body:
| missing_mandatory_fields | | missing_mandatory_fields |
| "url_pattern", "method" | | "url_pattern", "method" |
@@ -23,11 +23,11 @@ Feature: Kapow! server reject responses with semantic errors.
field url_pattern the server responds with an error. field url_pattern the server responds with an error.
Given I have a running Kapow! server Given I have a running Kapow! server
When I append the route: When I append the route:
| method | url_pattern | entrypoint | command | | method | url_pattern | entrypoint | command |
| GET | +123-- | /bin/sh -c | ls -la / \| response /body | | GET | +123-- | /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code Then I get 422 as response code
And I get "Invalid Route Spec" as response phrase And I get "Invalid Route Spec" as response reason phrase
And I get an empty response body And I get an empty response body
Scenario: Error because of wrong method value. Scenario: Error because of wrong method value.
@@ -35,9 +35,9 @@ Feature: Kapow! server reject responses with semantic errors.
field method the server responds with an error. field method the server responds with an error.
Given I have a running Kapow! server Given I have a running Kapow! server
When I append the route: When I append the route:
| method | url_pattern | entrypoint | command | | method | url_pattern | entrypoint | command |
| AVECES | +123-- | /bin/sh -c | ls -la / \| response /body | | AVECES | +123-- | /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code Then I get 422 as response code
And I get "Invalid Data Type" as response phrase And I get "Invalid Data Type" as response reason phrase
And I get an empty response body And I get an empty response body
@@ -8,11 +8,11 @@ Feature: Append new routes in Kapow! server.
will be at index 0. will be at index 0.
Given I have a just started Kapow! server Given I have a just started Kapow! server
When I append the route: When I append the route:
| method | url_pattern | entrypoint | command | | method | url_pattern | entrypoint | command |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body |
Then I get created as response code Then I get 201 as response code
And I get "Created" as response phrase And I get "Created" as response reason phrase
And I get the following entity as response body: And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id | | method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * |
@@ -25,11 +25,11 @@ Feature: Append new routes in Kapow! server.
| method | url_pattern | entrypoint | command | | method | url_pattern | entrypoint | command |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body |
| GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body | | GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body |
When I append the route: When I append the route:
| method | url_pattern | entrypoint | command | | method | url_pattern | entrypoint | command |
| GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | | GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body |
Then I get created as response code Then I get 201 as response code
And I get "Created" as response phrase And I get "Created" as response reason phrase
And I get the following entity as response body: And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id | | method | url_pattern | entrypoint | command | index | id |
| GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 2 | * | | GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 2 | * |
@@ -7,7 +7,7 @@ Feature: Fail to delete a route in Kapow! server.
will trigger a not found error. will trigger a not found error.
Given I have a just started Kapow! server Given I have a just started Kapow! server
When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
Then I get not found as response code Then I get 404 as response code
And I get "Not Found" as response phrase And I get "Not Found" as response reason phrase
And I get an empty response body And I get an empty response body
@@ -16,35 +16,35 @@ Feature: Routes auto-ordering in a Kapow! server.
will maintain their relative order and their indexes will maintain their relative order and their indexes
will be decreased by one. will be decreased by one.
When I delete the first route inserted When I delete the first route inserted
Then I get 200 as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response phrase
And I get an empty response body And I get an empty response body
When I request a routes listing When I request a routes listing
Then I get 200 as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response phrase
And I get a list with the following elements: And I get a list with the following elements:
| method | url_pattern | entrypoint | command | Index | id | | method | url_pattern | entrypoint | command | Index | id |
| GET | /listVarDir | /bin/sh -c | ls -la /var \| response /body | 0 | * | | GET | /listVarDir | /bin/sh -c | ls -la /var \| response /body | 0 | * |
| GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 1 | * | | GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 1 | * |
| GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body | 2 | * | | GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body | 2 | * |
Scenario: Removing the last routes. Scenario: Removing the last routes.
When removing the last route the remaining ones will When removing the last route the remaining ones will
maintain their relative order and indexes. maintain their relative order and indexes.
When I delete the last route inserted When I delete the last route inserted
Then I get 200 as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response phrase
And I get an empty response body And I get an empty response body
When I request a routes listing When I request a routes listing
Then I get 200 as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response phrase
And I get a list with the following elements: And I get a list with the following elements:
| method | url_pattern | entrypoint | command | Index | id | | method | url_pattern | entrypoint | command | Index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * |
| GET | /listVarDir | /bin/sh -c | ls -la /var \| response /body | 1 | * | | GET | /listVarDir | /bin/sh -c | ls -la /var \| response /body | 1 | * |
| GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 2 | * | | GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 2 | * |
Scenario: Removing a midst route. Scenario: Removing a midst route.
When removing a midst route the remaining ones will When removing a midst route the remaining ones will
@@ -6,8 +6,8 @@ Feature: Delete routes in Kapow! server.
Routes are removed from the sever by specifying their id. Routes are removed from the sever by specifying their id.
Given I have a running Kapow! server Given I have a running Kapow! server
And It has a route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" And It has a route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
Then I get ok as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response reason phrase
And I get an empty response body And I get an empty response body
@@ -8,18 +8,18 @@ Feature: Kapow! server reject responses with malformed JSON bodies.
the server will respond with a bad request error. the server will respond with a bad request error.
Given I have a running Kapow! server Given I have a running Kapow! server
When I try to insert with this JSON document: When I try to insert with this JSON document:
""" """
{ {
"method" "GET", "method" "GET",
"url_pattern": /hello, "url_pattern": /hello,
"entrypoint": null "entrypoint": null
"command": "echo Hello "command": "echo Hello
World | response /body", World | response /body",
"index": 0, "index": 0,
"id": "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" "id": "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
} }
""" """
Then I get bad request as response code Then I get bad request as response code
And I get "Malformed JSON" as response phrase And I get "Malformed JSON" as response phrase
And I get an empty response body And I get an empty response body
@@ -8,35 +8,35 @@ Feature: Kapow! server reject insert responses with semantic errors.
missing fields. missing fields.
Given I have a running Kapow! server Given I have a running Kapow! server
When I insert the route: When I insert the route:
| entrypoint | command | | entrypoint | command |
| /bin/sh -c | ls -la / \| response /body | | /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code Then I get 422 as response code
And I get "Missing Mandatory Field" as response phrase And I get "Missing Mandatory Field" as response reason phrase
And I get the following entity as response body: And I get the following entity as response body:
| missing_mandatory_fields | | missing_mandatory_fields |
| "url_pattern", "method" | | "url_pattern", "method" |
Scenario: Error because of wrong route specification. Scenario: Error because of wrong route specification.
If a request contains an invalid expression in the If a request contains an invalid expression in the
url_pattern field the server responds with an error. url_pattern field the server responds with an error.
Given I have a running Kapow! server Given I have a running Kapow! server
When I insert the route: When I insert the route:
| method | url_pattern | entrypoint | command | index | | method | url_pattern | entrypoint | command | index |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 |
Then I get unprocessable entity as response code Then I get 422 as response code
And I get "Invalid Route Spec" as response phrase And I get "Invalid Route Spec" as response reason phrase
And I get an empty response body And I get an empty response body
Scenario: Error because of wrong method value. Scenario: Error because of wrong method value.
If a request contains an invalid value in the If a request contains an invalid value in the
method field the server responds with an error. method field the server responds with an error.
Given I have a running Kapow! server Given I have a running Kapow! server
When I insert the route: When I insert the route:
| method | url_pattern | entrypoint | command | index | | method | url_pattern | entrypoint | command | index |
| AVECES | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | | AVECES | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 |
Then I get unprocessable entity as response code Then I get 422 as response code
And I get "Invalid Data Type" as response phrase And I get "Invalid Data Type" as response reason phrase
And I get an empty response body And I get an empty response body
@@ -13,11 +13,11 @@ Feature: Insert new routes in Kapow! server.
A route can be inserted at the begining of the list A route can be inserted at the begining of the list
by specifying an index 0 in the request. by specifying an index 0 in the request.
When I insert the route: When I insert the route:
| method | url_pattern | entrypoint | command | index | | method | url_pattern | entrypoint | command | index |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 |
Then I get ok as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response reason phrase
And I get the following entity as response body: And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id | | method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * |
@@ -27,11 +27,11 @@ Feature: Insert new routes in Kapow! server.
by specifying an index less or equal to the last by specifying an index less or equal to the last
index in the request. index in the request.
When I insert the route: When I insert the route:
| method | url_pattern | entrypoint | command | index | | method | url_pattern | entrypoint | command | index |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 1 | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 1 |
Then I get ok as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response reason phrase
And I get the following entity as response body: And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id | | method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 1 | * | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 1 | * |
+11 -11
View File
@@ -9,10 +9,10 @@ Feature: Listing routes in a Kapow! server
will show an empty list of routes. will show an empty list of routes.
Given I have a just started Kapow! server Given I have a just started Kapow! server
When I request a routes listing When I request a routes listing
Then I get 200 as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response phrase
And I get an empty list And I get an empty list
Scenario: Listing routes on a server with routes loaded. Scenario: Listing routes on a server with routes loaded.
After some route creation/insertion operations the server After some route creation/insertion operations the server
@@ -22,10 +22,10 @@ Feature: Listing routes in a Kapow! server
| method | url_pattern | entrypoint | command | | method | url_pattern | entrypoint | command |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body |
| GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body | | GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body |
When I request a routes listing When I request a routes listing
Then I get 200 as response code Then I get 200 as response code
And I get "OK" as response phrase And I get "OK" as response phrase
And I get a list with the following elements: And I get a list with the following elements:
| method | url_pattern | entrypoint | command | index | id | | method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * | | GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * |
| GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body | 1 | * | | GET | /listDir/{dirname} | /bin/sh -c | ls -la /request/params/dirname \| response /body | 1 | * |
+71 -5
View File
@@ -1,8 +1,11 @@
import subprocess import subprocess
from time import sleep from time import sleep
import shlex
import socket
from contextlib import suppress
import requests import requests
from environconfig import EnvironConfig, StringVar from environconfig import EnvironConfig, StringVar, IntVar
class Env(EnvironConfig): class Env(EnvironConfig):
@@ -15,16 +18,31 @@ class Env(EnvironConfig):
#: Where the Data API is #: Where the Data API is
KAPOW_DATAAPI_URL = StringVar(default="http://localhost:8080") KAPOW_DATAAPI_URL = StringVar(default="http://localhost:8080")
KAPOW_BOOT_TIMEOUT = IntVar(default=10)
@given('I have a just started Kapow! server') @given('I have a just started Kapow! server')
@given('I have a running Kapow! server')
def step_impl(context): def step_impl(context):
context.server = subprocess.Popen( context.server = subprocess.Popen(
Env.KAPOW_SERVER_CMD, shlex.split(Env.KAPOW_SERVER_CMD),
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
shell=True) shell=False)
is_running = context.server.poll() is None
assert is_running, "Server is not running!" # Check process is running with reachable APIs
open_ports = False
for _ in range(Env.KAPOW_BOOT_TIMEOUT):
is_running = context.server.poll() is None
assert is_running, "Server is not running!"
with suppress(requests.exceptions.ConnectionError):
open_ports = (
requests.head(Env.KAPOW_CONTROLAPI_URL, timeout=1).status_code
and requests.head(Env.KAPOW_DATAAPI_URL, timeout=1).status_code)
if open_ports:
break
sleep(1)
assert open_ports, "API is unreachable after KAPOW_BOOT_TIMEOUT"
@when('I request a routes listing') @when('I request a routes listing')
@@ -69,3 +87,51 @@ def step_impl(context):
assert header in entry, f"Response does not contain the key {header}" assert header in entry, f"Response does not contain the key {header}"
if row[header] != '*': if row[header] != '*':
assert entry[header] == row[header], f"Values mismatch" assert entry[header] == row[header], f"Values mismatch"
#
#
#
@when('I append the route')
def step_impl(context):
if not hasattr(context, 'table'):
raise RuntimeError("A table must be set for this step.")
for row in context.table:
response = requests.post(f"{Env.KAPOW_CONTROLAPI_URL}/routes",
json={h: row[h] for h in row.headings})
response.raise_for_status()
@then('I get {code} as response code')
def step_impl(context, code):
raise NotImplementedError('STEP: Then I get unprocessable entity as response code')
@then('I get "{reason}" as response reason phrase')
def step_impl(context, reason):
raise NotImplementedError('STEP: Then I get "Missing Mandatory Field" as response phrase')
@then('I get the following entity as response body')
def step_impl(context):
raise NotImplementedError('STEP: Then I get the following entity as response body')
@then('I get an empty response body')
def step_impl(context):
raise NotImplementedError('STEP: Then I get an empty response body')
@when('I delete the route with id "{id}"')
def step_impl(context, id):
raise NotImplementedError('STEP: When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"')
@given('It has a route with id "{id}"')
def step_impl(context, id):
raise NotImplementedError('STEP: Given It has a route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"')
@when('I insert the route')
def step_impl(context):
raise NotImplementedError('STEP: When I insert the route')