holado 0.9.0__py3-none-any.whl → 0.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of holado might be problematic. Click here for more details.
- holado/common/context/session_context.py +6 -5
- {holado-0.9.0.dist-info → holado-0.9.1.dist-info}/METADATA +1 -1
- {holado-0.9.0.dist-info → holado-0.9.1.dist-info}/RECORD +39 -39
- holado_core/common/block/base.py +3 -3
- holado_core/common/tools/path_manager.py +1 -1
- holado_django/server/django_projects/rest_api/rest_api/urls.py +1 -1
- holado_docker/tests/behave/steps/tools/docker_controller/client_steps.py +2 -2
- holado_docker/tools/docker_controller/client/rest/docker_controller_client.py +38 -1
- holado_docker/tools/docker_controller/server/run_docker_controller_in_docker.sh +3 -3
- holado_examples/tests/behave/testing_solution/environment.py +3 -3
- holado_examples/tests/behave/testing_solution/src/context/session_context.py +2 -2
- holado_examples/tests/behave/testing_solution/steps/config_steps.py +1 -1
- holado_multitask/multithreading/loopthread.py +4 -4
- holado_python/common/tools/datetime.py +35 -17
- holado_python/standard_library/ssl/resources/certificates/tcpbin.crt +16 -16
- holado_python/standard_library/ssl/resources/certificates/tcpbin.key +26 -26
- holado_python/tests/behave/steps/standard_library/datetime_steps.py +2 -2
- holado_rabbitmq/tools/rabbitmq/rabbitmq_manager.py +3 -3
- holado_report/campaign/campaign_manager.py +8 -3
- holado_report/report/builders/detailed_scenario_failed_report_builder.py +11 -7
- holado_report/report/builders/failure_report_builder.py +4 -3
- holado_report/report/builders/short_scenario_failed_report_builder.py +6 -5
- holado_report/report/builders/summary_report_builder.py +1 -1
- holado_report/report/builders/summary_scenario_failed_report_builder.py +6 -5
- holado_report/report/builders/summary_scenario_report_builder.py +12 -11
- holado_report/report/execution_historic.py +4 -2
- holado_report/report/report_manager.py +63 -13
- holado_rest/api/rest/rest_client.py +5 -1
- holado_test/__init__.py +3 -0
- holado_test/common/context/feature_context.py +3 -3
- holado_test/common/context/scenario_context.py +3 -3
- holado_test/common/context/step_context.py +3 -3
- holado_test/test_server/client/rest/test_server_client.py +117 -0
- holado_test/test_server/server/run_test_server_in_docker.sh +7 -7
- holado_value/common/tools/unique_value_manager.py +2 -1
- test_holado/environment.py +1 -1
- test_holado/logging.conf +1 -0
- holado_docker/tools/docker_controller/docker_controller_manager.py +0 -46
- {holado-0.9.0.dist-info → holado-0.9.1.dist-info}/WHEEL +0 -0
- {holado-0.9.0.dist-info → holado-0.9.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,7 +22,7 @@ import os
|
|
|
22
22
|
from holado_core.common.tools.converters.converter import Converter
|
|
23
23
|
from enum import Enum
|
|
24
24
|
from holado_python.common.enums import ArithmeticOperator
|
|
25
|
-
from datetime import timedelta
|
|
25
|
+
from datetime import timedelta
|
|
26
26
|
from dateutil.relativedelta import relativedelta
|
|
27
27
|
import math
|
|
28
28
|
from decimal import Decimal
|
|
@@ -39,6 +39,9 @@ FORMAT_DATETIME_ISO = '%Y-%m-%dT%H:%M:%S.%fZ'
|
|
|
39
39
|
FORMAT_DATETIME_ISO_SECONDS = '%Y-%m-%dT%H:%M:%SZ'
|
|
40
40
|
FORMAT_DATETIME_HUMAN_SECOND = '%Y-%m-%d %H:%M:%S'
|
|
41
41
|
|
|
42
|
+
TIMEZONE_LOCAL = datetime.datetime.now().astimezone().tzinfo
|
|
43
|
+
TIMEZONE_UTC = datetime.timezone.utc
|
|
44
|
+
|
|
42
45
|
|
|
43
46
|
class DurationUnit(str, Enum):
|
|
44
47
|
# Nanosecond = "nanosecond"
|
|
@@ -55,11 +58,16 @@ class DurationUnit(str, Enum):
|
|
|
55
58
|
|
|
56
59
|
|
|
57
60
|
class DateTime(object):
|
|
61
|
+
""" Tools to manipulate datetimes.
|
|
62
|
+
Note: Naive and aware datetimes cannot be compared. Thus HolAdo methods always set datetime timezone when it is known.
|
|
63
|
+
In methods unable to define the timezone (ex: str_2_datetime), it is highly recommended to specify 'tz' argument.
|
|
64
|
+
"""
|
|
58
65
|
|
|
59
66
|
__is_system_time_in_tai = None
|
|
60
67
|
__is_system_time_expected_in_tai = None
|
|
61
68
|
__utc_to_tai_timedelta = None
|
|
62
69
|
|
|
70
|
+
|
|
63
71
|
def __init__(self):
|
|
64
72
|
pass
|
|
65
73
|
|
|
@@ -71,22 +79,22 @@ class DateTime(object):
|
|
|
71
79
|
return cls.__is_system_time_in_tai
|
|
72
80
|
|
|
73
81
|
@classmethod
|
|
74
|
-
def now(cls):
|
|
75
|
-
return datetime.datetime.now()
|
|
82
|
+
def now(cls, tz=TIMEZONE_LOCAL):
|
|
83
|
+
return datetime.datetime.now(tz=tz)
|
|
76
84
|
|
|
77
85
|
@classmethod
|
|
78
86
|
def utcnow(cls):
|
|
79
87
|
if cls.is_system_time_in_tai():
|
|
80
|
-
return
|
|
88
|
+
return cls.now(TIMEZONE_UTC) - cls.utc_to_tai_timedelta()
|
|
81
89
|
else:
|
|
82
|
-
return
|
|
90
|
+
return cls.now(TIMEZONE_UTC)
|
|
83
91
|
|
|
84
92
|
@classmethod
|
|
85
93
|
def tainow(cls):
|
|
86
94
|
if cls.is_system_time_in_tai():
|
|
87
|
-
return
|
|
95
|
+
return cls.now(TIMEZONE_UTC)
|
|
88
96
|
else:
|
|
89
|
-
return
|
|
97
|
+
return cls.now(TIMEZONE_UTC) + cls.utc_to_tai_timedelta()
|
|
90
98
|
|
|
91
99
|
@classmethod
|
|
92
100
|
def utc_to_tai_timedelta(cls):
|
|
@@ -126,8 +134,15 @@ class DateTime(object):
|
|
|
126
134
|
return res
|
|
127
135
|
|
|
128
136
|
@classmethod
|
|
129
|
-
def str_2_datetime(cls, dt_str, dt_format=None,
|
|
130
|
-
"""Convert string to datetime instance
|
|
137
|
+
def str_2_datetime(cls, dt_str, dt_format=None, tz=None):
|
|
138
|
+
"""Convert string to datetime instance
|
|
139
|
+
@param dt_format If defined, use this format to parse string rather than using first matching format
|
|
140
|
+
@param tz If defined, return a datetime with this timezone.
|
|
141
|
+
If string already defines a timezone, the datetime is converted to this timezone,
|
|
142
|
+
else the string is supposed to represent a datetime in this timezone and timezone is set in result datetime.
|
|
143
|
+
Note: Naive and aware datetimes cannot be compared. Thus HolAdo methods always set datetime timezone when it is known.
|
|
144
|
+
It is highly recommended to specify 'tz' argument
|
|
145
|
+
"""
|
|
131
146
|
res = None
|
|
132
147
|
if dt_format is None:
|
|
133
148
|
res = dateutil.parser.parse(dt_str)
|
|
@@ -135,8 +150,11 @@ class DateTime(object):
|
|
|
135
150
|
res = datetime.datetime.strptime(dt_str, dt_format)
|
|
136
151
|
|
|
137
152
|
# Set timezone if needed
|
|
138
|
-
if
|
|
139
|
-
|
|
153
|
+
if tz is not None:
|
|
154
|
+
if res.tzinfo is None:
|
|
155
|
+
res = res.replace(tzinfo=tz)
|
|
156
|
+
else:
|
|
157
|
+
res = res.astimezone(tz)
|
|
140
158
|
|
|
141
159
|
return res
|
|
142
160
|
|
|
@@ -162,19 +180,19 @@ class DateTime(object):
|
|
|
162
180
|
return res
|
|
163
181
|
|
|
164
182
|
@classmethod
|
|
165
|
-
def _get_datetime(cls, dt):
|
|
183
|
+
def _get_datetime(cls, dt, tz_in_str=None):
|
|
166
184
|
res = None
|
|
167
185
|
if dt is not None:
|
|
168
186
|
if isinstance(dt, datetime.datetime):
|
|
169
187
|
res = dt
|
|
170
188
|
elif isinstance(dt, str):
|
|
171
|
-
res = DateTime.str_2_datetime(dt)
|
|
189
|
+
res = DateTime.str_2_datetime(dt, tz=tz_in_str)
|
|
172
190
|
else:
|
|
173
191
|
raise TechnicalException(f"Datetime can be a datetime, a str containing a datetime, or None")
|
|
174
192
|
return res
|
|
175
193
|
|
|
176
194
|
@classmethod
|
|
177
|
-
def _get_epoch_datetime(cls, epoch):
|
|
195
|
+
def _get_epoch_datetime(cls, epoch, tz_in_str=None):
|
|
178
196
|
res = None
|
|
179
197
|
if epoch is not None:
|
|
180
198
|
if isinstance(epoch, datetime.datetime):
|
|
@@ -183,7 +201,7 @@ class DateTime(object):
|
|
|
183
201
|
if epoch in ['EPOCH_1970', 'EPOCH_JULIAN_CNES', 'EPOCH_JULIAN_NASA']:
|
|
184
202
|
res = eval(epoch)
|
|
185
203
|
else:
|
|
186
|
-
res = DateTime.str_2_datetime(epoch)
|
|
204
|
+
res = DateTime.str_2_datetime(epoch, tz=tz_in_str)
|
|
187
205
|
else:
|
|
188
206
|
raise TechnicalException(f"Epoch can be a datetime, a str containing a datetime, a str containing an EPOCH name, or None")
|
|
189
207
|
return res
|
|
@@ -296,7 +314,7 @@ class DateTime(object):
|
|
|
296
314
|
"""
|
|
297
315
|
dt_src = dt
|
|
298
316
|
if isinstance(dt_src, str):
|
|
299
|
-
dt_src = cls.str_2_datetime(dt_src, dt_format)
|
|
317
|
+
dt_src = cls.str_2_datetime(dt_src, dt_format, tz=TIMEZONE_UTC)
|
|
300
318
|
|
|
301
319
|
return dt_src + DateTime.utc_to_tai_timedelta()
|
|
302
320
|
|
|
@@ -308,7 +326,7 @@ class DateTime(object):
|
|
|
308
326
|
"""
|
|
309
327
|
dt_src = dt
|
|
310
328
|
if isinstance(dt_src, str):
|
|
311
|
-
dt_src = cls.str_2_datetime(dt_src, dt_format)
|
|
329
|
+
dt_src = cls.str_2_datetime(dt_src, dt_format, tz=TIMEZONE_UTC)
|
|
312
330
|
|
|
313
331
|
return dt_src - DateTime.utc_to_tai_timedelta()
|
|
314
332
|
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
MIIDZTCCAk2gAwIBAgIBKjANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMCVVMx
|
|
3
3
|
CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZ0
|
|
4
4
|
Y3BiaW4xDDAKBgNVBAsMA29wczETMBEGA1UEAwwKdGNwYmluLmNvbTEjMCEGCSqG
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
FOLuMowBSAZfV5v82LmlaIIOvU/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
SIb3DQEJARYUaGFycnliYWdkaUBnbWFpbC5jb20wHhcNMjUxMDAyMTMzNjQ1WhcN
|
|
6
|
+
MjUxMDAzMTMzNjQ1WjAcMRowGAYDVQQDDBF0Y3BiaW4uY29tLWNsaWVudDCCASIw
|
|
7
|
+
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2xah/MsJKGnIpj84nYfBRCeAh8
|
|
8
|
+
MmN5dZwUCteehkX+wFhioEx1loAIqcqs6MPe7qQdeROuOZlGeiDR/6X0mnDsgyR4
|
|
9
|
+
qUnrIaRHS3EFWGtGp0WRLsQhKNvtxAHL7dErz7BoxTO5gV/w6dcT3uPORfZxkZdm
|
|
10
|
+
6t01t7DwPFktopQju9E8eeMBKVKaO1RrclZKkWEyfuHP3wNpIE6GwsH8jCn4I+r/
|
|
11
|
+
Y8Pgd+k4EyCaH+ngtFbS0lEhxxuqTpPRYyQrlEDMa1i/nETuMiL2WFkjEO2gEX/p
|
|
12
|
+
w05GlO3YUTDpaXWUWZf+Ck7MYevrFDC57oSZvMwTn5pJrQztvNJjFc+YF6kCAwEA
|
|
13
|
+
AaNCMEAwHQYDVR0OBBYEFLuHuKWOQ/U1+OpiGgffNV1faI9qMB8GA1UdIwQYMBaA
|
|
14
|
+
FOLuMowBSAZfV5v82LmlaIIOvU/DMA0GCSqGSIb3DQEBCwUAA4IBAQBYIRlg6Paz
|
|
15
|
+
ALTKoBm8nRB19n4d7Ay+U1bUBCP2U5vZkUTSu05ttQXT72TaFIaT04pFs9uIHGFZ
|
|
16
|
+
9yhP2DgbuCaexQrvf9yf6nnoCqLjlhJ8Y0NmscK14Hp9GgVSnkXeweL82gFsXB45
|
|
17
|
+
FaqqyDn20QiH14nwU2H7g8y/Ys0PIemhjG8UT7OjSLyhkaCkxwYy88N/2YjX3hGH
|
|
18
|
+
9eTHvfMZ+9E7Urh3DevivhfPQnX/6lUAOK7Sr+WTIEjpZ89Lz/rLltRCXoXv75C4
|
|
19
|
+
PdRoxB2/lo+3+X1i4B7ujaduZDLaMyPcckbpuTYxjPZtoxhLyYkKgzQTUMwYsVrW
|
|
20
|
+
DoI6HuqlfzoH
|
|
21
21
|
-----END CERTIFICATE-----
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
2
|
+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtsWofzLCShpyK
|
|
3
|
+
Y/OJ2HwUQngIfDJjeXWcFArXnoZF/sBYYqBMdZaACKnKrOjD3u6kHXkTrjmZRnog
|
|
4
|
+
0f+l9Jpw7IMkeKlJ6yGkR0txBVhrRqdFkS7EISjb7cQBy+3RK8+waMUzuYFf8OnX
|
|
5
|
+
E97jzkX2cZGXZurdNbew8DxZLaKUI7vRPHnjASlSmjtUa3JWSpFhMn7hz98DaSBO
|
|
6
|
+
hsLB/Iwp+CPq/2PD4HfpOBMgmh/p4LRW0tJRIccbqk6T0WMkK5RAzGtYv5xE7jIi
|
|
7
|
+
9lhZIxDtoBF/6cNORpTt2FEw6Wl1lFmX/gpOzGHr6xQwue6EmbzME5+aSa0M7bzS
|
|
8
|
+
YxXPmBepAgMBAAECggEBAIqgeMTch2jKyxGg6HTyNUWuL0MGbOj7vaROUsD4os4m
|
|
9
|
+
nrlsLegYSX/yaiF6k2QQ/4I4i7Prb8kneL3NHS8E5GaQPbLUIrj+UyFcTZfs3j7w
|
|
10
|
+
avyY/SxIEuZFBBUy/6HcR6zSUeIQgnNiQiAImfJTZX9l8P9Xgsf+4Zb0hhXe2E1G
|
|
11
|
+
TqLAYWnLoxD9us0rryQb37mRIREKcTO3qza+FXk32bWe83f1Dy46JJIChIoQg/QB
|
|
12
|
+
hwzSL51ld22fy7p+bsqeI3HUDWHplq4T0lws0SGUd4IvntF9rNGYHAI+aUKwiUBC
|
|
13
|
+
g/0se9+GBKeMSjhS11F9/Clg4i0E/tN/poOytA83aAECgYEA3+E0bhbaFAvzzevv
|
|
14
|
+
tAWSXkwHSFZ745KsJSJ8OOVkd+ATleyGl3AoRTrDxNqY+R/TvBFaTyiY+zqGV6tj
|
|
15
|
+
NI8SaSXuhRzbA9zDL2rSH7GIOeqzUs8PSUMk6JnmfCKk+aTBOoi8ULolHE4N6B45
|
|
16
|
+
te3GVgy/luJK22pPLCMsmL+D0ykCgYEAxpzr8T2CPVtl33W+loGbvrqZ1xXgq/7n
|
|
17
|
+
IsjHZdVdFsIIxFhtE2A2iO/7vMsLmwkZ7LgbtHcfEPOxjx5VzVt89l1I2lnP0jW+
|
|
18
|
+
pjKrN/eyXcHnWLLPCEtXA06oIvyem/VMSGXumu7EcOJZjnG3/PmqCWCjc2UUo2lJ
|
|
19
|
+
F2rQdC9bMIECgYEAl3nSdaI0j1e+79bw6kbSz8Z1LvaFAGce3klE72IV5h3QYqIU
|
|
20
|
+
NqaGOMEX8DtPQU/NfPPovKJlT6Y7e1nU15zuAgLOLXZmoWhfD9ggr5z45Obtydub
|
|
21
|
+
JiCt+ksW7WqrYNWef7JAaAZqUYpmUmUQ+w0UIuihQL9/kpGNW/m4lOkPknECgYAI
|
|
22
|
+
gbodWAwXAq4nVwy1t5FrJuTl8HryAvX1aHIZ63yUN/VWK49ocAuF6/l1SaESn94r
|
|
23
|
+
ZGtTXHLJMBbf0WXNaOi+SJqRN52OHF0xEySAPiy2lVKKWwZBDbEJZDoRXY6RkX0V
|
|
24
|
+
8L+6hRWG3DsHvdkqjar5wdjeXWr34M+PoDSTdV/LgQKBgFAqJc4I91AK8Ah9Ba8k
|
|
25
|
+
LqYtRFGFJ2J+p8QqcibfT6d6tZqWffxiXbQ5bS52/fmM3BdxEHjtzLdA7cOqCh6g
|
|
26
|
+
79kxRb3B5jjq5JvGtLy89VphZ08W9dhzgL/l3KGtgMobfTYUEDaNk33oExhItQnx
|
|
27
|
+
F97ecAMIx20oqFFOg6N0unwW
|
|
28
28
|
-----END PRIVATE KEY-----
|
|
@@ -45,9 +45,9 @@ def step_impl(context, varname, format_value, duration, duration_unit, value):
|
|
|
45
45
|
deltaT = timedelta(**args)
|
|
46
46
|
|
|
47
47
|
if value == "ago":
|
|
48
|
-
date =
|
|
48
|
+
date = DateTime.now() - deltaT
|
|
49
49
|
elif value == "ahead":
|
|
50
|
-
date =
|
|
50
|
+
date = DateTime.now() + deltaT
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
v = date.strftime(format_value)
|
|
@@ -92,12 +92,12 @@ class RMQManager:
|
|
|
92
92
|
# polling_seconds = 0.001 # a polling period below 1 ms is usually not efficient in testing context
|
|
93
93
|
#
|
|
94
94
|
# # Wait first message is needed
|
|
95
|
-
# dt_begin =
|
|
95
|
+
# dt_begin = DateTime.now()
|
|
96
96
|
# dt_last_poll = dt_begin
|
|
97
97
|
# if first_timeout_seconds is not None:
|
|
98
98
|
# while (dt_last_poll - dt_begin).total_seconds() < first_timeout_seconds:
|
|
99
99
|
# nb_msg_by_consumer = {c.name: c.nb_messages for c in consumers if c.nb_messages > 0}
|
|
100
|
-
# dt_last_poll =
|
|
100
|
+
# dt_last_poll = DateTime.now()
|
|
101
101
|
# if len(nb_msg_by_consumer) > 0:
|
|
102
102
|
# res = sum(nb_msg_by_consumer.values())
|
|
103
103
|
# if Tools.do_log(logger, logging.DEBUG):
|
|
@@ -115,7 +115,7 @@ class RMQManager:
|
|
|
115
115
|
# while (dt_last_poll - dt_last_receive).total_seconds() < window_seconds:
|
|
116
116
|
# nb_msg_by_consumer = {c.name: c.nb_messages for c in consumers if c.nb_messages > 0}
|
|
117
117
|
# nb = sum(nb_msg_by_consumer.values())
|
|
118
|
-
# dt_last_poll =
|
|
118
|
+
# dt_last_poll = DateTime.now()
|
|
119
119
|
# if nb > res:
|
|
120
120
|
# res = nb
|
|
121
121
|
# if Tools.do_log(logger, logging.DEBUG):
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
from holado.common.context.session_context import SessionContext
|
|
15
15
|
import logging
|
|
16
16
|
from holado_core.common.resource.table_data_manager import TableDataManager
|
|
17
|
-
from holado_python.common.tools.datetime import DateTime
|
|
17
|
+
from holado_python.common.tools.datetime import DateTime, TIMEZONE_LOCAL
|
|
18
18
|
import os
|
|
19
19
|
from holado_system.system.filesystem.file import File
|
|
20
|
+
import re
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
logger = logging.getLogger(__name__)
|
|
@@ -99,7 +100,7 @@ class CampaignManager(object):
|
|
|
99
100
|
res_dict_list = client.execute(query_str, result_as_dict_list=True, as_generator=False)
|
|
100
101
|
|
|
101
102
|
status_dt_str = res_dict_list[0]['status_at'] if res_dict_list else None
|
|
102
|
-
status_dt = DateTime.str_2_datetime(status_dt_str) if status_dt_str else None
|
|
103
|
+
status_dt = DateTime.str_2_datetime(status_dt_str, tz=TIMEZONE_LOCAL) if status_dt_str else None
|
|
103
104
|
return status_dt
|
|
104
105
|
|
|
105
106
|
def import_campaign_reports(self, report_path):
|
|
@@ -182,7 +183,11 @@ class CampaignManager(object):
|
|
|
182
183
|
parts = line.split(' - ')
|
|
183
184
|
status_dt_str = parts[0]
|
|
184
185
|
scenario_name = parts[1]
|
|
185
|
-
|
|
186
|
+
status_info = parts[-1]
|
|
187
|
+
|
|
188
|
+
m = re.match(r"^(.*?)(?: \(.*\))?$", status_info)
|
|
189
|
+
status = m.group(1)
|
|
190
|
+
|
|
186
191
|
self.update_or_add_campaign_scenario(camp_id, scenario_name, status=status, status_at_str=status_dt_str)
|
|
187
192
|
|
|
188
193
|
|
|
@@ -33,10 +33,10 @@ class DetailedScenarioFailedReportBuilder(ReportBuilder):
|
|
|
33
33
|
|
|
34
34
|
def after_scenario(self, scenario, scenario_report=None):
|
|
35
35
|
from holado_report.report.report_manager import ReportManager
|
|
36
|
-
status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
36
|
+
category_validation, status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
37
37
|
|
|
38
38
|
if status_validation != "Passed":
|
|
39
|
-
self.__file_fail_add_scenario(scenario, scenario_report, status_validation, step_failed, step_number)
|
|
39
|
+
self.__file_fail_add_scenario(scenario, scenario_report, category_validation, status_validation, step_failed, step_number)
|
|
40
40
|
|
|
41
41
|
def after_all(self):
|
|
42
42
|
# Manage file fail
|
|
@@ -44,13 +44,13 @@ class DetailedScenarioFailedReportBuilder(ReportBuilder):
|
|
|
44
44
|
self.__file_fail.close()
|
|
45
45
|
self.__file_fail = None
|
|
46
46
|
|
|
47
|
-
def __file_fail_add_scenario(self, scenario, scenario_report, status_validation, step_failed, step_number):
|
|
47
|
+
def __file_fail_add_scenario(self, scenario, scenario_report, category_validation, status_validation, step_failed, step_number):
|
|
48
48
|
if self.__is_format_xml:
|
|
49
|
-
self.__file_fail_add_scenario_xml(scenario, scenario_report, status_validation, step_failed, step_number)
|
|
49
|
+
self.__file_fail_add_scenario_xml(scenario, scenario_report, category_validation, status_validation, step_failed, step_number)
|
|
50
50
|
else:
|
|
51
|
-
self.__file_fail_add_scenario_txt(scenario, scenario_report, status_validation, step_failed, step_number)
|
|
51
|
+
self.__file_fail_add_scenario_txt(scenario, scenario_report, category_validation, status_validation, step_failed, step_number)
|
|
52
52
|
|
|
53
|
-
def __file_fail_add_scenario_xml(self, scenario, scenario_report, status_validation, step_failed, step_number):
|
|
53
|
+
def __file_fail_add_scenario_xml(self, scenario, scenario_report, category_validation, status_validation, step_failed, step_number):
|
|
54
54
|
from holado_report.report.report_manager import ReportManager
|
|
55
55
|
|
|
56
56
|
self.__open_file_if_needed()
|
|
@@ -61,6 +61,8 @@ class DetailedScenarioFailedReportBuilder(ReportBuilder):
|
|
|
61
61
|
msg_list.append(f" <scenario>{scenario.name}</scenario>")
|
|
62
62
|
msg_list.append(f" <report>{scenario_report.report_path}</report>")
|
|
63
63
|
msg_list.append(f" <tags>-t " + " -t ".join(scenario.feature.tags + scenario.tags) + "</tags>")
|
|
64
|
+
if category_validation:
|
|
65
|
+
msg_list.append(f" <validation_category>{category_validation}</validation_category>")
|
|
64
66
|
msg_list.append(f" <validation_status>{status_validation}</validation_status>")
|
|
65
67
|
if step_failed is not None:
|
|
66
68
|
msg_list.append(f" <failure>")
|
|
@@ -102,7 +104,7 @@ class DetailedScenarioFailedReportBuilder(ReportBuilder):
|
|
|
102
104
|
self.__file_fail.write(msg)
|
|
103
105
|
self.__file_fail.flush()
|
|
104
106
|
|
|
105
|
-
def __file_fail_add_scenario_txt(self, scenario, scenario_report, status_validation, step_failed, step_number):
|
|
107
|
+
def __file_fail_add_scenario_txt(self, scenario, scenario_report, category_validation, status_validation, step_failed, step_number):
|
|
106
108
|
from holado_report.report.report_manager import ReportManager
|
|
107
109
|
|
|
108
110
|
self.__open_file_if_needed()
|
|
@@ -112,6 +114,8 @@ class DetailedScenarioFailedReportBuilder(ReportBuilder):
|
|
|
112
114
|
msg_list.append(f" Scenario: {scenario.name}")
|
|
113
115
|
msg_list.append(f" Report: {scenario_report.report_path}")
|
|
114
116
|
msg_list.append(f" Tags: -t " + " -t ".join(scenario.feature.tags + scenario.tags))
|
|
117
|
+
if category_validation:
|
|
118
|
+
msg_list.append(f" Validation category: {category_validation}")
|
|
115
119
|
msg_list.append(f" Validation status: {status_validation}")
|
|
116
120
|
if step_failed is not None:
|
|
117
121
|
msg_list.append(f" Failure:")
|
|
@@ -41,16 +41,17 @@ class FailureReportBuilder(ReportBuilder):
|
|
|
41
41
|
|
|
42
42
|
def after_scenario(self, scenario, scenario_report=None):
|
|
43
43
|
from holado_report.report.report_manager import ReportManager
|
|
44
|
-
status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
44
|
+
category_validation, status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
45
45
|
|
|
46
46
|
if status_validation != "Passed":
|
|
47
47
|
step_error_message = ReportManager.get_step_error_message(step_failed).strip()
|
|
48
48
|
if step_error_message not in self.__failures:
|
|
49
49
|
self.__failures[step_error_message] = []
|
|
50
50
|
|
|
51
|
+
category_str = f" ({category_validation})" if category_validation else ""
|
|
51
52
|
if self.__file_format == 'txt':
|
|
52
53
|
msg_list = []
|
|
53
|
-
msg_list.append(f"scenario in {scenario.filename} at l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}")
|
|
54
|
+
msg_list.append(f"scenario in {scenario.filename} at l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}{category_str}")
|
|
54
55
|
msg_list.append(f" Feature/Scenario: {scenario.feature.name} => {scenario.name}")
|
|
55
56
|
msg_list.append(f" Report: {scenario_report.report_path}")
|
|
56
57
|
msg_list.append(f" Tags: -t " + " -t ".join(scenario.feature.tags + scenario.tags))
|
|
@@ -59,7 +60,7 @@ class FailureReportBuilder(ReportBuilder):
|
|
|
59
60
|
self.__failures[step_error_message].append(msg_scenario)
|
|
60
61
|
elif self.__file_format in ['json', 'xml']:
|
|
61
62
|
scenario_info = {
|
|
62
|
-
'title': f"{scenario.filename} - l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}",
|
|
63
|
+
'title': f"{scenario.filename} - l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}{category_str}",
|
|
63
64
|
'scenario': f"{scenario.feature.name} => {scenario.name}",
|
|
64
65
|
'report': scenario_report.report_path,
|
|
65
66
|
'tags': "-t " + " -t ".join(scenario.feature.tags + scenario.tags),
|
|
@@ -32,10 +32,10 @@ class ShortScenarioFailedReportBuilder(ReportBuilder):
|
|
|
32
32
|
|
|
33
33
|
def after_scenario(self, scenario, scenario_report=None):
|
|
34
34
|
from holado_report.report.report_manager import ReportManager
|
|
35
|
-
status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
35
|
+
category_validation, status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
36
36
|
|
|
37
37
|
if status_validation != "Passed":
|
|
38
|
-
self.__file_fail_add_scenario(scenario, scenario_report, status_validation, step_failed, step_number)
|
|
38
|
+
self.__file_fail_add_scenario(scenario, scenario_report, category_validation, status_validation, step_failed, step_number)
|
|
39
39
|
|
|
40
40
|
def after_all(self):
|
|
41
41
|
# Manage file fail
|
|
@@ -43,16 +43,17 @@ class ShortScenarioFailedReportBuilder(ReportBuilder):
|
|
|
43
43
|
self.__file_fail.close()
|
|
44
44
|
self.__file_fail = None
|
|
45
45
|
|
|
46
|
-
def __file_fail_add_scenario(self, scenario, scenario_report, status_validation, step_failed, step_number):
|
|
46
|
+
def __file_fail_add_scenario(self, scenario, scenario_report, category_validation, status_validation, step_failed, step_number):
|
|
47
47
|
from holado_report.report.report_manager import ReportManager
|
|
48
48
|
|
|
49
49
|
self.__open_file_if_needed()
|
|
50
50
|
|
|
51
51
|
msg_list = []
|
|
52
|
+
category_str = f" ({category_validation})" if category_validation else ""
|
|
52
53
|
if step_failed is not None:
|
|
53
|
-
msg_list.append(f"scenario in {scenario.filename} at l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}")
|
|
54
|
+
msg_list.append(f"scenario in {scenario.filename} at l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}{category_str}")
|
|
54
55
|
else:
|
|
55
|
-
msg_list.append(f"scenario in {scenario.filename} at l.{scenario.line} - step ? (missing step implementation ?) - {status_validation}")
|
|
56
|
+
msg_list.append(f"scenario in {scenario.filename} at l.{scenario.line} - step ? (missing step implementation ?) - {status_validation}{category_str}")
|
|
56
57
|
msg_list.append(f" Feature/Scenario: {scenario.feature.name} => {scenario.name}")
|
|
57
58
|
msg_list.append(f" Report: {scenario_report.report_path}")
|
|
58
59
|
msg_list.append(f" Tags: -t " + " -t ".join(scenario.feature.tags + scenario.tags))
|
|
@@ -63,7 +63,7 @@ class SummaryReportBuilder(ReportBuilder):
|
|
|
63
63
|
|
|
64
64
|
def after_scenario(self, scenario, scenario_report=None):
|
|
65
65
|
from holado_report.report.report_manager import ReportManager
|
|
66
|
-
status_name, _, _ = ReportManager.get_current_scenario_status_information(scenario)
|
|
66
|
+
_, status_name, _, _ = ReportManager.get_current_scenario_status_information(scenario)
|
|
67
67
|
|
|
68
68
|
if status_name not in self.__scenarios:
|
|
69
69
|
self.__scenarios[status_name] = 0
|
|
@@ -31,10 +31,10 @@ class SummaryScenarioFailedReportBuilder(ReportBuilder):
|
|
|
31
31
|
|
|
32
32
|
def after_scenario(self, scenario, scenario_report=None):
|
|
33
33
|
from holado_report.report.report_manager import ReportManager
|
|
34
|
-
status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
34
|
+
category_validation, status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
35
35
|
|
|
36
36
|
if status_validation != "Passed":
|
|
37
|
-
self.__file_fail_add_scenario(scenario, status_validation, step_failed, step_number)
|
|
37
|
+
self.__file_fail_add_scenario(scenario, category_validation, status_validation, step_failed, step_number)
|
|
38
38
|
|
|
39
39
|
def after_all(self):
|
|
40
40
|
# Manage file fail
|
|
@@ -42,12 +42,13 @@ class SummaryScenarioFailedReportBuilder(ReportBuilder):
|
|
|
42
42
|
self.__file_fail.close()
|
|
43
43
|
self.__file_fail = None
|
|
44
44
|
|
|
45
|
-
def __file_fail_add_scenario(self, scenario, status_validation, step_failed, step_number):
|
|
45
|
+
def __file_fail_add_scenario(self, scenario, category_validation, status_validation, step_failed, step_number):
|
|
46
46
|
self.__open_file_if_needed()
|
|
47
|
+
category_str = f" ({category_validation})" if category_validation else ""
|
|
47
48
|
if step_failed is not None:
|
|
48
|
-
self.__file_fail.write(f"scenario in {scenario.filename} at l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}\n")
|
|
49
|
+
self.__file_fail.write(f"scenario in {scenario.filename} at l.{scenario.line} - step {step_number} (l.{step_failed.line}) - {status_validation}{category_str}\n")
|
|
49
50
|
else:
|
|
50
|
-
self.__file_fail.write(f"scenario in {scenario.filename} at l.{scenario.line} - step ? (missing step implementation ?) - {status_validation}\n")
|
|
51
|
+
self.__file_fail.write(f"scenario in {scenario.filename} at l.{scenario.line} - step ? (missing step implementation ?) - {status_validation}{category_str}\n")
|
|
51
52
|
self.__file_fail.flush()
|
|
52
53
|
|
|
53
54
|
def __open_file_if_needed(self):
|
|
@@ -33,12 +33,12 @@ class SummaryScenarioReportBuilder(ReportBuilder):
|
|
|
33
33
|
|
|
34
34
|
def after_scenario(self, scenario, scenario_report=None):
|
|
35
35
|
from holado_report.report.report_manager import ReportManager
|
|
36
|
-
status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
36
|
+
category_validation, status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
37
37
|
|
|
38
38
|
if status_validation == "Passed":
|
|
39
|
-
self.__file_add_scenario_success(scenario, status_validation)
|
|
39
|
+
self.__file_add_scenario_success(scenario, category_validation, status_validation)
|
|
40
40
|
else:
|
|
41
|
-
self.__file_add_scenario_fail(scenario, status_validation, step_failed, step_number)
|
|
41
|
+
self.__file_add_scenario_fail(scenario, category_validation, status_validation, step_failed, step_number)
|
|
42
42
|
|
|
43
43
|
def after_all(self):
|
|
44
44
|
# Manage file fail
|
|
@@ -46,27 +46,28 @@ class SummaryScenarioReportBuilder(ReportBuilder):
|
|
|
46
46
|
self.__file.close()
|
|
47
47
|
self.__file = None
|
|
48
48
|
|
|
49
|
-
def __file_add_scenario_success(self, scenario, status_validation):
|
|
49
|
+
def __file_add_scenario_success(self, scenario, category_validation, status_validation):
|
|
50
50
|
self.__open_file_if_needed()
|
|
51
|
-
self.__file_write(scenario, None, status_validation)
|
|
51
|
+
self.__file_write(scenario, None, category_validation, status_validation)
|
|
52
52
|
self.__file.flush()
|
|
53
53
|
|
|
54
|
-
def __file_add_scenario_fail(self, scenario, status_validation, step_failed, step_number):
|
|
54
|
+
def __file_add_scenario_fail(self, scenario, category_validation, status_validation, step_failed, step_number):
|
|
55
55
|
self.__open_file_if_needed()
|
|
56
56
|
if step_failed is not None:
|
|
57
|
-
self.__file_write(scenario, f"step {step_number} (l.{step_failed.line})", status_validation)
|
|
57
|
+
self.__file_write(scenario, f"step {step_number} (l.{step_failed.line})", category_validation, status_validation)
|
|
58
58
|
else:
|
|
59
|
-
self.__file_write(scenario, f"step ? (missing step implementation ?)", status_validation)
|
|
59
|
+
self.__file_write(scenario, f"step ? (missing step implementation ?)", category_validation, status_validation)
|
|
60
60
|
self.__file.flush()
|
|
61
61
|
|
|
62
|
-
def __file_write(self, scenario, text, status_validation):
|
|
62
|
+
def __file_write(self, scenario, text, category_validation, status_validation):
|
|
63
63
|
dt = DateTime.now()
|
|
64
64
|
dt_str = DateTime.datetime_2_str(dt, FORMAT_DATETIME_HUMAN_SECOND)
|
|
65
65
|
|
|
66
|
+
category_str = f" ({category_validation})" if category_validation else ""
|
|
66
67
|
if text:
|
|
67
|
-
self.__file.write(f"{dt_str} - {scenario.filename} at l.{scenario.line} - {text} - {status_validation}\n")
|
|
68
|
+
self.__file.write(f"{dt_str} - {scenario.filename} at l.{scenario.line} - {text} - {status_validation}{category_str}\n")
|
|
68
69
|
else:
|
|
69
|
-
self.__file.write(f"{dt_str} - {scenario.filename} at l.{scenario.line} - {status_validation}\n")
|
|
70
|
+
self.__file.write(f"{dt_str} - {scenario.filename} at l.{scenario.line} - {status_validation}{category_str}\n")
|
|
70
71
|
|
|
71
72
|
def __open_file_if_needed(self):
|
|
72
73
|
if self.__file is None:
|
|
@@ -56,11 +56,12 @@ class ExecutionHistoric():
|
|
|
56
56
|
self.__get_execution_historic_current_feature_scenarios().append(seh)
|
|
57
57
|
|
|
58
58
|
def __new_ScenarioExecutionHistoric(self, scenario_context, scenario, scenario_report):
|
|
59
|
-
res = NamedTuple("ScenarioExecutionHistoric", scenario_context=object, scenario=object, scenario_report=object, steps_by_scope=dict, status_validation=str, step_failed=object, step_failed_number=int)
|
|
59
|
+
res = NamedTuple("ScenarioExecutionHistoric", scenario_context=object, scenario=object, scenario_report=object, steps_by_scope=dict, category_validation=str, status_validation=str, step_failed=object, step_failed_number=int)
|
|
60
60
|
res.scenario_context = scenario_context
|
|
61
61
|
res.scenario = scenario
|
|
62
62
|
res.scenario_report = scenario_report
|
|
63
63
|
res.steps_by_scope = {}
|
|
64
|
+
res.category_validation = None
|
|
64
65
|
res.status_validation = None
|
|
65
66
|
res.step_failed = None
|
|
66
67
|
res.step_failed_number = None
|
|
@@ -87,10 +88,11 @@ class ExecutionHistoric():
|
|
|
87
88
|
|
|
88
89
|
def after_scenario(self, scenario, scenario_report=None):
|
|
89
90
|
from holado_report.report.report_manager import ReportManager
|
|
90
|
-
status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
91
|
+
category_validation, status_validation, step_failed, step_number = ReportManager.get_current_scenario_status_information(scenario)
|
|
91
92
|
|
|
92
93
|
# Update execution historic
|
|
93
94
|
current_scenario = self.__get_execution_historic_current_scenario()
|
|
95
|
+
current_scenario.category_validation = category_validation
|
|
94
96
|
current_scenario.status_validation = status_validation
|
|
95
97
|
current_scenario.step_failed = step_failed
|
|
96
98
|
current_scenario.step_failed_number = step_number
|