Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce pydantic to validate Oxygen handler result values #44

Merged
merged 9 commits into from
Oct 27, 2023
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ Then `results_robot_output.xml` will be created under `path/to/`.

### [Read the developer guide on how to write your own handler](DEVGUIDE.md)

You might also want to look at [specification for handler results](handler_result_specification.md)

### Configuring your handler to Oxygen

Oxygen knows about different handlers based on the [`config.yml`](https://github.com/eficode/robotframework-oxygen/blob/master/config.yml) file. This configuration file can be interacted with through Oxygen's command line.
Expand Down
132 changes: 132 additions & 0 deletions handler_result_specification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Oxygen handler result specification
```
{
"$defs": {
"OxygenKeywordDict": {
"properties": {
"pass": {
"title": "Pass",
"type": "boolean"
},
"name": {
"title": "Name",
"type": "string"
},
"elapsed": {
"title": "Elapsed",
"type": "number"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"messages": {
"items": {
"type": "string"
},
"title": "Messages",
"type": "array"
},
"teardown": {
"$ref": "#/$defs/OxygenKeywordDict"
},
"keywords": {
"items": {
"$ref": "#/$defs/OxygenKeywordDict"
},
"title": "Keywords",
"type": "array"
}
},
"required": [
"pass",
"name"
],
"title": "OxygenKeywordDict",
"type": "object"
},
"OxygenSuiteDict": {
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"setup": {
"$ref": "#/$defs/OxygenKeywordDict"
},
"teardown": {
"$ref": "#/$defs/OxygenKeywordDict"
},
"suites": {
"items": {
"$ref": "#/$defs/OxygenSuiteDict"
},
"title": "Suites",
"type": "array"
},
"tests": {
"items": {
"$ref": "#/$defs/OxygenTestCaseDict"
},
"title": "Tests",
"type": "array"
}
},
"required": [
"name"
],
"title": "OxygenSuiteDict",
"type": "object"
},
"OxygenTestCaseDict": {
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"keywords": {
"items": {
"$ref": "#/$defs/OxygenKeywordDict"
},
"title": "Keywords",
"type": "array"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"setup": {
"$ref": "#/$defs/OxygenKeywordDict"
},
"teardown": {
"$ref": "#/$defs/OxygenKeywordDict"
}
},
"required": [
"name",
"keywords"
],
"title": "OxygenTestCaseDict",
"type": "object"
}
},
"allOf": [
{
"$ref": "#/$defs/OxygenSuiteDict"
}
]
}
```
50 changes: 0 additions & 50 deletions parser_specification.md

This file was deleted.

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
robotframework>=3.0.4
junitparser==2.0
PyYAML>=3.13
pydantic>=2.4.2

### Dev
mock>=2.0.0
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
install_requires=[
'robotframework>=3.0.4',
'junitparser==2.0',
'PyYAML>=3.13'
'PyYAML>=3.13',
'pydantic>=2.4.2'
],
packages=find_packages(SRC),
package_dir={'': 'src'},
Expand Down
9 changes: 7 additions & 2 deletions src/oxygen/base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from inspect import signature, Parameter

from oxygen.errors import MismatchArgumentException
from .errors import MismatchArgumentException
from .robot_interface import (RobotInterface, get_keywords_from,
set_special_keyword)

from .utils import validate_with_deprecation_warning

class BaseHandler(object):
DEFAULT_CLI = {tuple(['result_file']): {}}
Expand Down Expand Up @@ -132,6 +132,8 @@ def _build_results(self, keyword, setup_keyword, teardown_keyword):
f'parse_results expects at least {accepted_params_min} '
'arguments but got 1')

self._validate(test_results)

_, result_suite = self._interface.result.build_suite(
100000, test_results)

Expand All @@ -149,6 +151,9 @@ def _build_results(self, keyword, setup_keyword, teardown_keyword):

self._inject_suite_report(test, result_suite)

def _validate(self, oxygen_result_dict):
validate_with_deprecation_warning(oxygen_result_dict, self)

def _inject_suite_report(self, test, result_suite):
'''Add the given suite to the parent suite of the test case.

Expand Down
4 changes: 4 additions & 0 deletions src/oxygen/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ class MismatchArgumentException(Exception):

class InvalidConfigurationException(Exception):
pass


class InvalidOxygenResultException(Exception):
pass
9 changes: 0 additions & 9 deletions src/oxygen/gatling.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ def _transform_tests(self, result_file):
keyword = {
'name': ' | '.join(columns),
'pass': True,
'tags': [],
'messages': [],
'teardown': [],
'keywords': [],
}

if status == 'KO':
Expand All @@ -77,9 +74,6 @@ def _transform_tests(self, result_file):

test_case = {
'name': step_name,
'tags': [],
'setup': [],
'teardown': [],
'keywords': [keyword]
}

Expand All @@ -88,9 +82,6 @@ def _transform_tests(self, result_file):
test_suite = {
'name': 'Gatling Scenario',
'tags': self._tags,
'setup': [],
'teardown': [],
'suites': [],
'tests': test_cases,
}

Expand Down
9 changes: 0 additions & 9 deletions src/oxygen/junit.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ def _transform_tests(self, node):
suite_dict = {
'name': 'JUnit Execution',
'tags': self._tags,
'setup': [],
'teardown': [],
'suites': [],
'tests': [],
}

if isinstance(node, JUnitXmlTestSuite):
Expand All @@ -63,8 +60,6 @@ def _transform_test_suite(self, test_suite):
suite_dict = {
'name': test_suite.name,
'tags': [],
'setup': [],
'teardown': [],
'suites': [],
'tests': [],
}
Expand All @@ -91,9 +86,7 @@ def _transform_test_case(self, test_case):
test_dict = {
'name': '{} (Execution)'.format(test_case.name),
'pass': True,
'tags': [],
'messages': [],
'teardown': [],
'keywords': [],
}

Expand Down Expand Up @@ -126,8 +119,6 @@ def _transform_test_case(self, test_case):
test_case_dict = {
'name': test_case.name,
'tags': [],
'setup': [],
'teardown': [],
'keywords': [
test_dict,
],
Expand Down
2 changes: 2 additions & 0 deletions src/oxygen/oxygen.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
InvalidConfigurationException,
ResultFileNotFoundException)
from .robot_interface import RobotInterface
from .utils import validate_with_deprecation_warning
from .version import VERSION


Expand Down Expand Up @@ -301,6 +302,7 @@ def convert_to_robot_result(self, args):
output_filename = self.get_output_filename(args.get('result_file'))
parsed_results = args['func'](
**{k: v for (k, v) in args.items() if not callable(v)})
validate_with_deprecation_warning(parsed_results, args['func'])
robot_suite = RobotInterface().running.build_suite(parsed_results)
robot_suite.run(output=output_filename,
log=None,
Expand Down
Loading