Passed
Push — master ( 1a0948...80a4c8 )
by Amresh
01:23
created

fastest.bodies.test_case_template_builder   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 269
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 17
eloc 61
dl 0
loc 269
rs 10
c 0
b 0
f 0

9 Functions

Rating   Name   Duplication   Size   Complexity  
A get_params_list() 0 15 1
A create_assertion_test() 0 34 3
A create_type_test_case() 0 29 1
A is_type_test_ready() 0 29 1
A create_type_test_case_if_params() 0 30 2
A create_naive_test_case() 0 60 3
A convert_arg_to_py() 0 15 3
A case_generator() 0 11 2
A get_empty_of_type() 0 21 1
1
import re
2
import uuid
3
from pydoc import locate
4
from fastest.constants import Keys, Content
5
6
7
def case_generator(uuid_val=None):
8
    """
9
    ----
10
    examples:
11
    1) case_generator('a55eff11-ed51-ecb37-ccba') -> 'A55EFF11ED'
12
    ----
13
    Use uuid to create test-case unique name
14
    :return:
15
    """
16
    uuid_val = uuid_val if uuid_val is not None else str(uuid.uuid4())
17
    return str(uuid_val).upper().replace("-", "")[0:10]
18
19
20
def get_empty_of_type(input_type):
21
    """
22
    Return an empty form of a given type
23
    ----
24
    examples:
25
26
    1) get_empty_of_type('str') -> "''"
27
    2) get_empty_of_type('???') -> None
28
    ----
29
    :param input_type: str
30
    :return: str
31
    """
32
    empty_type = {
33
        'str': '\'\'',
34
        'int': '0',
35
        'list': '[]',
36
        'dict': '{}',
37
        '': '\'\''
38
    }
39
40
    return empty_type.get(input_type)
41
42
43
def get_params_list(params):
44
    """
45
    ----
46
    examples:
47
48
    1) get_params_list(['str', 'str', 'list', 'dict']) -> ["''", "''", '[]', '{}']
49
    2) get_params_list(['str', '???']) -> ["''"]
50
    ----
51
    :param params: list
52
    :return: list
53
    """
54
    return [
55
        get_empty_of_type(param)
56
        for param in params
57
        if param in ['str', 'int', 'list', 'dict']
58
    ]
59
60
61
def create_type_test_case(function_object, params):
62
    """
63
    Create test case for checking types of function
64
    -----
65
    examples:
66
67
    @need
68
    from fastest.constants import TestBodies
69
    @end
70
71
    @let
72
    function_object = {
73
        'tests': {
74
            'return': 'str'
75
        },
76
        'name': 'function_1'
77
    }
78
    params = ['str', 'str']
79
    @end
80
81
    1) create_type_test_case(function_object, params) -> TestBodies.TYPE_TEST_CASE_1
82
    -----
83
    :param function_object: dict
84
    :param params: list
85
    :return: str
86
    """
87
    empty_param_call = '{}({})'.format(function_object.get(Keys.NAME), ', '.join(params))
88
    return Content.TYPE_ASSERT_TEMPLATE.format(
89
        function=empty_param_call, value=function_object.get(Keys.TESTS, {}).get(Keys.RETURN)
90
    )
91
92
93
def create_type_test_case_if_params(function_object, params):
94
    """
95
    Create type test case if there is info over params and return
96
    ----
97
    examples:
98
99
    @need
100
    from fastest.constants import TestBodies
101
    @end
102
103
    @let
104
    function_object = {
105
        'tests': {
106
            'return': 'str'
107
        },
108
        'name': 'function_1'
109
    }
110
111
    params = ['str', 'str']
112
    @end
113
114
    1) create_type_test_case_if_params(function_object, params) -> TestBodies.TYPE_TEST_CASE_2
115
    ----
116
    :param function_object: dict
117
    :param params: list
118
    :return: str
119
    """
120
    return create_type_test_case(function_object, params)\
121
        if is_type_test_ready(function_object, params)\
122
        else ''
123
124
125
def is_type_test_ready(function_object, params):
126
    """
127
    if a function has params and return type specified, return True
128
    else False
129
    ----
130
    examples:
131
132
    @let
133
    function_object_1 = {
134
        'tests': {
135
            'return': 'str'
136
        }
137
    }
138
139
    function_object_2 = {'tests': {}}
140
141
    params = ['str', 'str']
142
    @end
143
144
    1) is_type_test_ready(function_object_1, params) -> True
145
    2) is_type_test_ready(function_object_2, params) -> False
146
    3) is_type_test_ready(function_object_1, []) -> False
147
    ----
148
    :param function_object: dict
149
    :param params: list
150
    :return: bool
151
    """
152
    return_type = function_object.get(Keys.TESTS, {}).get(Keys.RETURN)
153
    return bool(return_type and len(params) > 0)
154
155
156
def create_assertion_test(function_object):
157
    """
158
    Create assertion test cases by embedding into the template strings
159
    if examples are present in the docstrings
160
    -----
161
    examples:
162
163
    @need
164
    from fastest.constants import TestBodies
165
    @end
166
167
    @let
168
    function_object_1 = {
169
        'tests': {
170
            'variables': ['a = 5']
171
        }
172
    }
173
174
    function_object_2 = {'tests': {'variables': []}}
175
176
    params = ['str', 'str']
177
    @end
178
179
    1) create_assertion_test(function_object_1) -> TestBodies.ASSERTION_TEST_1
180
    2) create_assertion_test(function_object_2) -> ''
181
    -----
182
    :param function_object: dict
183
    :return: str
184
    """
185
    template = ''
186
    if function_object.get(Keys.TESTS, {}).get(Keys.VARIABLES):
187
        for variable in function_object.get(Keys.TESTS, {}).get(Keys.VARIABLES, []):
188
            template += Content.VARIABLES_TEMPLATE.format(variables=variable)
189
    return template
190
191
192
def convert_arg_to_py(arg):
193
    """
194
    ---
195
    1) convert_arg_to_py('None') -> None
196
    2) convert_arg_to_py('???') -> '???'
197
    3) convert_arg_to_py({}) -> {}
198
    ---
199
    :param arg:
200
    :return:
201
    """
202
    try:
203
        parsed_arg = locate(arg)
204
        return arg if parsed_arg is None and arg != 'None' else parsed_arg
205
    except Exception:
206
        return arg
207
208
209
def create_naive_test_case(function_object, test, test_id=None):
210
    """
211
    Create test cases from the assertions, docstring params and return types
212
    ----
213
    examples:
214
215
    @need
216
    from fastest.constants import TestBodies
217
    @end
218
219
    @let
220
    function_object = {
221
        'tests': {
222
            'return': 'str',
223
            'variables': ['a = 5']
224
        },
225
        'name': 'function_1'
226
    }
227
228
    test = {
229
        'from': 'function_1',
230
        'expect': '2'
231
    }
232
233
    exception_test = {
234
        'from': 'function_2(None)',
235
        'exception': 'TypeError'
236
    }
237
238
    test_id = 'a55eff11-ed51-ecb37-ccba'
239
    @end
240
    1) create_naive_test_case(function_object, test, test_id) -> TestBodies.NAIVE_TEST_RESULT
241
    2) create_naive_test_case(function_object, exception_test, test_id) -> TestBodies.EXCEPTION_TEST_RESULT
242
    ----
243
    :param function_object: dict
244
    :param test: dict
245
    :param test_id: str
246
    :return: str
247
    """
248
    test_template = Content.TEST_CASE_TEMPLATE.format(
249
        function_name=function_object.get(Keys.NAME),
250
        case_id=case_generator(test_id),
251
    )
252
253
    params = get_params_list(function_object.get(Keys.TESTS, {}).get(Keys.PARAMS, []))
254
255
    test_template += create_type_test_case_if_params(function_object, params)
256
    test_template += create_assertion_test(function_object)
257
258
    if test.get(Keys.EXPECT):
259
        test_template += Content.ASSERTION_TEMPLATE.format(function=test.get(Keys.FROM), value=test.get(Keys.EXPECT))
260
    elif test.get(Keys.EXCEPTION):
261
        args = re.search(r'\((.*)\)', test.get(Keys.FROM))
262
        args = [convert_arg_to_py(arg.strip()) for arg in args.group(1).split(',')]
263
        test_template += Content.EXCEPTION_TEMPLATE.format(
264
            function=function_object.get(Keys.NAME),
265
            value=test.get(Keys.EXCEPTION),
266
            args=args
267
        )
268
    return test_template
269