Passed
Push — master ( 573721...f12193 )
by Raúl
01:10
created

tests.test_parser   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 14
eloc 85
dl 0
loc 124
rs 10
c 0
b 0
f 0

7 Functions

Rating   Name   Duplication   Size   Complexity  
A _load_json_file() 0 4 2
A test_sources_parsed_correctly() 0 12 2
A test_validation_fails_with_invalid_definition() 0 18 4
A test_rules_parsed_correctly() 0 8 2
A test_engines_parsed_correctly() 0 9 2
A test_valid_test_definition() 0 8 1
A test_fully_parsed_engine() 0 24 1
1
import json
2
from pathlib import Path
3
4
import pytest
5
from jsonschema import ValidationError
6
7
from decision_engine import parser
8
9
10
tests_dir = Path(__file__).parents[0]
11
schema_dir = tests_dir.parents[0] / 'decision_engine'
12
13
schema_file = 'schema.json'
14
schema_path = (schema_dir / schema_file).absolute()
15
16
test_definition = 'test_definition.json'
17
definition_path = (tests_dir / test_definition).absolute()
18
19
nested_sources_def = 'test_nested_sources.json'
20
nested_sources_def_path = (tests_dir / nested_sources_def)
21
22
full_def = 'full_definition.json'
23
full_def_path = (tests_dir / full_def)
24
25
26
def _load_json_file(file: str) -> dict:
27
    with (open(file)) as fp:
28
        contents = json.load(fp)
29
    return contents
30
31
32
@pytest.mark.parametrize('definition_file', [
33
    definition_path,
34
    nested_sources_def_path,
35
    full_def_path
36
])
37
def test_sources_parsed_correctly(definition_file):
38
    definition = _load_json_file(definition_file)
39
    sources = parser.parse_sources(definition['sources'])
40
    assert len(sources) == len(definition['sources'])
41
    for i in range(len(definition['sources'])):
42
        assert sources[i].name == definition['sources'][i]['name']
43
        assert type(sources[i]).__name__ == definition['sources'][i]['class']
44
45
46
def test_rules_parsed_correctly():
47
    definition = _load_json_file(definition_path)
48
    sources = parser.parse_sources(definition['sources'])
49
    rules = parser.parse_rules(definition['rules'], sources)
50
    assert len(rules) == len(definition['rules'])
51
    for i in range(len(definition['rules'])):
52
        assert rules[i].name == definition['rules'][i]['name']
53
        assert type(rules[i]).__name__ == definition['rules'][i]['class']
54
55
56
def test_engines_parsed_correctly():
57
    definition = _load_json_file(definition_path)
58
    sources = parser.parse_sources(definition['sources'])
59
    rules = parser.parse_rules(definition['rules'], sources)
60
    engines = parser.parse_engines(definition['engines'], rules)
61
    assert len(engines) == len(definition['engines'])
62
    for i in range(len(definition['engines'])):
63
        assert engines[i].name == definition['engines'][i]['name']
64
        assert len(engines[i].rules) == len(rules)
65
66
67
def test_valid_test_definition():
68
    """
69
    Make sure our test definition is valid,
70
    otherwise there's no point in using it for testing.
71
    """
72
    schema = _load_json_file(schema_path)
73
    definition = _load_json_file(definition_path)
74
    parser.validate(definition, schema)
75
76
77
@pytest.mark.parametrize("air_miles, land_miles, age, vip, expected", [
78
    (500, 100, 37, 'yes', True),
79
    (150, 100, 37, 'yes', False),
80
    (500, 501, 37, 'yes', False),
81
    (500, 100, 16, 'yes', False),
82
    (500, 100, 70, 'yes', False),
83
    (500, 100, 37, 'no', False),
84
    (10, 50, 15, 'no', False)
85
])
86
def test_fully_parsed_engine(air_miles, land_miles, age, vip, expected):
87
    engines = parser.parse_json_file(full_def_path)
88
89
    print(engines)
90
91
    engine = engines['engines'][0]
92
93
    data = {
94
        'air_miles': air_miles,
95
        'land_miles': land_miles,
96
        'age': age,
97
        'vip': vip
98
    }
99
100
    assert engine.decide(data) == expected
101
102
103
# These are probably not needed, since what we're really doing here is
104
# testing that jsonschema validates correctly, which should be done in
105
# its own package, not here.
106
def test_validation_fails_with_invalid_definition():
107
    schema = _load_json_file(schema_path)
108
    definition = _load_json_file(definition_path)
109
110
    definition_without_sources = definition.copy()
111
    del definition_without_sources['sources']
112
    with pytest.raises(ValidationError):
113
        parser.validate(definition_without_sources, schema)
114
115
    definition_without_rules = definition.copy()
116
    del definition_without_rules['rules']
117
    with pytest.raises(ValidationError):
118
        parser.validate(definition_without_rules, schema)
119
120
    definition_without_engines = definition.copy()
121
    del definition_without_engines['engines']
122
    with pytest.raises(ValidationError):
123
        parser.validate(definition_without_engines, schema)
124