10
10
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
# See the License for the specific language governing permissions and
12
12
# limitations under the License
13
- import logging
13
+ """Report portal Nested Step handling module.
14
+
15
+ The module for handling and reporting Report Portal Nested Steps inside python
16
+ test frameworks. Import 'step' function to use it as decorator or together with
17
+ 'with' keyword to divide your tests on smaller steps.
18
+
19
+ Usage as decorator:
20
+ .. highlight:: python
21
+ .. code-block:: python
22
+
23
+ from reportportal_client import step
24
+
25
+ @step
26
+ def my_nested_step():
27
+ pass
28
+
29
+ def test_my_nested_step():
30
+ my_nested_step()
31
+
32
+
33
+ Usage with 'with' keyword:
34
+ .. highlight:: python
35
+ .. code-block:: python
36
+
37
+ from reportportal_client import step
38
+
39
+ def test_my_nested_step():
40
+ with step('My nested step', status='INFO'):
41
+ pass
42
+
43
+ """
14
44
from functools import wraps
15
45
16
46
from reportportal_client ._local import current
22
52
'after_test' , 'after_suite' , 'after_class' ,
23
53
'after_groups' , 'after_method' )
24
54
25
- logger = logging .getLogger (__name__ )
26
- logger .addHandler (logging .NullHandler ())
27
-
28
55
29
56
# noinspection PyUnresolvedReferences
30
57
class StepReporter :
58
+ """Nested Steps context handling class."""
59
+
31
60
def __init__ (self , rp_client ):
61
+ """Initialize required attributes.
62
+
63
+ :param rp_client: Report Portal client which will be used to report
64
+ steps
65
+ """
32
66
self .__levels = []
33
67
self .client = rp_client
34
68
35
69
def set_parent (self , item_type , parent_id ):
70
+ """Put an id into parent items queue if it has correct type.
71
+
72
+ :param item_type: type of the parent item
73
+ :param parent_id: ID of the parent item
74
+ """
36
75
if parent_id is not NOT_FOUND :
37
76
if item_type .lower () in NESTED_STEP_ITEMS :
38
77
self .__levels .append (parent_id )
39
78
40
79
def get_parent (self ):
80
+ """Retrieve the last item in the parent queue."""
41
81
if len (self .__levels ) > 0 :
42
82
return self .__levels [- 1 ]
43
83
44
84
def remove_parent (self , parent_id ):
85
+ """Remove the last item in the parent queue.
86
+
87
+ Remove the last item in the parent queue if it's equal to the method's
88
+ argument.
89
+ :param parent_id: item ID to remove
90
+ """
45
91
if len (self .__levels ) > 0 and self .__levels [- 1 ] == parent_id :
46
92
return self .__levels .pop ()
47
93
@@ -50,6 +96,12 @@ def start_nested_step(self,
50
96
start_time ,
51
97
parameters = None ,
52
98
** kwargs ):
99
+ """Start Nested Step on Report Portal.
100
+
101
+ :param name: Nested Step name
102
+ :param start_time: Nested Step start time
103
+ :param parameters: Nested Step parameters
104
+ """
53
105
parent_id = self .get_parent ()
54
106
if parent_id is None :
55
107
return
@@ -63,20 +115,38 @@ def finish_nested_step(self,
63
115
end_time ,
64
116
status = None ,
65
117
** kwargs ):
118
+ """Finish a Nested Step on Report Portal.
119
+
120
+ :param item_id: Nested Step item ID
121
+ :param end_time: Nested Step finish time
122
+ :param status: Nested Step finish status
123
+ """
66
124
if not self .remove_parent (item_id ):
67
125
return
68
126
return self .client .finish_test_item (item_id , end_time , status = status )
69
127
70
128
71
129
class Step :
130
+ """Step context handling class."""
131
+
72
132
def __init__ (self , name , params , status , rp_client ):
133
+ """Initialize required attributes.
134
+
135
+ :param name: Nested Step name
136
+ :param params: Nested Step parameters
137
+ :param status: Nested Step status which will be reported on
138
+ successful step finish
139
+ :param rp_client: Report Portal client which will be used to report
140
+ the step
141
+ """
73
142
self .name = name
74
143
self .params = params
75
144
self .status = status
76
145
self .client = rp_client
77
146
self .__item_id = None
78
147
79
148
def __enter__ (self ):
149
+ """Enter the runtime context related to this object."""
80
150
# Cannot call _local.current() early since it will be initialized
81
151
# before client put something in there
82
152
rp_client = self .client if self .client else current ()
@@ -94,6 +164,7 @@ def __enter__(self):
94
164
item_id = self .__item_id )
95
165
96
166
def __exit__ (self , exc_type , exc_val , exc_tb ):
167
+ """Exit the runtime context related to this object."""
97
168
# Cannot call _local.current() early since it will be initialized
98
169
# before client put something in there
99
170
rp_client = self .client if self .client else current ()
@@ -109,6 +180,8 @@ def __exit__(self, exc_type, exc_val, exc_tb):
109
180
.finish_nested_step (self .__item_id , timestamp (), step_status )
110
181
111
182
def __call__ (self , func ):
183
+ """The method is called when the instance is “called” as a function."""
184
+
112
185
@wraps (func )
113
186
def wrapper (* args , ** kwargs ):
114
187
__tracebackhide__ = True
@@ -122,6 +195,21 @@ def wrapper(*args, **kwargs):
122
195
123
196
124
197
def step (name_source , params = None , status = 'PASSED' , rp_client = None ):
198
+ """Nested step report function.
199
+
200
+ Create a Nested Step inside a test method on Report Portal.
201
+ :param name_source: a function or string which will be used as step's name
202
+ :param params: nested step parameters which will be reported as the
203
+ first step entry. If 'name_source' is a function
204
+ reference and this parameter is not specified, they
205
+ will be taken from the function.
206
+ :param status: the status which will be reported after the step
207
+ passed. Can be any of legal Report Portal statuses.
208
+ E.G.: PASSED, WARN, INFO, etc. Default value is PASSED
209
+ :param rp_client: overrides Report Portal client which will be used in
210
+ step reporting
211
+ :return: a step context object
212
+ """
125
213
if callable (name_source ):
126
214
name = name_source .__name__
127
215
return Step (name , params , status , rp_client )(name_source )
0 commit comments