This commit is contained in:
Héctor Hurtado
2019-08-21 11:07:23 +02:00
7 changed files with 127 additions and 34 deletions
+3 -1
View File
@@ -1,5 +1,7 @@
wip:
pipenv run behave --stop --wip
test:
gherkin-lint
pipenv run behave --no-capture --stop
pipenv run behave --no-capture
catalog:
pipenv run behave --steps-catalog
@@ -8,7 +8,7 @@ Feature: Kapow! server reject append requests with malformed JSON bodies.
the server will respond with a bad request error.
Given I have a running Kapow! server
When I try to append with this JSON document:
When I try to append with this malformed JSON document:
"""
{
"method" "GET",
@@ -20,5 +20,5 @@ Feature: Kapow! server reject append requests with malformed JSON bodies.
}
"""
Then I get 400 as response code
And I get "Malformed JSON" as response phrase
And I get "Malformed JSON" as response reason phrase
And I get an empty response body
@@ -21,5 +21,5 @@ Feature: Kapow! server reject insert requests with malformed JSON bodies.
}
"""
Then I get bad request as response code
And I get "Malformed JSON" as response phrase
And I get "Malformed JSON" as response reason phrase
And I get an empty response body
+38
View File
@@ -0,0 +1,38 @@
from functools import singledispatch
def assert_same_type(f):
def wrapper(a, b):
if type(a) != type(b):
raise TypeError("Non-matching types")
return f(a, b)
return wrapper
@singledispatch
@assert_same_type
def is_subset(model, obj):
return model == obj
@is_subset.register(dict)
@assert_same_type
def _(model, obj):
for key, value in model.items():
if key not in obj or not is_subset(value, obj[key]):
return False
return True
@is_subset.register(list)
@assert_same_type
def _(model, obj):
if type(model) != type(obj):
raise TypeError("Non-matching types")
return is_subset(set(model), set(obj))
@is_subset.register(set)
@assert_same_type
def _(model, obj):
return model <= obj
+56 -21
View File
@@ -1,12 +1,15 @@
import subprocess
from contextlib import suppress
from time import sleep
import json
import shlex
import socket
from contextlib import suppress
import subprocess
import requests
from environconfig import EnvironConfig, StringVar, IntVar
from environconfig import EnvironConfig, StringVar, IntVar, BooleanVar
from comparedict import is_subset
import logging
class Env(EnvironConfig):
#: How to run Kapow! server
@@ -20,9 +23,30 @@ class Env(EnvironConfig):
KAPOW_BOOT_TIMEOUT = IntVar(default=10)
@given('I have a just started Kapow! server')
@given('I have a running Kapow! server')
def step_impl(context):
KAPOW_DEBUG_TESTS = BooleanVar(default=True)
if Env.KAPOW_DEBUG_TESTS:
# These two lines enable debugging at httplib level
# (requests->urllib3->http.client) You will see the REQUEST,
# including HEADERS and DATA, and RESPONSE with HEADERS but without
# DATA. The only thing missing will be the response.body which is
# not logged.
try:
import http.client as http_client
except ImportError:
# Python 2
import httplib as http_client
http_client.HTTPConnection.debuglevel = 1
# You must initialize logging, otherwise you'll not see debug output.
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
def run_kapow_server(context):
context.server = subprocess.Popen(
shlex.split(Env.KAPOW_SERVER_CMD),
stdout=subprocess.DEVNULL,
@@ -44,6 +68,11 @@ def step_impl(context):
assert open_ports, "API is unreachable after KAPOW_BOOT_TIMEOUT"
@given('I have a just started Kapow! server')
@given('I have a running Kapow! server')
def step_impl(context):
run_kapow_server(context)
@when('I request a routes listing')
def step_impl(context):
@@ -58,13 +87,7 @@ def step_impl(context):
@given('I have a Kapow! server whith the following routes')
def step_impl(context):
context.server = subprocess.Popen(
Env.KAPOW_SERVER_CMD,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True)
is_running = context.server.poll() is None
assert is_running, "Server is not running!"
run_kapow_server(context)
if not hasattr(context, 'table'):
raise RuntimeError("A table must be set for this step.")
@@ -97,30 +120,32 @@ 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()
row = context.table[0]
context.response = requests.post(f"{Env.KAPOW_CONTROLAPI_URL}/routes",
json={h: row[h] for h in row.headings})
@then('I get {code} as response code')
def step_impl(context, code):
raise NotImplementedError('STEP: Then I get unprocessable entity as response code')
assert context.response.status_code == int(code), f"Got {context.response.status_code} instead"
@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')
assert context.response.reason == reason, f"Got {context.response.reason} instead"
@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')
for row in context.table:
for name, value in row.items():
assert name in context.response.json(), f"Field {name} not present in {context.response.json()}"
assert set(json.loads(value)) == set(context.response.json()[name])
@then('I get an empty response body')
def step_impl(context):
raise NotImplementedError('STEP: Then I get an empty response body')
assert context.response.content == b'', f"Response body is not empty. Got {context.response.content} instead."
@when('I delete the route with id "{id}"')
@@ -132,6 +157,16 @@ def step_impl(context, 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')
@when('I try to append with this malformed JSON document')
@when('I try to append with this JSON document')
def step_impl(context):
context.response = requests.post(
f"{Env.KAPOW_CONTROLAPI_URL}/routes",
headers={"Content-Type": "application/json"},
data=context.text)