22import traceback
33from time import time
44
5+ import pytest
56from six import with_metaclass
7+ from six .moves import queue
68
79from reportportal_client import ReportPortalServiceAsync
810
911
10- def async_error_handler (exc_info ):
11- exc , msg , tb = exc_info
12- traceback .print_exception (exc , msg , tb )
13-
14-
1512def timestamp ():
1613 return str (int (time () * 1000 ))
1714
@@ -32,9 +29,14 @@ class PyTestServiceClass(with_metaclass(Singleton, object)):
3229
3330 def __init__ (self ):
3431 self .RP = None
32+ self .ignore_errors = True
33+ self ._errors = queue .Queue ()
3534
36- def init_service (self , endpoint , project , uuid , log_batch_size ):
35+ def init_service (self , endpoint , project , uuid , log_batch_size ,
36+ ignore_errors ):
37+ self ._errors = queue .Queue ()
3738 if self .RP is None :
39+ self .ignore_errors = ignore_errors
3840 logging .debug (
3941 msg = "ReportPortal - Init service: "
4042 "endpoint={0}, project={1}, uuid={2}" .
@@ -43,18 +45,39 @@ def init_service(self, endpoint, project, uuid, log_batch_size):
4345 endpoint = endpoint ,
4446 project = project ,
4547 token = uuid ,
46- error_handler = async_error_handler ,
47- log_batch_size = log_batch_size )
48+ error_handler = self .async_error_handler ,
49+ log_batch_size = log_batch_size
50+ )
4851 else :
4952 logging .debug ("The pytest is already initialized" )
5053 return self .RP
5154
55+ def async_error_handler (self , exc_info ):
56+ self .terminate_service ()
57+ self .RP = None
58+ exc , msg , tb = exc_info
59+
60+ traceback .print_exception (exc , msg , tb )
61+ self ._errors .put_nowait (msg )
62+
63+ def _stop_if_neccessary (self ):
64+ if not self .ignore_errors :
65+ try :
66+ reason = self ._errors .get (False )
67+ pytest .exit (reason )
68+ except queue .Empty :
69+ pass
70+
5271 def terminate_service (self ):
5372 if self .RP is not None :
5473 self .RP .terminate ()
5574
5675 def start_launch (
5776 self , launch_name , mode = None , tags = None , description = None ):
77+ self ._stop_if_neccessary ()
78+ if self .RP is None :
79+ return
80+
5881 sl_pt = {
5982 "name" : launch_name ,
6083 "start_time" : timestamp (),
@@ -69,6 +92,10 @@ def start_launch(
6992 "response_body=%s" , req_data )
7093
7194 def start_pytest_item (self , test_item = None ):
95+ self ._stop_if_neccessary ()
96+ if self .RP is None :
97+ return
98+
7299 start_rq = {
73100 "name" : self ._get_full_name (test_item ),
74101 "description" : self ._get_description (test_item ),
@@ -104,6 +131,10 @@ def _get_tags(self, test_item):
104131 return []
105132
106133 def finish_pytest_item (self , status , issue = None ):
134+ self ._stop_if_neccessary ()
135+ if self .RP is None :
136+ return
137+
107138 fta_rq = {
108139 "end_time" : timestamp (),
109140 "status" : status ,
@@ -116,6 +147,10 @@ def finish_pytest_item(self, status, issue=None):
116147 self .RP .finish_test_item (** fta_rq )
117148
118149 def finish_launch (self , launch = None , status = "rp_launch" ):
150+ self ._stop_if_neccessary ()
151+ if self .RP is None :
152+ return
153+
119154 # To finish launch session str parameter is needed
120155 fl_rq = {
121156 "end_time" : timestamp (),
@@ -126,6 +161,10 @@ def finish_launch(self, launch=None, status="rp_launch"):
126161 self .RP .finish_launch (** fl_rq )
127162
128163 def post_log (self , message , loglevel = 'INFO' , attachment = None ):
164+ self ._stop_if_neccessary ()
165+ if self .RP is None :
166+ return
167+
129168 if loglevel not in self ._loglevels :
130169 logging .warning ('Incorrect loglevel = %s. Force set to INFO. '
131170 'Avaliable levels: %s.' , loglevel , self ._loglevels )
0 commit comments