19
19
import uuid
20
20
import logging
21
21
22
+ import six
22
23
from requests .adapters import HTTPAdapter
23
24
24
25
from .errors import ResponseError , EntryCreatedError , OperationCompletionError
27
28
logger .addHandler (logging .NullHandler ())
28
29
29
30
31
+ def _dict_to_payload (dictionary ):
32
+ def _str (value ):
33
+ if isinstance (value , six .text_type ):
34
+ # Don't try to encode 'unicode' in Python 2.
35
+ return value
36
+ return str (value )
37
+
38
+ return [
39
+ {"key" : key , "value" : _str (value )}
40
+ for key , value in dictionary .items ()
41
+ ]
42
+
43
+
30
44
def _get_id (response ):
31
45
try :
32
46
return _get_data (response )["id" ]
@@ -37,10 +51,10 @@ def _get_id(response):
37
51
38
52
def _get_msg (response ):
39
53
try :
40
- return _get_data (response )[ "msg" ]
54
+ return _get_data (response )
41
55
except KeyError :
42
56
raise OperationCompletionError (
43
- "No 'msg ' in response: {0}" .format (response .text ))
57
+ "No 'message ' in response: {0}" .format (response .text ))
44
58
45
59
46
60
def _get_data (response ):
@@ -75,12 +89,10 @@ def _get_json(response):
75
89
def _get_messages (data ):
76
90
error_messages = []
77
91
for ret in data .get ("responses" , [data ]):
78
- if "message" in ret :
79
- if "error_code" in ret :
80
- error_messages .append (
81
- "{0}: {1}" .format (ret ["error_code" ], ret ["message" ]))
82
- else :
83
- error_messages .append (ret ["message" ])
92
+ if "errorCode" in ret :
93
+ error_messages .append (
94
+ "{0}: {1}" .format (ret ["errorCode" ], ret .get ("message" ))
95
+ )
84
96
85
97
return error_messages
86
98
@@ -104,172 +116,153 @@ def uri_join(*uri_parts):
104
116
class ReportPortalService (object ):
105
117
"""Service class with report portal event callbacks."""
106
118
107
- def __init__ (self , endpoint , project , token , api_base = "api/v1" ,
119
+ def __init__ (self , endpoint , project , token ,
108
120
is_skipped_an_issue = True , verify_ssl = True , retries = None ):
109
121
"""Init the service class.
110
122
111
123
Args:
112
124
endpoint: endpoint of report portal service.
113
125
project: project name to use for launch names.
114
126
token: authorization token.
115
- api_base: defaults to api/v1, can be changed to other version.
116
127
is_skipped_an_issue: option to mark skipped tests as not
117
128
'To Investigate' items on Server side.
118
129
verify_ssl: option to not verify ssl certificates
119
130
"""
120
131
super (ReportPortalService , self ).__init__ ()
121
132
self .endpoint = endpoint
122
- self .api_base = api_base
123
133
self .project = project
124
134
self .token = token
125
135
self .is_skipped_an_issue = is_skipped_an_issue
126
- self .base_url = uri_join (self .endpoint ,
127
- self .api_base ,
128
- self .project )
136
+ self .base_url_v1 = uri_join (self .endpoint , "api/v1" , self .project )
137
+ self .base_url_v2 = uri_join (self .endpoint , "api/v2" , self .project )
129
138
130
139
self .session = requests .Session ()
131
140
if retries :
132
141
self .session .mount ('https://' , HTTPAdapter (max_retries = retries ))
133
142
self .session .mount ('http://' , HTTPAdapter (max_retries = retries ))
134
143
self .session .headers ["Authorization" ] = "bearer {0}" .format (self .token )
135
- self .stack = [None ]
136
144
self .launch_id = None
137
145
self .verify_ssl = verify_ssl
138
146
139
- def terminate (self ):
147
+ def terminate (self , * args , ** kwargs ):
140
148
pass
141
149
142
- def start_launch (self , name , start_time , description = None , tags = None ,
150
+ def start_launch (self , name , start_time , description = None , attributes = None ,
143
151
mode = None ):
152
+ if attributes is not None :
153
+ attributes = _dict_to_payload (attributes )
144
154
data = {
145
155
"name" : name ,
146
156
"description" : description ,
147
- "tags " : tags ,
148
- "start_time " : start_time ,
157
+ "attributes " : attributes ,
158
+ "startTime " : start_time ,
149
159
"mode" : mode
150
160
}
151
- url = uri_join (self .base_url , "launch" )
161
+ url = uri_join (self .base_url_v2 , "launch" )
152
162
r = self .session .post (url = url , json = data , verify = self .verify_ssl )
153
163
self .launch_id = _get_id (r )
154
- self .stack .append (None )
155
- logger .debug ("start_launch - Stack: %s" , self .stack )
164
+ logger .debug ("start_launch - ID: %s" , self .launch_id )
156
165
return self .launch_id
157
166
158
- def _finalize_launch (self , end_time , action , status ):
167
+ def finish_launch (self , end_time , status = None ):
168
+ """
169
+ status can be (PASSED, FAILED, STOPPED, SKIPPED, RESETED, CANCELLED)
170
+ """
159
171
data = {
160
- "end_time " : end_time ,
172
+ "endTime " : end_time ,
161
173
"status" : status
162
174
}
163
- url = uri_join (self .base_url , "launch" , self .launch_id , action )
175
+ url = uri_join (self .base_url_v1 , "launch" , self .launch_id , "finish" )
164
176
r = self .session .put (url = url , json = data , verify = self .verify_ssl )
165
- self .stack .pop ()
166
- logger .debug ("%s_launch - Stack: %s" , action , self .stack )
177
+ logger .debug ("finish_launch - ID: %s" , self .launch_id )
167
178
return _get_msg (r )
168
179
169
- def finish_launch (self , end_time , status = None ):
170
- return self ._finalize_launch (end_time = end_time , action = "finish" ,
171
- status = status )
172
-
173
- def stop_launch (self , end_time , status = None ):
174
- return self ._finalize_launch (end_time = end_time , action = "stop" ,
175
- status = status )
176
-
177
180
def start_test_item (self , name , start_time , item_type , description = None ,
178
- tags = None , parameters = None ):
181
+ attributes = None , parameters = None , parent_item_id = None ):
179
182
"""
180
183
item_type can be (SUITE, STORY, TEST, SCENARIO, STEP, BEFORE_CLASS,
181
184
BEFORE_GROUPS, BEFORE_METHOD, BEFORE_SUITE, BEFORE_TEST, AFTER_CLASS,
182
185
AFTER_GROUPS, AFTER_METHOD, AFTER_SUITE, AFTER_TEST)
183
186
184
- parameters should be a dictionary with the following format:
187
+ attributes and parameters should be a dictionary
188
+ with the following format:
185
189
{
186
190
"<key1>": "<value1>",
187
191
"<key2>": "<value2>",
188
192
...
189
193
}
190
194
"""
195
+ if attributes is not None :
196
+ attributes = _dict_to_payload (attributes )
191
197
if parameters is not None :
192
- parameters = [{"key" : key , "value" : str (value )}
193
- for key , value in parameters .items ()]
198
+ parameters = _dict_to_payload (parameters )
194
199
195
200
data = {
196
201
"name" : name ,
197
202
"description" : description ,
198
- "tags " : tags ,
199
- "start_time " : start_time ,
200
- "launch_id " : self .launch_id ,
203
+ "attributes " : attributes ,
204
+ "startTime " : start_time ,
205
+ "launchUuid " : self .launch_id ,
201
206
"type" : item_type ,
202
207
"parameters" : parameters ,
203
208
}
204
- parent_item_id = self .stack [- 1 ]
205
209
if parent_item_id is not None :
206
- url = uri_join (self .base_url , "item" , parent_item_id )
210
+ url = uri_join (self .base_url_v2 , "item" , parent_item_id )
207
211
else :
208
- url = uri_join (self .base_url , "item" )
212
+ url = uri_join (self .base_url_v2 , "item" )
209
213
r = self .session .post (url = url , json = data , verify = self .verify_ssl )
210
214
211
215
item_id = _get_id (r )
212
- self .stack .append (item_id )
213
- logger .debug ("start_test_item - Stack: %s" , self .stack )
216
+ logger .debug ("start_test_item - ID: %s" , item_id )
214
217
return item_id
215
218
216
- def update_test_item (self , description = None , tags = None ):
217
- """Update test item.
218
-
219
- :param str description: test item description
220
- :param list tags: test item tags
221
- """
222
- data = {
223
- "description" : description ,
224
- "tags" : tags ,
225
- }
226
-
227
- item_id = self .stack [- 1 ]
228
- url = uri_join (self .base_url , "item" , item_id , "update" )
229
- r = self .session .put (url = url , json = data , verify = self .verify_ssl )
230
- logger .debug ("update_test_item - Stack: %s" , self .stack )
231
- return _get_msg (r )
232
-
233
- def finish_test_item (self , end_time , status , issue = None ):
219
+ def finish_test_item (self , item_id , end_time , status ,
220
+ issue = None , attributes = None ):
234
221
# check if skipped test should not be marked as "TO INVESTIGATE"
235
222
if issue is None and status == "SKIPPED" \
236
223
and not self .is_skipped_an_issue :
237
224
issue = {"issue_type" : "NOT_ISSUE" }
238
225
226
+ if attributes is not None :
227
+ attributes = _dict_to_payload (attributes )
228
+
239
229
data = {
240
- "end_time " : end_time ,
230
+ "endTime " : end_time ,
241
231
"status" : status ,
242
232
"issue" : issue ,
233
+ "launchUuid" : self .launch_id ,
234
+ "attributes" : attributes
243
235
}
244
- item_id = self .stack .pop ()
245
- url = uri_join (self .base_url , "item" , item_id )
236
+ url = uri_join (self .base_url_v2 , "item" , item_id )
246
237
r = self .session .put (url = url , json = data , verify = self .verify_ssl )
247
- logger .debug ("finish_test_item - Stack : %s" , self . stack )
238
+ logger .debug ("finish_test_item - ID : %s" , item_id )
248
239
return _get_msg (r )
249
240
250
241
def get_project_settings (self ):
251
- url = uri_join (self .base_url , "settings" )
242
+ url = uri_join (self .base_url_v1 , "settings" )
252
243
r = self .session .get (url = url , json = {}, verify = self .verify_ssl )
253
- logger .debug ("settings - Stack: %s" , self . stack )
244
+ logger .debug ("settings" )
254
245
return _get_json (r )
255
246
256
- def log (self , time , message , level = None , attachment = None ):
247
+ def log (self , time , message , level = None , attachment = None , item_id = None ):
257
248
data = {
258
- "item_id" : self . stack [ - 1 ] or self .launch_id ,
249
+ "launchUuid" : self .launch_id ,
259
250
"time" : time ,
260
251
"message" : message ,
261
252
"level" : level ,
262
253
}
254
+ if item_id :
255
+ data ["itemUuid" ] = item_id
263
256
if attachment :
264
257
data ["attachment" ] = attachment
265
- return self .log_batch ([data ])
258
+ return self .log_batch ([data ], item_id = item_id )
266
259
else :
267
- url = uri_join (self .base_url , "log" )
260
+ url = uri_join (self .base_url_v2 , "log" )
268
261
r = self .session .post (url = url , json = data , verify = self .verify_ssl )
269
- logger .debug ("log - Stack : %s" , self . stack )
262
+ logger .debug ("log - ID : %s" , item_id )
270
263
return _get_id (r )
271
264
272
- def log_batch (self , log_data ):
265
+ def log_batch (self , log_data , item_id = None ):
273
266
"""Logs batch of messages with attachment.
274
267
275
268
Args:
@@ -283,11 +276,13 @@ def log_batch(self, log_data):
283
276
284
277
"""
285
278
286
- url = uri_join (self .base_url , "log" )
279
+ url = uri_join (self .base_url_v2 , "log" )
287
280
288
281
attachments = []
289
282
for log_item in log_data :
290
- log_item ["item_id" ] = self .stack [- 1 ]
283
+ if item_id :
284
+ log_item ["itemUuid" ] = item_id
285
+ log_item ["launchUuid" ] = self .launch_id
291
286
attachment = log_item .get ("attachment" , None )
292
287
293
288
if "attachment" in log_item :
@@ -328,7 +323,7 @@ def log_batch(self, log_data):
328
323
raise
329
324
break
330
325
331
- logger .debug ("log_batch - Stack : %s" , self . stack )
326
+ logger .debug ("log_batch - ID : %s" , item_id )
332
327
logger .debug ("log_batch response: %s" , r .text )
333
328
334
329
return _get_data (r )
0 commit comments