Browse Source

Unittest improvements (output)

master
Dirk Alders 3 years ago
parent
commit
ecec65be06
6 changed files with 578 additions and 359 deletions
  1. 297
    0
      jsonlog.py
  2. 16
    148
      module_status.py
  3. 81
    0
      output.py
  4. 173
    199
      run.py
  5. 10
    11
      scripts/Makefile
  6. 1
    1
      scripts/unittest.py

+ 297
- 0
jsonlog.py View File

1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+#
4
+
5
+import json
6
+import os
7
+import subprocess
8
+
9
+import fstools
10
+from unittest.output import STATUS_AVAILABLE, STATUS_CHANGED, STATUS_CLEAN, STATUS_EXISTS, STATUS_IN_WORK, STATUS_MISSING, STATUS_OLD, STATUS_RELEASED, STATUS_UNKNOWN
11
+
12
+JSONLOG_FNAME = 'unittest.json'
13
+
14
+
15
+#
16
+# MAIN KEYS
17
+#
18
+MAIN_KEY_COVERAGE_INFO = 'coverage_information'
19
+MAIN_KEY_LOST_SOULS = "lost_souls"
20
+MAIN_KEY_SPECIFICATION = 'specification'
21
+MAIN_KEY_SYSTEM_INFO = 'system_information'
22
+MAIN_KEY_TESTOBJECT_INFO = 'testobject_information'
23
+MAIN_KEY_TESTRUNS = 'testrun_list'
24
+MAIN_KEY_UNITTEST_INFO = 'unittest_information'
25
+#
26
+# SUBKEYS FOR MAIN_KEY_COVERAGE_INFO
27
+#
28
+COVI_KEY_NAME = 'name'
29
+COVI_KEY_FILEPATH = 'filepath'
30
+COVI_KEY_LINE_COVERAGE = 'line_coverage'
31
+COVI_KEY_BRANCH_COVERAGE = 'branch_coverage'
32
+COVI_KEY_FILES = 'files'
33
+#
34
+# SUBKEYS FOR MAIN_KEY_LOST_SOULS
35
+#
36
+LOST_ITEMLIST = "item_list"
37
+LOST_TESTCASELIST = "testcase_list"
38
+#
39
+# SUBKEYS FOR MAIN_KEY_SPECIFICATION
40
+#
41
+SPEC_ITEM_DICT = 'item_dict'
42
+#
43
+# SUBKEYS FOR MAIN_KEY_SYSTEM_INFO
44
+#
45
+SYSI_ARCHITECTURE = "Architecture"
46
+SYSI_DISTRIBUTION = "Distribution"
47
+SYSI_HOSTNAME = "Hostname"
48
+SYSI_KERNEL = "Kernel"
49
+SYSI_MACHINE = "Machine"
50
+SYSI_PATH = "Path"
51
+SYSI_SYSTEM = "System"
52
+SYSI_USERNAME = "Username"
53
+#
54
+# SUBKEYS FOR MAIN_KEY_TESTOBJECT_INFO
55
+#
56
+TOBI_DEPENDENCIES = "Dependencies"
57
+TOBI_DESCRIPTION = "Description"
58
+TOBI_NAME = "Name"
59
+TOBI_STATE = "State"
60
+TOBI_STATE_RELESED = 'Released'
61
+TOBI_STATE_IN_DEVELOPMENT = 'In development'
62
+TOBI_SUPP_INTERP = "Supported Interpreters"
63
+TOBI_VERSION = "Version"
64
+#
65
+# SUBKEYS FOR MAIN_KEY_TESTRUNS
66
+#
67
+TRUN_TESTCASES = 'testcases'
68
+#
69
+# SUBKEYS FOR MAIN_KEY_UNITTEST_INFO
70
+#
71
+UTEI_VERSION = TOBI_VERSION
72
+
73
+
74
+def get_lib_folder(ut_folder):
75
+    return os.path.join(ut_folder, 'pylibs', os.path.basename(ut_folder))
76
+
77
+
78
+def get_ut_config(ut_folder):
79
+    return os.path.join(get_ut_src_folder(ut_folder), 'config.py')
80
+
81
+
82
+def get_ut_testcase_folder(ut_folder):
83
+    return os.path.join(get_ut_src_folder(ut_folder), 'tests')
84
+
85
+
86
+def get_ut_testresult_folder(ut_folder):
87
+    return os.path.join(get_ut_subfolder(ut_folder), 'testresults')
88
+
89
+
90
+def get_lib_testresult_folder(ut_folder):
91
+    return os.path.join(get_lib_folder(ut_folder), '_testresults_')
92
+
93
+
94
+def get_lib_jsonlog(ut_folder):
95
+    return os.path.join(get_lib_testresult_folder(ut_folder), JSONLOG_FNAME)
96
+
97
+
98
+def get_ut_jsonlog(ut_folder):
99
+    return os.path.join(get_ut_testresult_folder(ut_folder), JSONLOG_FNAME)
100
+
101
+
102
+def get_ut_src_folder(ut_folder):
103
+    return os.path.join(get_ut_subfolder(ut_folder), 'src')
104
+
105
+
106
+def get_ut_subfolder(ut_folder):
107
+    return os.path.join(ut_folder, 'unittest')
108
+
109
+
110
+def module_uid(path):
111
+    return fstools.uid_filelist(path, '*.py', rekursive=True)
112
+
113
+
114
+def __get_release_state__(ut_folder, lib):
115
+    if lib:
116
+        fn = get_lib_jsonlog(ut_folder)
117
+    else:
118
+        fn = get_ut_jsonlog(ut_folder)
119
+    try:
120
+        with open(fn, 'r') as fh:
121
+            ut_data = json.loads(fh.read())
122
+    except IOError:
123
+        return STATUS_MISSING
124
+    else:
125
+        ut_status = ut_data.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_STATE, 'unknown')
126
+        if 'released' in ut_status.lower():
127
+            return STATUS_RELEASED
128
+        elif 'work' in ut_status.lower():
129
+            return STATUS_IN_WORK
130
+        else:
131
+            return STATUS_UNKNOWN
132
+
133
+
134
+def get_lib_release_state(ut_folder):
135
+    return __get_release_state__(ut_folder, True)
136
+
137
+
138
+def get_ut_release_state(ut_folder):
139
+    return __get_release_state__(ut_folder, False)
140
+
141
+
142
+def __get_testcase_integrity__(ut_folder, lib):
143
+    if lib:
144
+        fn = get_lib_jsonlog(ut_folder)
145
+    else:
146
+        fn = get_ut_jsonlog(ut_folder)
147
+    try:
148
+        with open(fn, 'r') as fh:
149
+            ut_data = json.loads(fh.read())
150
+    except IOError:
151
+        return STATUS_MISSING
152
+    else:
153
+        tc_version = ut_data.get(MAIN_KEY_UNITTEST_INFO, {}).get(UTEI_VERSION)
154
+        current_version = module_uid(get_ut_testcase_folder(ut_folder))
155
+        if tc_version == current_version:
156
+            return STATUS_CLEAN
157
+        else:
158
+            return STATUS_CHANGED
159
+
160
+
161
+def get_lib_testcase_integrity(ut_folder):
162
+    return __get_testcase_integrity__(ut_folder, True)
163
+
164
+
165
+def get_ut_testcase_integrity(ut_folder):
166
+    return __get_testcase_integrity__(ut_folder, False)
167
+
168
+
169
+def __get_src_integrity__(ut_folder, lib):
170
+    if lib:
171
+        fn = get_lib_jsonlog(ut_folder)
172
+    else:
173
+        fn = get_ut_jsonlog(ut_folder)
174
+    try:
175
+        with open(fn, 'r') as fh:
176
+            ut_data = json.loads(fh.read())
177
+    except IOError:
178
+        return STATUS_MISSING
179
+    else:
180
+        tested_version = ut_data.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_VERSION)
181
+        current_version = module_uid(get_lib_folder(ut_folder))
182
+        if tested_version == current_version:
183
+            return STATUS_CLEAN
184
+        else:
185
+            return STATUS_CHANGED
186
+
187
+
188
+def get_lib_src_integrity(ut_folder):
189
+    return __get_src_integrity__(ut_folder, True)
190
+
191
+
192
+def get_ut_src_integrity(ut_folder):
193
+    return __get_src_integrity__(ut_folder, False)
194
+
195
+
196
+def status_module(ut_folder):
197
+    try:
198
+        with open(get_lib_jsonlog(ut_folder), 'r') as fh:
199
+            ut_lib = json.loads(fh.read())
200
+    except IOError:
201
+        return STATUS_MISSING
202
+    else:
203
+        try:
204
+            with open(get_ut_jsonlog(ut_folder), 'r') as fh:
205
+                ut_ut = json.loads(fh.read())
206
+        except IOError:
207
+            return STATUS_UNKNOWN
208
+        else:
209
+            tested_version = ut_lib.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_VERSION)
210
+            current_version = module_uid(get_lib_folder(ut_folder))
211
+            if ut_ut[MAIN_KEY_TESTOBJECT_INFO] != ut_lib[MAIN_KEY_TESTOBJECT_INFO] or ut_ut[MAIN_KEY_UNITTEST_INFO] != ut_lib[MAIN_KEY_UNITTEST_INFO] or tested_version != current_version:
212
+                return STATUS_OLD
213
+            else:
214
+                ut_status = ut_lib.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_STATE, 'unknown')
215
+                if 'released' in ut_status.lower():
216
+                    return STATUS_RELEASED
217
+                elif 'work' in ut_status.lower():
218
+                    return STATUS_IN_WORK
219
+                else:
220
+                    return STATUS_UNKNOWN
221
+
222
+
223
+def versions_module(ut_folder):
224
+    try:
225
+        with open(get_ut_jsonlog(ut_folder), 'r') as fh:
226
+            ut = json.loads(fh.read())
227
+    except IOError:
228
+        return STATUS_UNKNOWN
229
+    else:
230
+        interpreters = ut.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_SUPP_INTERP, '')
231
+        interpreters = interpreters.split(',')
232
+        for i in range(len(interpreters)):
233
+            interpreters[i] = interpreters[i].strip()
234
+            interpreters[i] = interpreters[i][6:]
235
+        return ', '.join(interpreters)
236
+
237
+
238
+def __get_coverage__(ut_folder, lib):
239
+    if lib:
240
+        fn = get_lib_jsonlog(ut_folder)
241
+    else:
242
+        fn = get_ut_jsonlog(ut_folder)
243
+    try:
244
+        with open(fn, 'r') as fh:
245
+            ut = json.loads(fh.read())
246
+    except IOError:
247
+        return None, None
248
+    else:
249
+        lcov = ut.get(MAIN_KEY_COVERAGE_INFO, [{}])[0].get(COVI_KEY_LINE_COVERAGE)
250
+        bcov = ut.get(MAIN_KEY_COVERAGE_INFO, [{}])[0].get(COVI_KEY_BRANCH_COVERAGE)
251
+        return lcov, bcov
252
+
253
+
254
+def lib_coverage(ut_folder):
255
+    return __get_coverage__(ut_folder, True)
256
+
257
+
258
+def ut_coverage(ut_folder):
259
+    return __get_coverage__(ut_folder, False)
260
+
261
+
262
+def status_git(ut_folder):
263
+    p = subprocess.Popen("git -C %s status 2> /dev/null" % ut_folder, stdout=subprocess.PIPE, shell=True)
264
+    output = p.communicate()[0]
265
+    p_status = p.wait()
266
+    if p_status == 0:
267
+        if b"nichts zu committen" in output and b"um lokale Commits zu publizieren" not in output:
268
+            return STATUS_CLEAN
269
+        else:
270
+            return STATUS_CHANGED
271
+    else:
272
+        return STATUS_UNKNOWN
273
+
274
+
275
+def status_doc(ut_folder):
276
+    if os.path.exists(os.path.join(get_lib_folder(ut_folder), '_docs_', 'index.html')):
277
+        return STATUS_AVAILABLE
278
+    else:
279
+        if os.path.exists(os.path.join(ut_folder, 'docs', 'index.rst')):
280
+            return STATUS_IN_WORK
281
+        else:
282
+            return STATUS_MISSING
283
+
284
+
285
+def status_spec(ut_folder):
286
+    if os.path.exists(os.path.join(ut_folder, 'requirements', 'specification.reqif')):
287
+        try:
288
+            with open(get_ut_jsonlog(ut_folder), 'r') as fh:
289
+                ut = json.loads(fh.read())
290
+                if len(ut[MAIN_KEY_LOST_SOULS][LOST_ITEMLIST]) > 0 or len(ut[MAIN_KEY_LOST_SOULS][LOST_TESTCASELIST]) > 0:
291
+                    return STATUS_IN_WORK
292
+                else:
293
+                    return STATUS_CLEAN
294
+        except IOError:
295
+            return STATUS_EXISTS
296
+    else:
297
+        return STATUS_MISSING

+ 16
- 148
module_status.py View File

3
 #
3
 #
4
 
4
 
5
 import os
5
 import os
6
-import json
7
-import subprocess
8
 
6
 
9
-from unittest.run import module_uid
10
-from unittest.run import UNITTEST_KEY_TESTOBJECT_INFO
11
-
12
-
13
-class termcolors:
14
-    HEADER = '\033[95m'
15
-    OKBLUE = '\033[94m'
16
-    OKGREEN = '\033[92m'
17
-    WARNING = '\033[93m'
18
-    FAIL = '\033[91m'
19
-    ENDC = '\033[0m'
20
-    BOLD = '\033[1m'
21
-    UNDERLINE = '\033[4m'
22
-
23
-
24
-STATUS_RELEASED = 'RELEASED'
25
-STATUS_AVAILABLE = 'AVAILABLE'
26
-STATUS_IN_WORK = 'IN_WORK'
27
-STATUS_EXISTS = 'EXISTS'
28
-STATUS_OLD = 'OLD'
29
-STATUS_MISSING = 'MISSING'
30
-#
31
-STATUS_CLEAN = 'CLEAN'
32
-STATUS_CHANGED = 'CHANGED'
33
-#
34
-STATUS_UNKNOWN = 'UNKNOWN'
7
+from unittest.output import termcolors, coverage_output
35
 
8
 
9
+from unittest.output import STATUS_COLORS, STATUS_UNKNOWN
10
+from unittest.jsonlog import lib_coverage, status_doc, status_git, status_module, status_spec, versions_module
36
 
11
 
37
 STATUS_LENGTH = 13
12
 STATUS_LENGTH = 13
38
 
13
 
39
-STR_STATUS = {
40
-    STATUS_RELEASED: termcolors.OKGREEN + (STATUS_LENGTH - len(STATUS_RELEASED)) * ' ' + STATUS_RELEASED + termcolors.ENDC,
41
-    STATUS_AVAILABLE: termcolors.OKGREEN + (STATUS_LENGTH - len(STATUS_AVAILABLE)) * ' ' + STATUS_AVAILABLE + termcolors.ENDC,
42
-    STATUS_IN_WORK: termcolors.WARNING + (STATUS_LENGTH - len(STATUS_IN_WORK)) * ' ' + STATUS_IN_WORK + termcolors.ENDC,
43
-    STATUS_OLD: termcolors.WARNING + (STATUS_LENGTH - len(STATUS_OLD)) * ' ' + STATUS_OLD + termcolors.ENDC,
44
-    STATUS_EXISTS: termcolors.WARNING + (STATUS_LENGTH - len(STATUS_EXISTS)) * ' ' + STATUS_EXISTS + termcolors.ENDC,
45
-    STATUS_MISSING: termcolors.FAIL + (STATUS_LENGTH - len(STATUS_MISSING)) * ' ' + STATUS_MISSING + termcolors.ENDC,
46
-    #
47
-    STATUS_CLEAN: termcolors.OKGREEN + (STATUS_LENGTH - len(STATUS_CLEAN)) * ' ' + STATUS_CLEAN + termcolors.ENDC,
48
-    STATUS_CHANGED: termcolors.WARNING + (STATUS_LENGTH - len(STATUS_CHANGED)) * ' ' + STATUS_CHANGED + termcolors.ENDC,
49
-    #
50
-    STATUS_UNKNOWN: termcolors.FAIL + (STATUS_LENGTH - len(STATUS_UNKNOWN)) * ' ' + STATUS_UNKNOWN + termcolors.ENDC,
51
-}
14
+
15
+def status_output(status_or_text, default_color=STATUS_COLORS[STATUS_UNKNOWN]):
16
+    if status_or_text in STATUS_COLORS:
17
+        default_color = STATUS_COLORS[status_or_text]
18
+    return default_color + (STATUS_LENGTH - len(status_or_text[:STATUS_LENGTH])) * ' ' + status_or_text[:STATUS_LENGTH] + termcolors.ENDC
52
 
19
 
53
 
20
 
54
 def module_status_head():
21
 def module_status_head():
67
     return rv
34
     return rv
68
 
35
 
69
 
36
 
70
-def module_status_line(module_folder):
37
+def module_status_line(ut_folder):
71
     rv = '%25s%s%s%s%s%s%s\n' % (
38
     rv = '%25s%s%s%s%s%s%s\n' % (
72
-        os.path.basename(module_folder) + ':',
73
-        STR_STATUS.get(module_unittest_status(module_folder), STATUS_UNKNOWN),
74
-        STR_STATUS.get(module_doc_status(module_folder), STATUS_UNKNOWN),
75
-        module_unittest_versions(module_folder),
76
-        module_unittest_coverage(module_folder),
77
-        STR_STATUS.get(module_spec_status(module_folder), STATUS_UNKNOWN),
78
-        STR_STATUS.get(module_git_status(module_folder), STATUS_UNKNOWN),
39
+        os.path.basename(ut_folder) + ':',
40
+        status_output(status_module(ut_folder)),
41
+        status_output(status_doc(ut_folder)),
42
+        status_output(versions_module(ut_folder), termcolors.BOLD),
43
+        coverage_output(*lib_coverage(ut_folder), length=STATUS_LENGTH),
44
+        status_output(status_spec(ut_folder)),
45
+        status_output(status_git(ut_folder)),
79
     )
46
     )
80
     return rv
47
     return rv
81
-
82
-
83
-def module_unittest_status(module_folder):
84
-    try:
85
-        with open(os.path.join(module_folder, 'pylibs', os.path.basename(module_folder), '_testresults_', 'unittest.json'), 'r') as fh:
86
-            ut_lib = json.loads(fh.read())
87
-    except IOError:
88
-        return STATUS_MISSING
89
-    else:
90
-        try:
91
-            with open(os.path.join(module_folder, 'unittest', 'testresults', 'unittest.json'), 'r') as fh:
92
-                ut_ut = json.loads(fh.read())
93
-        except IOError:
94
-            return STATUS_UNKNOWN
95
-        else:
96
-            tested_version = ut_lib.get(UNITTEST_KEY_TESTOBJECT_INFO, {}).get('Version')
97
-            current_version = module_uid(os.path.join(module_folder, 'pylibs', os.path.basename(module_folder)))
98
-            if ut_ut['testobject_information'] != ut_lib['testobject_information'] or ut_ut['unittest_information'] != ut_lib['unittest_information'] or tested_version != current_version:
99
-                return STATUS_OLD
100
-            else:
101
-                ut_status = ut_lib.get('testobject_information', {}).get('State', 'unknown')
102
-                if 'released' in ut_status.lower():
103
-                    return STATUS_RELEASED
104
-                elif 'work' in ut_status.lower():
105
-                    return STATUS_IN_WORK
106
-                else:
107
-                    return STATUS_UNKNOWN
108
-
109
-
110
-def module_unittest_versions(module_folder):
111
-    try:
112
-        with open(os.path.join(module_folder, 'unittest', 'testresults', 'unittest.json'), 'r') as fh:
113
-            ut = json.loads(fh.read())
114
-    except IOError:
115
-        return STR_STATUS[STATUS_UNKNOWN]
116
-    else:
117
-        interpreters = ut.get('testobject_information', '').get('Supported Interpreters')
118
-        interpreters = interpreters.split(',')
119
-        for i in range(len(interpreters)):
120
-            interpreters[i] = interpreters[i].strip()
121
-            interpreters[i] = interpreters[i][6:]
122
-        rv = ', '.join(interpreters)
123
-        return (STATUS_LENGTH - len(rv)) * ' ' + rv
124
-
125
-
126
-def module_unittest_coverage(module_folder):
127
-    try:
128
-        with open(os.path.join(module_folder, 'unittest', 'testresults', 'unittest.json'), 'r') as fh:
129
-            ut = json.loads(fh.read())
130
-    except IOError:
131
-        return STR_STATUS[STATUS_UNKNOWN]
132
-    else:
133
-        lcov = ut.get('coverage_information', [{}])[0].get('line_coverage')
134
-        bcov = ut.get('coverage_information', [{}])[0].get('branch_coverage')
135
-        if lcov is None or bcov is None:
136
-            return STR_STATUS[STATUS_UNKNOWN]
137
-        elif lcov > 90:
138
-            rv = termcolors.OKGREEN + '%3d%% (%3d%%)' % (lcov, bcov) + termcolors.ENDC
139
-        else:
140
-            rv = termcolors.WARNING + '%3d%% (%3d%%)' % (lcov, bcov) + termcolors.ENDC
141
-        return (STATUS_LENGTH - 11) * ' ' + rv
142
-
143
-
144
-def module_git_status(module_folder):
145
-    p = subprocess.Popen("git -C %s status 2> /dev/null" % module_folder, stdout=subprocess.PIPE, shell=True)
146
-    output = p.communicate()[0]
147
-    p_status = p.wait()
148
-    if p_status == 0:
149
-        if b"nichts zu committen" in output and b"um lokale Commits zu publizieren" not in output:
150
-            return STATUS_CLEAN
151
-        else:
152
-            return STATUS_CHANGED
153
-    else:
154
-        return STATUS_UNKNOWN
155
-
156
-
157
-def module_doc_status(module_folder):
158
-    if os.path.exists(os.path.join(module_folder, 'pylibs', os.path.basename(module_folder), '_docs_', 'index.html')):
159
-        return STATUS_AVAILABLE
160
-    else:
161
-        if os.path.exists(os.path.join(module_folder, 'docs', 'index.rst')):
162
-            return STATUS_IN_WORK
163
-        else:
164
-            return STATUS_MISSING
165
-
166
-
167
-def module_spec_status(module_folder):
168
-    if os.path.exists(os.path.join(module_folder, 'requirements', 'specification.reqif')):
169
-        try:
170
-            with open(os.path.join(module_folder, 'unittest', 'testresults', 'unittest.json'), 'r') as fh:
171
-                ut = json.loads(fh.read())
172
-                if len(ut['lost_souls']['item_list']) > 0 or len(ut['lost_souls']['testcase_list']) > 0:
173
-                    return STATUS_IN_WORK
174
-                else:
175
-                    return STATUS_CLEAN
176
-        except IOError:
177
-            return STATUS_EXISTS
178
-    else:
179
-        return STATUS_MISSING

+ 81
- 0
output.py View File

1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+#
4
+
5
+#
6
+# STATUS_KEYS
7
+#
8
+STATUS_AVAILABLE = 'AVAILABLE'
9
+STATUS_CLEAN = 'CLEAN'
10
+STATUS_RELEASED = 'RELEASED'
11
+STATUS_SUCCESS = 'SUCCESS'
12
+#
13
+STATUS_CHANGED = 'CHANGED'
14
+STATUS_EXISTS = 'EXISTS'
15
+STATUS_IN_WORK = 'IN_WORK'
16
+STATUS_OLD = 'OLD'
17
+#
18
+STATUS_FAILED = 'FAILED'
19
+STATUS_MISSING = 'MISSING'
20
+STATUS_UNKNOWN = 'UNKNOWN'
21
+
22
+
23
+class termcolors:
24
+    HEADER = '\033[95m'
25
+    OKBLUE = '\033[94m'
26
+    OKGREEN = '\033[92m'
27
+    WARNING = '\033[93m'
28
+    FAIL = '\033[91m'
29
+    ENDC = '\033[0m'
30
+    BOLD = '\033[1m'
31
+    UNDERLINE = '\033[4m'
32
+
33
+
34
+STATUS_COLORS = {
35
+    STATUS_AVAILABLE: termcolors.OKGREEN,
36
+    STATUS_CLEAN: termcolors.OKGREEN,
37
+    STATUS_RELEASED: termcolors.OKGREEN,
38
+    STATUS_SUCCESS: termcolors.OKGREEN,
39
+    #
40
+    STATUS_CHANGED: termcolors.WARNING,
41
+    STATUS_EXISTS: termcolors.WARNING,
42
+    STATUS_IN_WORK: termcolors.WARNING,
43
+    STATUS_OLD: termcolors.WARNING,
44
+    #
45
+    STATUS_FAILED: termcolors.FAIL,
46
+    STATUS_MISSING: termcolors.FAIL,
47
+    STATUS_UNKNOWN: termcolors.FAIL,
48
+}
49
+
50
+
51
+def print_header(txt):
52
+    print(termcolors.BOLD + termcolors.WARNING + txt + termcolors.ENDC)
53
+
54
+
55
+def print_action(txt):
56
+    print(termcolors.BOLD + '  * ' + txt + termcolors.ENDC)
57
+
58
+
59
+def status_output(txt, default_color):
60
+    return STATUS_COLORS.get(txt, default_color) + txt + termcolors.ENDC
61
+
62
+
63
+def print_info(txt, default_color=termcolors.ENDC):
64
+    print('      ' + status_output(txt, default_color))
65
+
66
+
67
+def coverage_output(lcov, bcov, length=None):
68
+    if lcov is None or bcov is None:
69
+        return (length - len(STATUS_UNKNOWN)) * ' ' + status_output(STATUS_UNKNOWN, termcolors.FAIL)
70
+    elif lcov > 90:
71
+        rv = termcolors.OKGREEN + '%3d%% (%3d%%)' % (lcov, bcov) + termcolors.ENDC
72
+    else:
73
+        rv = termcolors.WARNING + '%3d%% (%3d%%)' % (lcov, bcov) + termcolors.ENDC
74
+    if length is None:
75
+        return rv
76
+    else:
77
+        return (length - 11) * ' ' + rv
78
+
79
+
80
+def print_coverage(lcov, bcov):
81
+    print('      ' + coverage_output(lcov, bcov))

+ 173
- 199
run.py View File

2
 # -*- coding: utf-8 -*-
2
 # -*- coding: utf-8 -*-
3
 #
3
 #
4
 import fstools
4
 import fstools
5
+from unittest import jsonlog
6
+from unittest import output
5
 import report
7
 import report
6
 import reqif
8
 import reqif
7
 
9
 
23
     jinja2 = None
25
     jinja2 = None
24
 import shutil
26
 import shutil
25
 
27
 
26
-HEADER = '\033[95m'
27
-OKBLUE = '\033[94m'
28
-OKGREEN = '\033[92m'
29
-WARNING = '\033[93m'
30
-FAIL = '\033[91m'
31
-ENDC = '\033[0m'
32
-BOLD = '\033[1m'
33
-UNDERLINE = '\033[4m'
34
 
28
 
35
 ARG_CLEAN = 'clean'
29
 ARG_CLEAN = 'clean'
36
 ARG_RUN = 'run'
30
 ARG_RUN = 'run'
40
 ARG_COPY = 'copy'
34
 ARG_COPY = 'copy'
41
 ARG_RELEASE = 'release'
35
 ARG_RELEASE = 'release'
42
 
36
 
43
-UNITTEST_KEY_SYSTEM_INFO = 'system_information'
44
-UNITTEST_KEY_UNITTEST_INFO = 'unittest_information'
45
-UNITTEST_KEY_TESTOBJECT_INFO = 'testobject_information'
46
-UNITTEST_KEY_TESTRUNS = 'testrun_list'
47
-UNITTEST_KEY_COVERAGE_INFO = 'coverage_information'
48
-UNITTEST_KEY_SPECIFICATION = 'specification'
37
+FN_DATA_COLLECTION = 'unittest.json'
38
+FN_TEX_REPORT = 'unittest.tex'
39
+FN_PDF_REPORT = 'unittest.pdf'
40
+FN_COVERAGE = 'coverage.xml'
49
 
41
 
50
-FILES = {
51
-    'data-collection': 'unittest.json',
52
-    'tex-report': 'unittest.tex',
53
-    'coverage-xml': 'coverage.xml'
54
-}
55
 
42
 
56
-REPORT_FILES = [FILES['data-collection'], FILES['coverage-xml'], 'unittest.pdf']
43
+REPORT_FILES = [FN_DATA_COLLECTION, FN_COVERAGE, FN_PDF_REPORT]
44
+
45
+
46
+def testresults_filename(ut_folder, filename):
47
+    return os.path.join(jsonlog.get_ut_testresult_folder(ut_folder), filename)
48
+
49
+
50
+def remove_file(filename):
51
+    if os.path.exists(filename) and not filename.endswith('.gitkeep'):
52
+        try:
53
+            output.print_info('Removing %s' % filename)
54
+            os.remove(filename)
55
+        except OSError:
56
+            pass
57
 
57
 
58
 
58
 
59
 class coverage_info(list):
59
 class coverage_info(list):
60
-    KEY_NAME = 'name'
61
-    KEY_FILEPATH = 'filepath'
62
-    KEY_LINE_COVERAGE = 'line_coverage'
63
-    KEY_BRANCH_COVERAGE = 'branch_coverage'
64
-    KEY_FILES = 'files'
65
     KEY_FRAGMENTS = 'fragments'
60
     KEY_FRAGMENTS = 'fragments'
66
     KEY_START_LINE = 'start'
61
     KEY_START_LINE = 'start'
67
     KEY_END_LINE = 'end'
62
     KEY_END_LINE = 'end'
77
         itemlist = xmldoc.getElementsByTagName('package')
72
         itemlist = xmldoc.getElementsByTagName('package')
78
         for p in itemlist:
73
         for p in itemlist:
79
             module = {}
74
             module = {}
80
-            module[self.KEY_NAME] = p.attributes['name'].value[len(module_basepath) + 1:]
81
-            module[self.KEY_FILEPATH] = p.attributes['name'].value.replace('.', os.path.sep)
82
-            module[self.KEY_LINE_COVERAGE] = float(p.attributes['line-rate'].value) * 100.
75
+            module[jsonlog.COVI_KEY_NAME] = p.attributes['name'].value[len(module_basepath) + 1:]
76
+            module[jsonlog.COVI_KEY_FILEPATH] = p.attributes['name'].value.replace('.', os.path.sep)
77
+            module[jsonlog.COVI_KEY_LINE_COVERAGE] = float(p.attributes['line-rate'].value) * 100.
83
             try:
78
             try:
84
-                module[self.KEY_BRANCH_COVERAGE] = float(p.attributes['branch-rate'].value) * 100.
79
+                module[jsonlog.COVI_KEY_BRANCH_COVERAGE] = float(p.attributes['branch-rate'].value) * 100.
85
             except AttributeError:
80
             except AttributeError:
86
-                module[self.KEY_BRANCH_COVERAGE] = None
87
-            module[self.KEY_FILES] = []
81
+                module[jsonlog.COVI_KEY_BRANCH_COVERAGE] = None
82
+            module[jsonlog.COVI_KEY_FILES] = []
88
             for c in p.getElementsByTagName('class'):
83
             for c in p.getElementsByTagName('class'):
89
                 f = {}
84
                 f = {}
90
-                f[self.KEY_NAME] = c.attributes['filename'].value[len(module_basepath) + 1:].replace(os.path.sep, '.')
91
-                f[self.KEY_FILEPATH] = c.attributes['filename'].value
92
-                f[self.KEY_LINE_COVERAGE] = float(c.attributes['line-rate'].value) * 100.
85
+                f[jsonlog.COVI_KEY_NAME] = c.attributes['filename'].value[len(module_basepath) + 1:].replace(os.path.sep, '.')
86
+                f[jsonlog.COVI_KEY_FILEPATH] = c.attributes['filename'].value
87
+                f[jsonlog.COVI_KEY_LINE_COVERAGE] = float(c.attributes['line-rate'].value) * 100.
93
                 try:
88
                 try:
94
-                    f[self.KEY_BRANCH_COVERAGE] = float(p.attributes['branch-rate'].value) * 100.
89
+                    f[jsonlog.COVI_KEY_BRANCH_COVERAGE] = float(p.attributes['branch-rate'].value) * 100.
95
                 except Exception:
90
                 except Exception:
96
-                    f[self.KEY_BRANCH_COVERAGE] = None
91
+                    f[jsonlog.COVI_KEY_BRANCH_COVERAGE] = None
97
                 f[self.KEY_FRAGMENTS] = []
92
                 f[self.KEY_FRAGMENTS] = []
98
                 last_hit = None
93
                 last_hit = None
99
                 start_line = 1
94
                 start_line = 1
146
                 line[self.KEY_END_LINE] = None
141
                 line[self.KEY_END_LINE] = None
147
                 line[self.KEY_COVERAGE_STATE] = self.CLEAN
142
                 line[self.KEY_COVERAGE_STATE] = self.CLEAN
148
                 f[self.KEY_FRAGMENTS].append(line)
143
                 f[self.KEY_FRAGMENTS].append(line)
149
-                module[self.KEY_FILES].append(f)
144
+                module[jsonlog.COVI_KEY_FILES].append(f)
150
             self.append(module)
145
             self.append(module)
151
 
146
 
152
     def __str__(self):
147
     def __str__(self):
153
         rv = ''
148
         rv = ''
154
         for module in self:
149
         for module in self:
155
-            rv += '%s (%.1f%% - %s)\n' % (module.get(self.KEY_NAME), module.get(self.KEY_LINE_COVERAGE), module.get(self.KEY_FILEPATH))
156
-            for py_file in module.get(self.KEY_FILES):
157
-                rv += '    %s (%.1f%% - %s)\n' % (py_file.get(self.KEY_NAME), py_file.get(self.KEY_LINE_COVERAGE), py_file.get(self.KEY_FILEPATH))
150
+            rv += '%s (%.1f%% - %s)\n' % (module.get(jsonlog.COVI_KEY_NAME), module.get(jsonlog.COVI_KEY_LINE_COVERAGE), module.get(jsonlog.COVI_KEY_FILEPATH))
151
+            for py_file in module.get(jsonlog.COVI_KEY_FILES):
152
+                rv += '    %s (%.1f%% - %s)\n' % (py_file.get(jsonlog.COVI_KEY_NAME), py_file.get(jsonlog.COVI_KEY_LINE_COVERAGE), py_file.get(jsonlog.COVI_KEY_FILEPATH))
158
                 for fragment in py_file.get(self.KEY_FRAGMENTS):
153
                 for fragment in py_file.get(self.KEY_FRAGMENTS):
159
                     if fragment.get(self.KEY_END_LINE) is not None:
154
                     if fragment.get(self.KEY_END_LINE) is not None:
160
                         rv += '        %d - %d: %s\n' % (fragment.get(self.KEY_START_LINE), fragment.get(self.KEY_END_LINE), repr(fragment.get(self.KEY_COVERAGE_STATE)))
155
                         rv += '        %d - %d: %s\n' % (fragment.get(self.KEY_START_LINE), fragment.get(self.KEY_END_LINE), repr(fragment.get(self.KEY_COVERAGE_STATE)))
161
                     else:
156
                     else:
162
-                        rv += '        %d -  : %s\n' % (fragment.get(self.KEY_START_LINE), repr(fragment.get(self.KEY_COVERAGE_STATE)))
157
+                        rv += '        %d -  : %s\n' % (fragment.get(self.KEY_START_LINE), repr(fragment.get(self.COVERAGE_STATE)))
163
         return rv
158
         return rv
164
 
159
 
165
 
160
 
166
-def unittest_filename(base_folder, filename):
167
-    return os.path.join(base_folder, 'testresults', filename)
168
-
169
-
170
-def print_header(txt, color=BOLD + WARNING):
171
-    print(color + txt + ENDC)
172
-
173
-
174
-def print_action(txt, color=BOLD):
175
-    print(color + '  * ' + txt + ENDC)
176
-
177
-
178
-def print_info(txt, color=ENDC):
179
-    print('      ' + color + txt + ENDC)
180
-
181
-
182
-def remove_file(filename):
183
-    if os.path.exists(filename) and not filename.endswith('.gitkeep'):
184
-        try:
185
-            print_info('Removing %s' % filename)
186
-            os.remove(filename)
187
-        except OSError:
188
-            pass
189
-
190
-
191
-def module_uid(path):
192
-    return fstools.uid_filelist(path, '*.py', rekursive=True)
193
-
194
-
195
 def unittest(options, args, unittest_folder):
161
 def unittest(options, args, unittest_folder):
196
     if 'release_testcases' in args:
162
     if 'release_testcases' in args:
197
         unittest_release_testcases(unittest_folder)
163
         unittest_release_testcases(unittest_folder)
209
         unittest_publish(unittest_folder)
175
         unittest_publish(unittest_folder)
210
 
176
 
211
 
177
 
212
-def unittest_release_testcases(unittest_folder):
213
-    unittest_uid = module_uid(os.path.join(unittest_folder, 'src', 'tests'))
214
-    config_file = os.path.join(unittest_folder, 'src', 'config.py')
215
-    print_header('Releasing unittest')
178
+def unittest_release_testcases(ut_folder):
179
+    unittest_uid = jsonlog.module_uid(jsonlog.get_ut_testcase_folder(ut_folder))
180
+    output.print_header('Releasing unittest')
181
+    config_file = jsonlog.get_ut_config(ut_folder)
216
     with open(config_file, 'r') as fh:
182
     with open(config_file, 'r') as fh:
217
         conf_file = fh.read()
183
         conf_file = fh.read()
218
-    print_action('Setting release_unittest_version = %s in %s' % (unittest_uid, config_file))
184
+    output.print_action('Setting release_unittest_version = %s in %s' % (unittest_uid, config_file))
219
     with open(config_file, 'w') as fh:
185
     with open(config_file, 'w') as fh:
220
         for line in conf_file.splitlines():
186
         for line in conf_file.splitlines():
221
             if line.startswith('release_unittest_version'):
187
             if line.startswith('release_unittest_version'):
224
                 fh.write(line + '\n')
190
                 fh.write(line + '\n')
225
 
191
 
226
 
192
 
227
-def unittest_clean(unittest_folder):
228
-    print_header('Cleaning up...')
229
-    print_action('Testresults from last testrun')
230
-    for fn in os.listdir(unittest_filename(unittest_folder, '')):
231
-        remove_file(unittest_filename(unittest_folder, fn))
232
-    remove_file(unittest_filename(unittest_folder, FILES['coverage-xml']))
193
+def unittest_clean(ut_folder):
194
+    output.print_header('Cleaning up...')
195
+    output.print_action('Testresults from last testrun')
196
+    for fn in os.listdir(testresults_filename(ut_folder, '')):
197
+        remove_file(testresults_filename(ut_folder, fn))
233
 
198
 
234
 
199
 
235
-def unittest_prepare(unittest_folder):
236
-    config = imp.load_source('', os.path.join(unittest_folder, 'src', 'config.py'))
200
+def unittest_prepare(ut_folder):
201
+    config = imp.load_source('', jsonlog.get_ut_config(ut_folder))
237
     #
202
     #
238
-    print_header("Initiating unittest for first testrun...")
239
-    if not os.path.exists(unittest_filename(unittest_folder, '')):
240
-        print_action('Creating outpout folder %s' % unittest_filename(unittest_folder, ''))
241
-        fstools.mkdir(unittest_filename(unittest_folder, ''))
203
+    output.print_header("Initiating unittest for first testrun...")
204
+    if not os.path.exists(testresults_filename(ut_folder, '')):
205
+        output.print_action('Creating outpout folder %s' % testresults_filename(ut_folder, ''))
206
+        fstools.mkdir(testresults_filename(ut_folder, ''))
242
     #
207
     #
243
-    print_action('Creating unittest data-collection: %s' % unittest_filename(unittest_folder, FILES['data-collection']))
208
+    output.print_action('Creating unittest data-collection: %s' % testresults_filename(ut_folder, FN_DATA_COLLECTION))
244
     #
209
     #
245
     system_info = {}
210
     system_info = {}
246
-    system_info['Architecture'] = platform.architecture()[0]
247
-    system_info['Machine'] = platform.machine()
248
-    system_info['Hostname'] = platform.node()
249
-    system_info['Distribution'] = ' '.join(dist())
250
-    system_info['System'] = platform.system()
251
-    system_info['Kernel'] = platform.release() + ' (%s)' % platform.version()
252
-    system_info['Username'] = getpass.getuser()
253
-    system_info['Path'] = unittest_folder
211
+    system_info[jsonlog.SYSI_ARCHITECTURE] = platform.architecture()[0]
212
+    system_info[jsonlog.SYSI_MACHINE] = platform.machine()
213
+    system_info[jsonlog.SYSI_HOSTNAME] = platform.node()
214
+    system_info[jsonlog.SYSI_DISTRIBUTION] = ' '.join(dist())
215
+    system_info[jsonlog.SYSI_SYSTEM] = platform.system()
216
+    system_info[jsonlog.SYSI_KERNEL] = platform.release() + ' (%s)' % platform.version()
217
+    system_info[jsonlog.SYSI_USERNAME] = getpass.getuser()
218
+    system_info[jsonlog.SYSI_PATH] = ut_folder
254
     #
219
     #
255
     unittest_info = {}
220
     unittest_info = {}
256
-    unittest_info['Version'] = module_uid(os.path.join(unittest_folder, 'src', 'tests'))
221
+    unittest_info[jsonlog.UTEI_VERSION] = jsonlog.module_uid(jsonlog.get_ut_testcase_folder(ut_folder))
257
     #
222
     #
258
     testobject_info = {}
223
     testobject_info = {}
259
-    testobject_info['Name'] = config.lib.__name__
260
-    testobject_info['Version'] = module_uid(config.lib.__path__[0])
261
-    testobject_info['Description'] = config.lib.__DESCRIPTION__
262
-    testobject_info['Supported Interpreters'] = ', '.join(['python%d' % vers for vers in config.lib.__INTERPRETER__])
263
-    testobject_info['State'] = 'Released' if config.release_unittest_version == module_uid(os.path.join(unittest_folder, 'src', 'tests')) else 'In development'
264
-    testobject_info['Dependencies'] = []
224
+    testobject_info[jsonlog.TOBI_NAME] = config.lib.__name__
225
+    testobject_info[jsonlog.TOBI_VERSION] = jsonlog.module_uid(config.lib.__path__[0])
226
+    testobject_info[jsonlog.TOBI_DESCRIPTION] = config.lib.__DESCRIPTION__
227
+    testobject_info[jsonlog.TOBI_SUPP_INTERP] = ', '.join(['python%d' % vers for vers in config.lib.__INTERPRETER__])
228
+    testobject_info[jsonlog.TOBI_STATE] = jsonlog.TOBI_STATE_RELESED if config.release_unittest_version == unittest_info[jsonlog.UTEI_VERSION] else jsonlog.TOBI_STATE_IN_DEVELOPMENT
229
+    testobject_info[jsonlog.TOBI_DEPENDENCIES] = []
265
     for dependency in config.lib.__DEPENDENCIES__:
230
     for dependency in config.lib.__DEPENDENCIES__:
266
-        testobject_info['Dependencies'].append((dependency, module_uid(os.path.join(unittest_folder, 'src', dependency))))
231
+        testobject_info[jsonlog.TOBI_DEPENDENCIES].append((dependency, jsonlog.module_uid(os.path.join(jsonlog.get_ut_src_folder(ut_folder), dependency))))
267
     #
232
     #
268
-    spec_filename = os.path.join(unittest_folder, '..', 'requirements', 'specification.reqif')
269
-    print_action("Adding Requirement Specification from %s" % spec_filename)
233
+    spec_filename = os.path.join(ut_folder, 'requirements', 'specification.reqif')
234
+    output.print_action("Adding Requirement Specification from %s" % spec_filename)
270
     try:
235
     try:
271
         spec = reqif.reqif_dict(spec_filename, 'Heading', 'Software Specification')
236
         spec = reqif.reqif_dict(spec_filename, 'Heading', 'Software Specification')
272
     except FileNotFoundError:
237
     except FileNotFoundError:
273
-        print_info('FAILED', FAIL)
238
+        output.print_info(output.STATUS_FAILED)
274
         spec = {}
239
         spec = {}
275
     else:
240
     else:
276
-        print_info('SUCCESS', OKGREEN)
241
+        output.print_info(output.STATUS_SUCCESS)
277
     #
242
     #
278
     data_collection = {
243
     data_collection = {
279
-        UNITTEST_KEY_SYSTEM_INFO: system_info,
280
-        UNITTEST_KEY_UNITTEST_INFO: unittest_info,
281
-        UNITTEST_KEY_TESTOBJECT_INFO: testobject_info,
282
-        UNITTEST_KEY_SPECIFICATION: spec,
283
-        UNITTEST_KEY_TESTRUNS: [],
244
+        jsonlog.MAIN_KEY_SYSTEM_INFO: system_info,
245
+        jsonlog.MAIN_KEY_UNITTEST_INFO: unittest_info,
246
+        jsonlog.MAIN_KEY_TESTOBJECT_INFO: testobject_info,
247
+        jsonlog.MAIN_KEY_SPECIFICATION: spec,
248
+        jsonlog.MAIN_KEY_TESTRUNS: [],
284
     }
249
     }
285
-    with open(unittest_filename(unittest_folder, FILES['data-collection']), 'w') as fh:
250
+    with open(testresults_filename(ut_folder, FN_DATA_COLLECTION), 'w') as fh:
286
         fh.write(json.dumps(data_collection, indent=4, sort_keys=True))
251
         fh.write(json.dumps(data_collection, indent=4, sort_keys=True))
287
 
252
 
288
 
253
 
289
-def unittest_testrun(unittest_folder, options):
290
-    tests = imp.load_source('', os.path.join(unittest_folder, 'src', 'tests', '__init__.py'))
291
-    config = imp.load_source('', os.path.join(unittest_folder, 'src', 'config.py'))
254
+def unittest_testrun(ut_folder, options):
255
+    tests = imp.load_source('', os.path.join(jsonlog.get_ut_testcase_folder(ut_folder), '__init__.py'))
256
+    config = imp.load_source('', jsonlog.get_ut_config(ut_folder))
292
     #
257
     #
293
     interpreter_version = 'python ' + '.'.join(['%d' % n for n in sys.version_info[:3]]) + ' (%s)' % sys.version_info[3]
258
     interpreter_version = 'python ' + '.'.join(['%d' % n for n in sys.version_info[:3]]) + ' (%s)' % sys.version_info[3]
294
     #
259
     #
295
     execution_level = report.TCEL_REVERSE_NAMED.get(options.execution_level, report.TCEL_FULL)
260
     execution_level = report.TCEL_REVERSE_NAMED.get(options.execution_level, report.TCEL_FULL)
296
     #
261
     #
297
     if sys.version_info.major in config.lib.__INTERPRETER__:
262
     if sys.version_info.major in config.lib.__INTERPRETER__:
298
-        print_header("Running \"%s\" Unittest with %s" % (options.execution_level, interpreter_version))
299
-        print_action('Loading Testrun data from %s' % unittest_filename(unittest_folder, FILES['data-collection']))
300
-        with open(unittest_filename(unittest_folder, FILES['data-collection']), 'r') as fh:
263
+        output.print_header("Running \"%s\" Unittest with %s" % (options.execution_level, interpreter_version))
264
+        with open(testresults_filename(ut_folder, FN_DATA_COLLECTION), 'r') as fh:
301
             data_collection = json.loads(fh.read())
265
             data_collection = json.loads(fh.read())
302
-        print_action('Executing Testcases')
266
+        output.print_action('Executing Testcases')
303
         heading_dict = {}
267
         heading_dict = {}
304
-        for key in data_collection[UNITTEST_KEY_SPECIFICATION].get('item_dict', {}):
305
-            heading_dict[key] = data_collection[UNITTEST_KEY_SPECIFICATION]['item_dict'][key]['Heading']
268
+        for key in data_collection[jsonlog.MAIN_KEY_SPECIFICATION].get(jsonlog.SPEC_ITEM_DICT, {}):
269
+            heading_dict[key] = data_collection[jsonlog.MAIN_KEY_SPECIFICATION][jsonlog.SPEC_ITEM_DICT][key]['Heading']
306
         test_session = report.testSession(
270
         test_session = report.testSession(
307
             ['__unittest__', 'root'],
271
             ['__unittest__', 'root'],
308
             interpreter=interpreter_version,
272
             interpreter=interpreter_version,
312
         )
276
         )
313
         tests.testrun(test_session)
277
         tests.testrun(test_session)
314
         #
278
         #
315
-        print_action('Adding Testrun data to %s' % unittest_filename(unittest_folder, FILES['data-collection']))
316
-        data_collection[UNITTEST_KEY_TESTRUNS].append(test_session)
317
-        with open(unittest_filename(unittest_folder, FILES['data-collection']), 'w') as fh:
279
+        output.print_action('Adding Testrun data to %s' % testresults_filename(ut_folder, FN_DATA_COLLECTION))
280
+        data_collection[jsonlog.MAIN_KEY_TESTRUNS].append(test_session)
281
+        with open(testresults_filename(ut_folder, FN_DATA_COLLECTION), 'w') as fh:
318
             fh.write(json.dumps(data_collection, indent=4, sort_keys=True))
282
             fh.write(json.dumps(data_collection, indent=4, sort_keys=True))
319
     else:
283
     else:
320
-        print_header("Library does not support %s." % interpreter_version)
284
+        output.print_header("Library does not support %s." % interpreter_version)
321
 
285
 
322
 
286
 
323
-def unittest_finalise(unittest_folder):
324
-    config = imp.load_source('', os.path.join(unittest_folder, 'src', 'config.py'))
287
+def unittest_finalise(ut_folder):
288
+    config = imp.load_source('', jsonlog.get_ut_config(ut_folder))
325
     #
289
     #
326
-    print_header("Adding Requirement information")
290
+    output.print_header("Adding Requirement information")
327
     #
291
     #
328
-    print_action('Loading Testrun data from %s' % unittest_filename(unittest_folder, FILES['data-collection']))
329
-    with open(unittest_filename(unittest_folder, FILES['data-collection']), 'r') as fh:
292
+    with open(testresults_filename(ut_folder, FN_DATA_COLLECTION), 'r') as fh:
330
         data_collection = json.loads(fh.read())
293
         data_collection = json.loads(fh.read())
331
     #
294
     #
332
-    data_collection['lost_souls'] = {}
295
+    data_collection[jsonlog.MAIN_KEY_LOST_SOULS] = {}
333
     #
296
     #
334
-    print_action("Adding Lost Requirement Soul")
335
-    data_collection['lost_souls']['item_list'] = []
336
-    for req_id in data_collection[UNITTEST_KEY_SPECIFICATION].get('item_dict', {}):
337
-        item = data_collection[UNITTEST_KEY_SPECIFICATION]['item_dict'][req_id]
297
+    output.print_action("Adding Lost Requirement Soul")
298
+    data_collection[jsonlog.MAIN_KEY_LOST_SOULS][jsonlog.LOST_ITEMLIST] = []
299
+    for req_id in data_collection[jsonlog.MAIN_KEY_SPECIFICATION].get(jsonlog.SPEC_ITEM_DICT, {}):
300
+        item = data_collection[jsonlog.MAIN_KEY_SPECIFICATION][jsonlog.SPEC_ITEM_DICT][req_id]
338
         if item['system_type_uid'] == '_MR7eNHYYEem_kd-7nxt1sg':
301
         if item['system_type_uid'] == '_MR7eNHYYEem_kd-7nxt1sg':
339
             testcase_available = False
302
             testcase_available = False
340
-            for testrun in data_collection[UNITTEST_KEY_TESTRUNS]:
341
-                if req_id in testrun['testcases']:
303
+            for testrun in data_collection[jsonlog.MAIN_KEY_TESTRUNS]:
304
+                if req_id in testrun[jsonlog.TRUN_TESTCASES]:
342
                     testcase_available = True
305
                     testcase_available = True
343
                     break
306
                     break
344
             if not testcase_available:
307
             if not testcase_available:
345
-                data_collection['lost_souls']['item_list'].append(req_id)
346
-                print_info('%s - "%s" has no corresponding testcase' % (item['system_uid'], item['Heading']), FAIL)
308
+                data_collection[jsonlog.MAIN_KEY_LOST_SOULS][jsonlog.LOST_ITEMLIST].append(req_id)
309
+                output.print_info('%s - "%s" has no corresponding testcase' % (item['system_uid'], item['Heading']), output.termcolors.FAIL)
347
     #
310
     #
348
-    print_action("Adding Lost Testcase Soul")
349
-    data_collection['lost_souls']['testcase_list'] = []
350
-    for testrun in data_collection[UNITTEST_KEY_TESTRUNS]:
351
-        for tc_id in testrun.get('testcases', {}):
352
-            if tc_id not in data_collection[UNITTEST_KEY_SPECIFICATION].get('item_dict', {}) and tc_id not in data_collection['lost_souls']['testcase_list']:
353
-                data_collection['lost_souls']['testcase_list'].append(tc_id)
354
-                print_info('"%s" has no corresponding testcase' % tc_id, FAIL)
311
+    output.print_action("Adding Lost Testcase Soul")
312
+    data_collection[jsonlog.MAIN_KEY_LOST_SOULS][jsonlog.LOST_TESTCASELIST] = []
313
+    for testrun in data_collection[jsonlog.MAIN_KEY_TESTRUNS]:
314
+        for tc_id in testrun.get(jsonlog.TRUN_TESTCASES, {}):
315
+            if tc_id not in data_collection[jsonlog.MAIN_KEY_SPECIFICATION].get(jsonlog.SPEC_ITEM_DICT, {}) and tc_id not in data_collection[jsonlog.MAIN_KEY_LOST_SOULS][jsonlog.LOST_TESTCASELIST]:
316
+                data_collection[jsonlog.MAIN_KEY_LOST_SOULS][jsonlog.LOST_TESTCASELIST].append(tc_id)
317
+                output.print_info('"%s" has no corresponding testcase' % tc_id, output.termcolors.FAIL)
355
     #
318
     #
356
-    print_header("Adding Coverage information")
357
-    print_action('Adding Coverage Information to %s' % unittest_filename(unittest_folder, FILES['data-collection']))
358
-    data_collection[UNITTEST_KEY_COVERAGE_INFO] = coverage_info(unittest_filename(unittest_folder, 'coverage.xml'), os.path.dirname(config.lib_path))
359
-    with open(unittest_filename(unittest_folder, FILES['data-collection']), 'w') as fh:
319
+    output.print_header("Adding Coverage information")
320
+    output.print_action('Adding Coverage Information to %s' % testresults_filename(ut_folder, FN_DATA_COLLECTION))
321
+    data_collection[jsonlog.MAIN_KEY_COVERAGE_INFO] = coverage_info(testresults_filename(ut_folder, FN_COVERAGE), os.path.dirname(config.lib_path))
322
+    with open(testresults_filename(ut_folder, FN_DATA_COLLECTION), 'w') as fh:
360
         fh.write(json.dumps(data_collection, indent=4, sort_keys=True))
323
         fh.write(json.dumps(data_collection, indent=4, sort_keys=True))
361
     #
324
     #
362
-    print_header("Creating LaTeX-Report of Unittest")
363
-    print_action('Loading Testrun data from %s' % unittest_filename(unittest_folder, FILES['data-collection']))
364
-    with open(unittest_filename(unittest_folder, FILES['data-collection']), 'r') as fh:
325
+    output.print_header("Creating LaTeX-Report of Unittest")
326
+    with open(testresults_filename(ut_folder, FN_DATA_COLLECTION), 'r') as fh:
365
         data_collection = json.loads(fh.read())
327
         data_collection = json.loads(fh.read())
366
 
328
 
367
     if jinja2 is None:
329
     if jinja2 is None:
368
-        print_action('You need to install jinja2 to create a LaTeX-Report!', FAIL)
330
+        output.print_action('You need to install jinja2 to create a LaTeX-Report!', output.termcolors.FAIL)
369
     else:
331
     else:
370
-        fn = unittest_filename(unittest_folder, FILES['tex-report'])
371
-        print_action('Creating LaTeX-File %s' % fn)
332
+        fn = testresults_filename(ut_folder, FN_TEX_REPORT)
333
+        output.print_action('Creating LaTeX-File %s' % fn)
372
         with open(fn, 'w') as fh:
334
         with open(fn, 'w') as fh:
373
             #
335
             #
374
             template_path = os.path.join(os.path.dirname(__file__), 'templates')
336
             template_path = os.path.join(os.path.dirname(__file__), 'templates')
378
             fh.write(template.render(data=data_collection))
340
             fh.write(template.render(data=data_collection))
379
 
341
 
380
 
342
 
381
-def unittest_publish(unittest_folder):
382
-    config = imp.load_source('', os.path.join(unittest_folder, 'src', 'config.py'))
343
+def unittest_publish(ut_folder):
344
+    config = imp.load_source('', jsonlog.get_ut_config(ut_folder))
383
     #
345
     #
384
-    print_header('Copy unittest files to library')
346
+    output.print_header('Copy unittest files to library')
385
     target_folder = os.path.join(config.lib_path, '_testresults_')
347
     target_folder = os.path.join(config.lib_path, '_testresults_')
386
-    print_action('Copying Unittest Files to  %s' % target_folder)
348
+    output.print_action('Copying Unittest Files to  %s' % target_folder)
387
     if not os.path.exists(target_folder):
349
     if not os.path.exists(target_folder):
388
-        print_info('Creating folder %s' % target_folder)
350
+        output.print_info('Creating folder %s' % target_folder)
389
         fstools.mkdir(target_folder)
351
         fstools.mkdir(target_folder)
390
     else:
352
     else:
391
         for fn in os.listdir(target_folder):
353
         for fn in os.listdir(target_folder):
392
             remove_file(os.path.join(target_folder, fn))
354
             remove_file(os.path.join(target_folder, fn))
393
     for fn in REPORT_FILES:
355
     for fn in REPORT_FILES:
394
-        src = unittest_filename(unittest_folder, fn)
356
+        src = testresults_filename(ut_folder, fn)
395
         dst = os.path.join(target_folder, fn)
357
         dst = os.path.join(target_folder, fn)
396
-        print_info('copying %s -> %s' % (src, dst))
358
+        output.print_info('copying %s -> %s' % (src, dst))
397
         shutil.copyfile(src, dst)
359
         shutil.copyfile(src, dst)
398
 
360
 
399
 
361
 
400
-def unittest_status(unittest_folder):
401
-    print_header('Checking status of all submodules')
402
-    print_action('Updating all submodules (fetch)')
403
-    process = subprocess.Popen("LANGUAGE='en_US.UTF-8 git' git submodule foreach git fetch", cwd=os.path.dirname(unittest_folder), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
362
+def unittest_status(ut_folder):
363
+    #
364
+    # GIT STATUS
365
+    #
366
+    output.print_header('Checking GIT repository status')
367
+    # GIT FETCH
368
+    output.print_action('Fetching repository from server...')
369
+    process = subprocess.Popen("LANGUAGE='en_US.UTF-8 git' git submodule foreach git fetch", cwd=ut_folder, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
404
     stderroutput = process.communicate()[1]
370
     stderroutput = process.communicate()[1]
405
     if stderroutput == b'':
371
     if stderroutput == b'':
406
-        print_info('SUCCESS', color=OKGREEN)
372
+        output.print_info(output.STATUS_SUCCESS)
407
     else:
373
     else:
408
-        print_info('FAILED', color=FAIL)
409
-
410
-    print_action('Checking status...')
411
-    process = subprocess.Popen("LANGUAGE='en_US.UTF-8 git' git submodule foreach git status", cwd=os.path.dirname(unittest_folder), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
374
+        output.print_info(output.STATUS_FAILED)
375
+    # GIT_REPO
376
+    output.print_action('Analysing repository status...')
377
+    output.print_info(jsonlog.status_git(ut_folder))
378
+    # SUBMODULES
379
+    output.print_action('Analysing submodule status...')
380
+    process = subprocess.Popen("LANGUAGE='en_US.UTF-8 git' git submodule foreach git status", cwd=ut_folder, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
412
     stdoutput, stderroutput = process.communicate()
381
     stdoutput, stderroutput = process.communicate()
413
     if stderroutput == b'':
382
     if stderroutput == b'':
414
         module = None
383
         module = None
425
                 data[m] += line
394
                 data[m] += line
426
         for key in data:
395
         for key in data:
427
             if "working tree clean" not in data[key] and "working directory clean" not in data[key]:
396
             if "working tree clean" not in data[key] and "working directory clean" not in data[key]:
428
-                data[key] = ("local changes", FAIL)
397
+                data[key] = ("LOCAL CHANGES", output.termcolors.WARNING)
429
             elif "Your branch is behind" in data[key]:
398
             elif "Your branch is behind" in data[key]:
430
-                data[key] = ("no up to date (try git pull)", FAIL)
399
+                data[key] = ("OUTDATED (try git pull)", output.termcolors.WARNING)
431
             elif "HEAD detached at" in data[key]:
400
             elif "HEAD detached at" in data[key]:
432
-                data[key] = ("no up to date (try git checkout master)", FAIL)
401
+                data[key] = ("OUTDATED (try git checkout master)", output.termcolors.WARNING)
433
             elif "Your branch is ahead of" in data[key]:
402
             elif "Your branch is ahead of" in data[key]:
434
-                data[key] = ("push required", WARNING)
403
+                data[key] = ("CHANGED (try git push)", output.termcolors.WARNING)
435
             elif "nothing to commit" in data[key]:
404
             elif "nothing to commit" in data[key]:
436
-                data[key] = ("clean", OKGREEN)
405
+                data[key] = ("CLEAN", output.termcolors.OKGREEN)
437
             else:
406
             else:
438
-                data[key] = ("unknown", FAIL)
439
-            print_info('Submodule %s... %s' % (key, data[key][1] + data[key][0]))
407
+                data[key] = ("UNKNOWN", output.termcolors.FAIL)
408
+            output.print_info('Submodule %s... %s' % (key, data[key][1] + data[key][0]))
440
     else:
409
     else:
441
-        print_info('FAILED', color=FAIL)
410
+        output.print_info(output.STATUS_FAILED)
442
     #
411
     #
443
-    print_header('Checking status of unittest and testresults in the library')
444
-    print_action('Loading Testrun data from %s' % unittest_filename(unittest_folder, FILES['data-collection']))
445
-    with open(unittest_filename(unittest_folder, FILES['data-collection']), 'r') as fh:
446
-        data_collection = json.loads(fh.read())
447
-    print_action('Checking release state of this testrun... ')
448
-    if data_collection[UNITTEST_KEY_TESTOBJECT_INFO]['State'] != 'Released':
449
-        print_info("FAILED", FAIL)
450
-    else:
451
-        print_info("SUCCESS", OKGREEN)
412
+    # TESTRUN STATUS
413
+    #
414
+    output.print_header('Checking status of unittest in the library')
415
+    for txt, fcn in (
416
+        ('Checking release state... ', jsonlog.get_lib_release_state),
417
+        ('Checking testcase integrity... ', jsonlog.get_lib_testcase_integrity),
418
+        ('Checking source integrity... ', jsonlog.get_lib_src_integrity)
419
+    ):
420
+        output.print_action(txt)
421
+        output.print_info(fcn(ut_folder))
422
+    output.print_action('Checking code coverage... ')
423
+    output.print_coverage(*jsonlog.lib_coverage(ut_folder))
452
     #
424
     #
453
-    from unittest.module_status import module_unittest_status
454
-    print_action('Checking status of testrults in library...')
455
-    st = module_unittest_status(os.path.abspath(os.path.join(unittest_folder, '..')))
456
-    stc = {
457
-        'RELEASED': OKGREEN,
458
-        'IN_WORK': OKBLUE,
459
-    }.get(st, FAIL)
460
-    print_info(st, stc)
425
+    output.print_header('Checking status of unittest for this testrun')
426
+    for txt, fcn in (
427
+        ('Checking release state... ', jsonlog.get_ut_release_state),
428
+        ('Checking testcase integrity... ', jsonlog.get_ut_testcase_integrity),
429
+        ('Checking source integrity... ', jsonlog.get_ut_src_integrity)
430
+    ):
431
+        output.print_action(txt)
432
+        output.print_info(fcn(ut_folder))
433
+    output.print_action('Checking code coverage... ')
434
+    output.print_coverage(*jsonlog.ut_coverage(ut_folder))

+ 10
- 11
scripts/Makefile View File

27
 	@echo "    - testrun_smoke: Run some testcases"
27
 	@echo "    - testrun_smoke: Run some testcases"
28
 	@echo "    - testrun_single: Run one testcases"
28
 	@echo "    - testrun_single: Run one testcases"
29
 
29
 
30
-release: clean prepare testrun_full coverage_analysis finalise compile publish status
31
-full: clean prepare testrun_full coverage_analysis finalise compile status
32
-short: clean prepare testrun_short coverage_analysis finalise compile status
33
-smoke: clean prepare testrun_smoke coverage_analysis finalise compile status
34
-single: clean prepare testrun_single coverage_analysis finalise compile status
30
+release: testrun_full coverage_analysis finalise compile publish status
31
+full: testrun_full finalise compile status
32
+short: testrun_short finalise compile status
33
+smoke: testrun_smoke finalise compile status
34
+single: testrun_single finalise compile status
35
 
35
 
36
 clean:
36
 clean:
37
 	@$(PYT3_CMD) src/unittest/scripts/unittest.py clean
37
 	@$(PYT3_CMD) src/unittest/scripts/unittest.py clean
44
 prepare:
44
 prepare:
45
 	@$(PYT3_CMD) src/unittest/scripts/unittest.py prepare
45
 	@$(PYT3_CMD) src/unittest/scripts/unittest.py prepare
46
 
46
 
47
-testrun_full:
47
+testrun_full: clean prepare
48
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e full
48
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e full
49
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e full
49
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e full
50
 
50
 
51
-testrun_short:
51
+testrun_short: clean prepare
52
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e short
52
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e short
53
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e short
53
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e short
54
 
54
 
55
-testrun_smoke:
55
+testrun_smoke: clean prepare
56
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e smoke
56
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e smoke
57
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e smoke
57
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e smoke
58
 
58
 
59
-testrun_single:
60
-
59
+testrun_single: clean prepare
61
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e single
60
 	@$(COV2_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e single
62
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e single
61
 	@$(COV3_CMD) run -a --branch --source=`$(PYT3_CMD) src/config.py -p` src/unittest/scripts/unittest.py testrun -e single
63
 
62
 
65
 	@echo "\e[1m\e[93mCreating Coverage-XML-File: $(pwd)/testresults/coverage.xml\e[0m"
64
 	@echo "\e[1m\e[93mCreating Coverage-XML-File: $(pwd)/testresults/coverage.xml\e[0m"
66
 	@$(COV3_CMD) xml -o testresults/coverage.xml
65
 	@$(COV3_CMD) xml -o testresults/coverage.xml
67
 
66
 
68
-finalise:
67
+finalise: coverage_analysis
69
 	@$(PYT3_CMD) src/unittest/scripts/unittest.py finalise
68
 	@$(PYT3_CMD) src/unittest/scripts/unittest.py finalise
70
 
69
 
71
 compile:
70
 compile:

+ 1
- 1
scripts/unittest.py View File

19
 if report.TCEL_REVERSE_NAMED.get(tests.execution_level, report.TCEL_FULL) < report.TCEL_REVERSE_NAMED.get(options.execution_level, report.TCEL_FULL):
19
 if report.TCEL_REVERSE_NAMED.get(tests.execution_level, report.TCEL_FULL) < report.TCEL_REVERSE_NAMED.get(options.execution_level, report.TCEL_FULL):
20
     options.execution_level = tests.execution_level
20
     options.execution_level = tests.execution_level
21
 
21
 
22
-unittest.run.unittest(options, args, BASEPATH)
22
+unittest.run.unittest(options, args, os.path.dirname(BASEPATH))

Loading…
Cancel
Save