Skip to content

Commit

Permalink
Add request.execute() function
Browse files Browse the repository at this point in the history
  • Loading branch information
otto-ifak committed May 29, 2024
1 parent b2a8cdf commit 8c21e55
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 26 deletions.
19 changes: 5 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,7 @@ description = {

graph = parse_open_api(description)
for i in graph.generate_paths():
test_case = graph.execute(i.path)
request = test_case.to_request()
request = graph.execute(i.path)
request.dump()
```

Expand Down Expand Up @@ -403,13 +402,11 @@ PATCH /videos/0
PATCH /videos/0
BODY: true
PATCH /videos/0
PATCH /videos/0
PATCH /videos/0
```
</details>

Please note, that Fences does not include a client to execute these tests.
You can do this on your own, for example using the `requests` library:
You can execute the generated tests using the `request.execute()` method.
Please note, that you need to install the `requests` library for this.

```python
import requests
Expand All @@ -418,15 +415,9 @@ import requests

graph = parse_open_api(description)
for i in graph.generate_paths():
test_case = graph.execute(i.path)
request = test_case.to_request()
request = graph.execute(i.path)
request.dump()
requests.request(
url='http://localhost:8080' + test_case.path,
method=test_case.operation.method,
data=request.body,
headers=dict(request.headers),
)
request.execute('http://localhost:8080')
```

</details>
Expand Down
43 changes: 34 additions & 9 deletions fences/open_api/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,31 @@

@dataclass
class Request:
operation: Operation
path: str
method: str
headers: ListOfPairs
body: Optional[str]

def dump(self, body_max_chars=80):
print(f"{self.method.upper()} {self.path}")
print(f"{self.operation.method.upper()} {self.path}")
if self.body:
if len(self.body) > body_max_chars:
b = self.body[:body_max_chars] + '...'
else:
b = self.body
print(f" BODY: {b}")

def execute(self, host: str):
import requests # optional dependency
if host.endswith('/'):
host = host[:-1]
requests.request(
url=host + self.path,
method=self.operation.method,
data=self.body,
headers=dict(self.headers)
)


@dataclass
class TestCase:
Expand All @@ -56,12 +67,21 @@ def to_request(self) -> Request:
body = json.dumps(self.body)
return Request(
path=path,
method=self.operation.method,
headers=headers,
body=body,
operation=self.operation
)


class ExtractRequestLeaf(Leaf):

def apply(self, data: TestCase) -> any:
return data.to_request()

def description(self) -> str:
return "Convert to request"


class StartTestCase(Decision):
def __init__(self, path: str, operation: Operation) -> None:
super().__init__(operation.operation_id, True)
Expand All @@ -71,6 +91,9 @@ def __init__(self, path: str, operation: Operation) -> None:
def apply(self, data: any) -> any:
return TestCase(self.path, self.operation)

def description(self) -> str:
return "Start Test Case"


class InsertParamLeaf(Leaf):
def __init__(self, is_valid: bool, parameter: Parameter, value: any) -> None:
Expand Down Expand Up @@ -152,13 +175,13 @@ def add(self, schema: any, components: Dict[str, any]) -> Samples:

def parse(open_api: any) -> Node:
openapi: OpenApi = OpenApi.from_dict(open_api)
super_root = NoOpDecision()
sample_cache = SampleCache()

# Create graph
root = NoOpDecision()
for path in openapi.paths:
for operation in path.operations:
root = StartTestCase(path.path, operation)
op_root = StartTestCase(path.path, operation)
for param in operation.parameters:
param_root = NoOpDecision(f"{operation.operation_id}/{param.name}")
samples = sample_cache.add(param.schema, openapi.components)
Expand All @@ -168,7 +191,7 @@ def parse(open_api: any) -> Node:
param_root.add_transition(InsertParamLeaf(False, param, sample))
if param.position != ParameterPosition.PATH:
param_root.add_transition(NoOpLeaf(is_valid=not param.required))
root.add_transition(param_root)
op_root.add_transition(param_root)
if operation.request_body:
body_root = NoOpDecision('BODY')
bodies = sample_cache.add(operation.request_body.schema, openapi.components)
Expand All @@ -177,6 +200,8 @@ def parse(open_api: any) -> Node:
for body in bodies.invalid:
body_root.add_transition(InsertBodyLeaf(False, body))
body_root.add_transition(NoOpLeaf(is_valid=not operation.request_body.required))
root.add_transition(body_root)
super_root.add_transition(root)
return super_root
op_root.add_transition(body_root)
op_root.add_transition(ExtractRequestLeaf())
root.add_transition(op_root)

return root
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ coverage>=6.3
PyYAML>=5.3
json-schema-tool==0.1.0
hypothesis-jsonschema==0.23.0
requests>=2
5 changes: 2 additions & 3 deletions test/open_api/test_generate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from fences.open_api.generate import parse, TestCase
from fences.open_api.generate import parse, Request
from fences.core.render import render

import unittest
Expand All @@ -16,8 +16,7 @@ def check(self, schema, debug=False):
render(graph).write_svg('graph.svg')

for i in graph.generate_paths():
test_case: TestCase = graph.execute(i.path)
request = test_case.to_request()
request: Request = graph.execute(i.path)
if debug:
request.dump()

Expand Down

0 comments on commit 8c21e55

Please sign in to comment.