2010-03-30 00:25:25 +04:00
# Python module for parsing and generating the Subunit protocol
# (Samba-specific)
# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__all__ = [ ' parse_results ' ]
2016-08-17 01:56:50 +03:00
import datetime
2010-03-30 00:25:25 +04:00
import re
2010-03-30 14:46:26 +04:00
import sys
2017-06-01 06:26:48 +03:00
import os
2014-12-11 05:30:49 +03:00
from samba import subunit
from samba . subunit . run import TestProtocolClient
import unittest
2021-02-02 15:44:01 +03:00
try :
from dateutil . parser import isoparse as iso_parse_date
except ImportError :
try :
from iso8601 import parse_date as iso_parse_date ;
except ImportError :
print ( ' Install either python-dateutil >= 2.7.1 or python-iso8601 ' )
2018-08-04 16:23:28 +03:00
2010-03-30 00:25:25 +04:00
2016-08-02 01:27:05 +03:00
VALID_RESULTS = set ( [ ' success ' , ' successful ' , ' failure ' , ' fail ' , ' skip ' ,
' knownfail ' , ' error ' , ' xfail ' , ' skip-testsuite ' ,
' testsuite-failure ' , ' testsuite-xfail ' ,
' testsuite-success ' , ' testsuite-error ' ,
' uxsuccess ' , ' testsuite-uxsuccess ' ] )
2010-03-30 00:25:25 +04:00
2018-07-30 09:20:39 +03:00
2014-12-11 05:30:49 +03:00
class TestsuiteEnabledTestResult ( unittest . TestResult ) :
2010-09-13 23:17:05 +04:00
def start_testsuite ( self , name ) :
raise NotImplementedError ( self . start_testsuite )
2010-03-30 00:25:25 +04:00
def parse_results ( msg_ops , statistics , fh ) :
2010-11-21 22:26:59 +03:00
exitcode = 0
2010-09-14 00:09:46 +04:00
open_tests = { }
2010-03-30 00:25:25 +04:00
2020-11-19 06:44:42 +03:00
for l in fh :
2010-04-11 03:39:06 +04:00
parts = l . split ( None , 1 )
if not len ( parts ) == 2 or not l . startswith ( parts [ 0 ] ) :
2010-08-26 04:25:44 +04:00
msg_ops . output_msg ( l )
2010-04-11 03:39:06 +04:00
continue
command = parts [ 0 ] . rstrip ( " : " )
arg = parts [ 1 ]
if command in ( " test " , " testing " ) :
msg_ops . control_msg ( l )
2010-09-14 00:09:46 +04:00
name = arg . rstrip ( )
test = subunit . RemotedTestCase ( name )
if name in open_tests :
2010-09-14 05:47:04 +04:00
msg_ops . addError ( open_tests . pop ( name ) , subunit . RemoteError ( u " Test already running " ) )
2010-09-14 00:09:46 +04:00
msg_ops . startTest ( test )
open_tests [ name ] = test
2010-04-11 03:39:06 +04:00
elif command == " time " :
2010-03-30 00:25:25 +04:00
msg_ops . control_msg ( l )
2010-09-13 23:31:08 +04:00
try :
2021-02-02 15:44:01 +03:00
dt = iso_parse_date ( arg . rstrip ( " \n " ) )
2018-02-14 00:35:53 +03:00
except TypeError as e :
2018-03-09 17:03:29 +03:00
print ( " Unable to parse time line: %s " % arg . rstrip ( " \n " ) )
2010-09-13 23:31:08 +04:00
else :
msg_ops . time ( dt )
2010-04-11 03:39:06 +04:00
elif command in VALID_RESULTS :
2010-03-30 00:25:25 +04:00
msg_ops . control_msg ( l )
2010-04-11 03:39:06 +04:00
result = command
2023-03-15 01:31:43 +03:00
grp = re . match ( r " (.*?)( \ [)?([ \ t]*)( multipart)? \ n " , arg )
2010-04-11 03:39:06 +04:00
( testname , hasreason ) = ( grp . group ( 1 ) , grp . group ( 2 ) )
2010-03-30 00:25:25 +04:00
if hasreason :
reason = " "
# reason may be specified in next lines
terminated = False
2020-11-19 06:44:42 +03:00
for l in fh :
2010-03-30 00:25:25 +04:00
msg_ops . control_msg ( l )
2020-11-05 16:19:11 +03:00
if l == " ] \n " :
2010-03-30 00:25:25 +04:00
terminated = True
break
else :
reason + = l
2010-08-26 05:50:08 +04:00
2020-07-04 05:05:16 +03:00
if isinstance ( reason , bytes ) :
2018-08-04 16:23:28 +03:00
remote_error = subunit . RemoteError ( reason . decode ( " utf-8 " ) )
else :
remote_error = subunit . RemoteError ( reason )
2010-09-14 05:47:04 +04:00
2010-03-30 00:25:25 +04:00
if not terminated :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2020-11-06 14:35:04 +03:00
msg_ops . addError ( subunit . RemotedTestCase ( testname ) ,
subunit . RemoteError ( u " result ( %s ) reason ( %s ) interrupted " % ( result , reason ) ) )
2010-03-30 00:25:25 +04:00
return 1
2010-03-30 02:30:52 +04:00
else :
reason = None
2010-09-14 05:47:04 +04:00
remote_error = subunit . RemoteError ( u " No reason specified " )
2010-03-30 00:25:25 +04:00
if result in ( " success " , " successful " ) :
2010-04-11 00:35:57 +04:00
try :
2010-09-14 00:09:46 +04:00
test = open_tests . pop ( testname )
except KeyError :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-09-14 05:47:04 +04:00
msg_ops . addError ( subunit . RemotedTestCase ( testname ) , subunit . RemoteError ( u " Test was never started " ) )
2010-04-11 00:35:57 +04:00
else :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_EXPECTED_OK ' ] + = 1
2010-09-14 05:47:04 +04:00
msg_ops . addSuccess ( test )
2010-03-30 00:25:25 +04:00
elif result in ( " xfail " , " knownfail " ) :
2010-04-11 00:35:57 +04:00
try :
2010-09-14 00:09:46 +04:00
test = open_tests . pop ( testname )
except KeyError :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-09-14 05:47:04 +04:00
msg_ops . addError ( subunit . RemotedTestCase ( testname ) , subunit . RemoteError ( u " Test was never started " ) )
2010-04-11 00:35:57 +04:00
else :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_EXPECTED_FAIL ' ] + = 1
2010-09-14 05:47:04 +04:00
msg_ops . addExpectedFailure ( test , remote_error )
2011-12-04 04:55:23 +04:00
elif result in ( " uxsuccess " , ) :
try :
test = open_tests . pop ( testname )
except KeyError :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2011-12-04 04:55:23 +04:00
exitcode = 1
msg_ops . addError ( subunit . RemotedTestCase ( testname ) , subunit . RemoteError ( u " Test was never started " ) )
else :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_UNEXPECTED_OK ' ] + = 1
2015-01-30 04:07:17 +03:00
msg_ops . addUnexpectedSuccess ( test )
2011-12-04 04:55:23 +04:00
exitcode = 1
2010-03-30 00:25:25 +04:00
elif result in ( " failure " , " fail " ) :
2010-04-11 00:35:57 +04:00
try :
2010-09-14 00:09:46 +04:00
test = open_tests . pop ( testname )
except KeyError :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-09-14 05:47:04 +04:00
msg_ops . addError ( subunit . RemotedTestCase ( testname ) , subunit . RemoteError ( u " Test was never started " ) )
2010-04-11 00:35:57 +04:00
else :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_UNEXPECTED_FAIL ' ] + = 1
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-09-14 05:47:04 +04:00
msg_ops . addFailure ( test , remote_error )
2010-03-30 00:25:25 +04:00
elif result == " skip " :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_SKIP ' ] + = 1
2010-03-30 00:25:25 +04:00
# Allow tests to be skipped without prior announcement of test
2010-09-14 00:09:46 +04:00
try :
test = open_tests . pop ( testname )
except KeyError :
test = subunit . RemotedTestCase ( testname )
msg_ops . addSkip ( test , reason )
2010-03-30 00:25:25 +04:00
elif result == " error " :
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-04-11 00:35:57 +04:00
try :
2010-09-14 00:09:46 +04:00
test = open_tests . pop ( testname )
except KeyError :
test = subunit . RemotedTestCase ( testname )
2010-09-14 05:47:04 +04:00
msg_ops . addError ( test , remote_error )
2010-03-30 00:25:25 +04:00
elif result == " skip-testsuite " :
msg_ops . skip_testsuite ( testname )
elif result == " testsuite-success " :
msg_ops . end_testsuite ( testname , " success " , reason )
elif result == " testsuite-failure " :
msg_ops . end_testsuite ( testname , " failure " , reason )
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-03-30 00:25:25 +04:00
elif result == " testsuite-xfail " :
msg_ops . end_testsuite ( testname , " xfail " , reason )
2014-03-12 18:12:42 +04:00
elif result == " testsuite-uxsuccess " :
msg_ops . end_testsuite ( testname , " uxsuccess " , reason )
exitcode = 1
2010-03-30 00:25:25 +04:00
elif result == " testsuite-error " :
msg_ops . end_testsuite ( testname , " error " , reason )
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-08-26 04:25:44 +04:00
else :
raise AssertionError ( " Recognized but unhandled result %r " %
2018-07-30 09:16:12 +03:00
result )
2010-04-11 03:39:06 +04:00
elif command == " testsuite " :
msg_ops . start_testsuite ( arg . strip ( ) )
elif command == " progress " :
arg = arg . strip ( )
2010-03-30 16:36:25 +04:00
if arg == " pop " :
msg_ops . progress ( None , subunit . PROGRESS_POP )
elif arg == " push " :
msg_ops . progress ( None , subunit . PROGRESS_PUSH )
elif arg [ 0 ] in ' +- ' :
msg_ops . progress ( int ( arg ) , subunit . PROGRESS_CUR )
else :
msg_ops . progress ( int ( arg ) , subunit . PROGRESS_SET )
2010-03-30 00:25:25 +04:00
else :
msg_ops . output_msg ( l )
while open_tests :
2010-09-14 00:13:15 +04:00
test = subunit . RemotedTestCase ( open_tests . popitem ( ) [ 1 ] )
2010-09-14 05:47:04 +04:00
msg_ops . addError ( test , subunit . RemoteError ( u " was started but never finished! " ) )
2018-07-30 09:18:03 +03:00
statistics [ ' TESTS_ERROR ' ] + = 1
2010-11-21 22:26:59 +03:00
exitcode = 1
2010-03-30 00:25:25 +04:00
2010-11-21 22:26:59 +03:00
return exitcode
2010-03-30 00:25:25 +04:00
2018-07-30 09:19:05 +03:00
class SubunitOps ( TestProtocolClient , TestsuiteEnabledTestResult ) :
2014-12-11 05:30:49 +03:00
def progress ( self , count , whence ) :
2014-12-14 23:10:20 +03:00
if whence == subunit . PROGRESS_POP :
self . _stream . write ( " progress: pop \n " )
elif whence == subunit . PROGRESS_PUSH :
self . _stream . write ( " progress: push \n " )
elif whence == subunit . PROGRESS_SET :
self . _stream . write ( " progress: %d \n " % count )
elif whence == subunit . PROGRESS_CUR :
raise NotImplementedError
2010-03-30 00:25:25 +04:00
2010-03-30 02:59:04 +04:00
# The following are Samba extensions:
def start_testsuite ( self , name ) :
2010-09-13 23:17:05 +04:00
self . _stream . write ( " testsuite: %s \n " % name )
2010-03-30 00:25:25 +04:00
2010-03-30 02:59:04 +04:00
def skip_testsuite ( self , name , reason = None ) :
if reason :
2010-09-13 23:17:05 +04:00
self . _stream . write ( " skip-testsuite: %s [ \n %s \n ] \n " % ( name , reason ) )
2010-03-30 02:59:04 +04:00
else :
2010-09-13 23:17:05 +04:00
self . _stream . write ( " skip-testsuite: %s \n " % name )
2010-03-30 00:25:25 +04:00
2010-03-30 02:59:04 +04:00
def end_testsuite ( self , name , result , reason = None ) :
if reason :
2010-09-13 23:17:05 +04:00
self . _stream . write ( " testsuite- %s : %s [ \n %s \n ] \n " % ( result , name , reason ) )
2010-03-30 02:59:04 +04:00
else :
2010-09-13 23:17:05 +04:00
self . _stream . write ( " testsuite- %s : %s \n " % ( result , name ) )
2010-03-30 00:25:25 +04:00
2010-09-15 22:05:51 +04:00
def output_msg ( self , msg ) :
self . _stream . write ( msg )
2010-03-30 14:46:26 +04:00
2017-06-01 06:26:48 +03:00
def read_test_regexes ( * names ) :
2022-12-06 07:16:00 +03:00
ret = [ ]
2017-06-01 06:26:48 +03:00
files = [ ]
for name in names :
# if we are given a directory, we read all the files it contains
# (except the ones that end with "~").
if os . path . isdir ( name ) :
files . extend ( [ os . path . join ( name , x )
for x in os . listdir ( name )
if x [ - 1 ] != ' ~ ' ] )
else :
files . append ( name )
for filename in files :
2020-11-19 06:44:42 +03:00
with open ( filename , ' r ' ) as f :
2017-06-01 06:26:48 +03:00
for l in f :
l = l . strip ( )
if l == " " or l [ 0 ] == " # " :
continue
if " # " in l :
( regex , reason ) = l . split ( " # " , 1 )
2022-12-06 07:16:00 +03:00
ret . append ( re . compile ( regex . strip ( ) ) )
2017-06-01 06:26:48 +03:00
else :
2022-12-06 07:16:00 +03:00
ret . append ( re . compile ( l ) )
2020-11-19 06:44:42 +03:00
2010-04-06 05:55:10 +04:00
return ret
2010-03-30 14:46:26 +04:00
def find_in_list ( regexes , fullname ) :
2022-12-06 07:16:00 +03:00
for regex in regexes :
if regex . match ( fullname ) :
return True
return False
2010-03-30 14:46:26 +04:00
2010-09-28 09:10:43 +04:00
class ImmediateFail ( Exception ) :
""" Raised to abort immediately. """
def __init__ ( self ) :
super ( ImmediateFail , self ) . __init__ ( " test failed and fail_immediately set " )
2014-12-11 05:30:49 +03:00
class FilterOps ( unittest . TestResult ) :
2010-03-30 14:46:26 +04:00
def control_msg ( self , msg ) :
2018-07-30 09:19:33 +03:00
pass # We regenerate control messages, so ignore this
2010-03-30 14:46:26 +04:00
2010-09-13 23:31:08 +04:00
def time ( self , time ) :
self . _ops . time ( time )
2010-03-30 14:46:26 +04:00
2010-03-30 16:36:25 +04:00
def progress ( self , delta , whence ) :
self . _ops . progress ( delta , whence )
2010-03-30 14:46:26 +04:00
def output_msg ( self , msg ) :
if self . output is None :
sys . stdout . write ( msg )
else :
2018-07-30 09:18:03 +03:00
self . output + = msg
2010-03-30 14:46:26 +04:00
2010-09-13 23:42:32 +04:00
def startTest ( self , test ) :
2010-11-03 18:30:40 +03:00
self . seen_output = True
2010-09-14 00:09:46 +04:00
test = self . _add_prefix ( test )
2010-03-30 14:46:26 +04:00
if self . strip_ok_output :
2018-07-30 09:13:57 +03:00
self . output = " "
2010-03-30 14:46:26 +04:00
2010-09-13 23:42:32 +04:00
self . _ops . startTest ( test )
2010-03-30 14:46:26 +04:00
2010-09-14 00:09:46 +04:00
def _add_prefix ( self , test ) :
2016-08-02 02:00:27 +03:00
return subunit . RemotedTestCase ( self . prefix + test . id ( ) + self . suffix )
2010-09-14 00:09:46 +04:00
2014-12-11 05:30:49 +03:00
def addError ( self , test , err = None ) :
2010-09-14 00:09:46 +04:00
test = self . _add_prefix ( test )
2018-07-30 09:18:03 +03:00
self . error_added + = 1
self . total_error + = 1
2014-12-11 05:30:49 +03:00
self . _ops . addError ( test , err )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2010-09-14 00:29:38 +04:00
self . output = None
2010-09-27 05:56:50 +04:00
if self . fail_immediately :
2010-09-28 09:10:43 +04:00
raise ImmediateFail ( )
2010-09-13 23:55:22 +04:00
2014-12-11 05:30:49 +03:00
def addSkip ( self , test , reason = None ) :
2010-11-03 18:30:40 +03:00
self . seen_output = True
2010-09-14 00:09:46 +04:00
test = self . _add_prefix ( test )
2014-12-11 05:30:49 +03:00
self . _ops . addSkip ( test , reason )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2010-09-14 00:29:38 +04:00
self . output = None
2010-03-30 14:46:26 +04:00
2014-12-11 05:30:49 +03:00
def addExpectedFailure ( self , test , err = None ) :
2010-09-14 00:09:46 +04:00
test = self . _add_prefix ( test )
2014-12-11 05:30:49 +03:00
self . _ops . addExpectedFailure ( test , err )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2010-09-14 00:29:38 +04:00
self . output = None
2010-09-14 00:09:46 +04:00
2015-01-30 04:07:17 +03:00
def addUnexpectedSuccess ( self , test ) :
2011-12-04 04:55:23 +04:00
test = self . _add_prefix ( test )
2018-07-30 09:18:03 +03:00
self . uxsuccess_added + = 1
self . total_uxsuccess + = 1
2015-01-30 04:07:17 +03:00
self . _ops . addUnexpectedSuccess ( test )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2014-03-12 18:12:42 +04:00
if self . output :
self . _ops . output_msg ( self . output )
2011-12-04 04:55:23 +04:00
self . output = None
2014-03-12 18:12:42 +04:00
if self . fail_immediately :
raise ImmediateFail ( )
2011-12-04 04:55:23 +04:00
2014-12-11 05:30:49 +03:00
def addFailure ( self , test , err = None ) :
2010-09-14 00:09:46 +04:00
test = self . _add_prefix ( test )
2022-12-06 07:16:00 +03:00
xfail = find_in_list ( self . expected_failures , test . id ( ) )
if not xfail :
xfail = find_in_list ( self . flapping , test . id ( ) )
if xfail :
2018-07-30 09:18:03 +03:00
self . xfail_added + = 1
self . total_xfail + = 1
2014-12-11 05:30:49 +03:00
self . _ops . addExpectedFailure ( test , err )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2010-09-14 00:29:38 +04:00
else :
2018-07-30 09:18:03 +03:00
self . fail_added + = 1
self . total_fail + = 1
2014-12-11 05:30:49 +03:00
self . _ops . addFailure ( test , err )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2010-09-14 00:29:38 +04:00
if self . output :
self . _ops . output_msg ( self . output )
2010-09-28 09:10:43 +04:00
if self . fail_immediately :
raise ImmediateFail ( )
2010-03-30 14:46:26 +04:00
self . output = None
2014-12-11 05:30:49 +03:00
def addSuccess ( self , test ) :
2010-09-14 00:29:38 +04:00
test = self . _add_prefix ( test )
2022-12-06 07:16:00 +03:00
xfail = find_in_list ( self . expected_failures , test . id ( ) )
if xfail :
2011-12-04 03:23:02 +04:00
self . uxsuccess_added + = 1
self . total_uxsuccess + = 1
2015-02-02 01:20:42 +03:00
self . _ops . addUnexpectedSuccess ( test )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2011-12-04 03:23:02 +04:00
if self . output :
self . _ops . output_msg ( self . output )
if self . fail_immediately :
raise ImmediateFail ( )
else :
2014-12-11 05:30:49 +03:00
self . _ops . addSuccess ( test )
python:subunit: Avoid misleading "Test was never started" error message
subunithelper.py keeps track of tests that have been started, and
displays an error message if a test reports an outcome without having
previously been started. However, it makes the assumption that a test
has finished once it has reported a single outcome. This means that a
misleading error message will be displayed if it receives multiple
outcomes from the same test (which can happen if a test using the Python
unittest framework does not complete successfully, and the cleanup
subsequently fails), and any actual errors from the cleanup remain
undisplayed.
This commit ensures that only a single outcome is reported for each
test, and only after the test has finished. Outcomes are buffered up
until the stopTest() function is called, when a single outcome is
determined and all errors received for that test are output.
FilterOps still needs to output test outcomes immediately rather than
buffering them, otherwise they are never picked up and passed on to the
remote test case by subunithelper.parse_results(). This would result in
an error as the test would be considered to have never finished.
Example subunitrun output before the change:
time: 2021-04-28 01:28:49.862123Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:28:49.862215Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862407Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:28:49.862467Z
time: 2021-04-28 01:28:49.862510Z
and after:
time: 2021-04-28 01:29:19.949347Z
test: samba.tests.example.ExampleTests.test
time: 2021-04-28 01:29:19.949440Z
time: 2021-04-28 01:29:19.949590Z
time: 2021-04-28 01:29:19.949640Z
failure: samba.tests.example.ExampleTests.test [
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 28, in test
self.fail()
AssertionError: None
Traceback (most recent call last):
File "bin/python/samba/tests/example.py", line 31, in tearDown
self.fail()
AssertionError: None
]
time: 2021-04-28 01:29:19.949702Z
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-04-28 04:55:02 +03:00
self . _ops . writeOutcome ( test )
2010-09-14 00:29:38 +04:00
self . output = None
2010-03-30 14:46:26 +04:00
def skip_testsuite ( self , name , reason = None ) :
self . _ops . skip_testsuite ( name , reason )
def start_testsuite ( self , name ) :
self . _ops . start_testsuite ( name )
self . error_added = 0
self . fail_added = 0
self . xfail_added = 0
2011-12-04 03:23:02 +04:00
self . uxsuccess_added = 0
2010-03-30 14:46:26 +04:00
def end_testsuite ( self , name , result , reason = None ) :
xfail = False
if self . xfail_added > 0 :
xfail = True
2014-03-12 18:12:42 +04:00
if self . fail_added > 0 or self . error_added > 0 or self . uxsuccess_added > 0 :
2010-03-30 14:46:26 +04:00
xfail = False
if xfail and result in ( " fail " , " failure " ) :
result = " xfail "
2014-03-12 18:12:42 +04:00
if self . uxsuccess_added > 0 and result != " uxsuccess " :
result = " uxsuccess "
if reason is None :
reason = " Subunit/Filter Reason "
reason + = " \n uxsuccess[ %d ] " % self . uxsuccess_added
2010-03-30 14:46:26 +04:00
if self . fail_added > 0 and result != " failure " :
result = " failure "
if reason is None :
reason = " Subunit/Filter Reason "
reason + = " \n failures[ %d ] " % self . fail_added
if self . error_added > 0 and result != " error " :
result = " error "
if reason is None :
reason = " Subunit/Filter Reason "
reason + = " \n errors[ %d ] " % self . error_added
self . _ops . end_testsuite ( name , result , reason )
2014-03-12 18:12:42 +04:00
if result not in ( " success " , " xfail " ) :
if self . output :
self . _ops . output_msg ( self . output )
if self . fail_immediately :
raise ImmediateFail ( )
self . output = None
2010-03-30 14:46:26 +04:00
2012-04-27 06:50:36 +04:00
def __init__ ( self , out , prefix = None , suffix = None , expected_failures = None ,
2011-12-04 03:23:02 +04:00
strip_ok_output = False , fail_immediately = False ,
flapping = None ) :
2010-09-13 23:17:05 +04:00
self . _ops = out
2010-11-03 18:30:40 +03:00
self . seen_output = False
2010-03-30 14:46:26 +04:00
self . output = None
self . prefix = prefix
2012-04-27 06:50:36 +04:00
self . suffix = suffix
2010-10-02 20:41:14 +04:00
if expected_failures is not None :
self . expected_failures = expected_failures
else :
2022-12-06 07:16:00 +03:00
self . expected_failures = [ ]
2011-12-04 03:23:02 +04:00
if flapping is not None :
self . flapping = flapping
else :
2022-12-06 07:16:00 +03:00
self . flapping = [ ]
2010-03-30 14:46:26 +04:00
self . strip_ok_output = strip_ok_output
self . xfail_added = 0
2010-09-22 22:30:34 +04:00
self . fail_added = 0
2011-12-04 03:23:02 +04:00
self . uxsuccess_added = 0
2010-03-30 14:46:26 +04:00
self . total_xfail = 0
self . total_error = 0
self . total_fail = 0
2011-12-04 03:23:02 +04:00
self . total_uxsuccess = 0
2010-09-23 00:05:55 +04:00
self . error_added = 0
2010-09-27 05:56:50 +04:00
self . fail_immediately = fail_immediately
2010-10-02 19:02:02 +04:00
2016-08-17 01:56:50 +03:00
class PerfFilterOps ( unittest . TestResult ) :
def progress ( self , delta , whence ) :
pass
def output_msg ( self , msg ) :
pass
def control_msg ( self , msg ) :
pass
def skip_testsuite ( self , name , reason = None ) :
self . _ops . skip_testsuite ( name , reason )
def start_testsuite ( self , name ) :
self . suite_has_time = False
def end_testsuite ( self , name , result , reason = None ) :
pass
def _add_prefix ( self , test ) :
return subunit . RemotedTestCase ( self . prefix + test . id ( ) + self . suffix )
def time ( self , time ) :
self . latest_time = time
#self._ops.output_msg("found time %s\n" % time)
self . suite_has_time = True
def get_time ( self ) :
if self . suite_has_time :
return self . latest_time
return datetime . datetime . utcnow ( )
def startTest ( self , test ) :
self . seen_output = True
test = self . _add_prefix ( test )
self . starts [ test . id ( ) ] = self . get_time ( )
def addSuccess ( self , test ) :
test = self . _add_prefix ( test )
tid = test . id ( )
if tid not in self . starts :
self . _ops . addError ( test , " %s succeeded without ever starting! " % tid )
delta = self . get_time ( ) - self . starts [ tid ]
self . _ops . output_msg ( " elapsed-time: %s : %f \n " % ( tid , delta . total_seconds ( ) ) )
def addFailure ( self , test , err = ' ' ) :
tid = test . id ( )
delta = self . get_time ( ) - self . starts [ tid ]
self . _ops . output_msg ( " failure: %s failed after %f seconds ( %s ) \n " %
( tid , delta . total_seconds ( ) , err ) )
def addError ( self , test , err = ' ' ) :
tid = test . id ( )
delta = self . get_time ( ) - self . starts [ tid ]
self . _ops . output_msg ( " error: %s failed after %f seconds ( %s ) \n " %
( tid , delta . total_seconds ( ) , err ) )
def __init__ ( self , out , prefix = ' ' , suffix = ' ' ) :
self . _ops = out
self . prefix = prefix or ' '
self . suffix = suffix or ' '
self . starts = { }
self . seen_output = False
self . suite_has_time = False
2010-10-02 19:02:02 +04:00
class PlainFormatter ( TestsuiteEnabledTestResult ) :
2010-10-02 20:41:14 +04:00
def __init__ ( self , verbose , immediate , statistics ,
2018-07-30 09:16:12 +03:00
totaltests = None ) :
2010-10-02 19:02:02 +04:00
super ( PlainFormatter , self ) . __init__ ( )
self . verbose = verbose
self . immediate = immediate
self . statistics = statistics
self . start_time = None
self . test_output = { }
self . suitesfailed = [ ]
self . suites_ok = 0
self . skips = { }
self . index = 0
self . name = None
self . _progress_level = 0
self . totalsuites = totaltests
self . last_time = None
2010-10-03 00:31:31 +04:00
@staticmethod
2010-10-02 19:02:02 +04:00
def _format_time ( delta ) :
minutes , seconds = divmod ( delta . seconds , 60 )
hours , minutes = divmod ( minutes , 60 )
ret = " "
if hours :
ret + = " %d h " % hours
if minutes :
ret + = " %d m " % minutes
ret + = " %d s " % seconds
return ret
def progress ( self , offset , whence ) :
if whence == subunit . PROGRESS_POP :
self . _progress_level - = 1
elif whence == subunit . PROGRESS_PUSH :
self . _progress_level + = 1
elif whence == subunit . PROGRESS_SET :
if self . _progress_level == 0 :
self . totalsuites = offset
elif whence == subunit . PROGRESS_CUR :
raise NotImplementedError
def time ( self , dt ) :
if self . start_time is None :
self . start_time = dt
self . last_time = dt
def start_testsuite ( self , name ) :
self . index + = 1
self . name = name
if not self . verbose :
self . test_output [ name ] = " "
2014-11-01 22:51:31 +03:00
total_tests = ( self . statistics [ ' TESTS_EXPECTED_OK ' ] +
self . statistics [ ' TESTS_EXPECTED_FAIL ' ] +
self . statistics [ ' TESTS_ERROR ' ] +
self . statistics [ ' TESTS_UNEXPECTED_FAIL ' ] +
self . statistics [ ' TESTS_UNEXPECTED_OK ' ] )
out = " [ %d ( %d ) " % ( self . index , total_tests )
2010-10-02 19:02:02 +04:00
if self . totalsuites is not None :
out + = " / %d " % self . totalsuites
if self . start_time is not None :
2014-10-17 13:17:53 +04:00
out + = " at " + self . _format_time ( self . last_time - self . start_time )
2010-10-02 19:02:02 +04:00
if self . suitesfailed :
out + = " , %d errors " % ( len ( self . suitesfailed ) , )
out + = " ] %s " % name
if self . immediate :
sys . stdout . write ( out + " \n " )
else :
sys . stdout . write ( out + " : " )
def output_msg ( self , output ) :
if self . verbose :
sys . stdout . write ( output )
elif self . name is not None :
self . test_output [ self . name ] + = output
else :
sys . stdout . write ( output )
def control_msg ( self , output ) :
pass
def end_testsuite ( self , name , result , reason ) :
out = " "
unexpected = False
2018-07-30 09:22:34 +03:00
if name not in self . test_output :
2018-03-09 17:03:29 +03:00
print ( " no output for name[ %s ] " % name )
2010-10-02 19:02:02 +04:00
if result in ( " success " , " xfail " ) :
2018-07-30 09:18:03 +03:00
self . suites_ok + = 1
2010-10-02 19:02:02 +04:00
else :
self . output_msg ( " ERROR: Testsuite[ %s ] \n " % name )
if reason is not None :
self . output_msg ( " REASON: %s \n " % ( reason , ) )
self . suitesfailed . append ( name )
if self . immediate and not self . verbose and name in self . test_output :
out + = self . test_output [ name ]
unexpected = True
if not self . immediate :
if not unexpected :
out + = " ok \n "
else :
out + = " " + result . upper ( ) + " \n "
sys . stdout . write ( out )
def startTest ( self , test ) :
pass
def addSuccess ( self , test ) :
self . end_test ( test . id ( ) , " success " , False )
2014-12-11 05:30:49 +03:00
def addError ( self , test , err = None ) :
self . end_test ( test . id ( ) , " error " , True , err )
2010-10-02 19:02:02 +04:00
2014-12-11 05:30:49 +03:00
def addFailure ( self , test , err = None ) :
self . end_test ( test . id ( ) , " failure " , True , err )
2010-10-02 19:02:02 +04:00
2014-12-11 05:30:49 +03:00
def addSkip ( self , test , reason = None ) :
self . end_test ( test . id ( ) , " skip " , False , reason )
2010-10-02 19:02:02 +04:00
2014-12-11 05:30:49 +03:00
def addExpectedFailure ( self , test , err = None ) :
self . end_test ( test . id ( ) , " xfail " , False , err )
2010-10-02 19:02:02 +04:00
2014-12-11 05:30:49 +03:00
def addUnexpectedSuccess ( self , test ) :
self . end_test ( test . id ( ) , " uxsuccess " , True )
2011-12-04 04:55:23 +04:00
2014-12-11 05:30:49 +03:00
def end_test ( self , testname , result , unexpected , err = None ) :
2010-10-02 19:02:02 +04:00
if not unexpected :
self . test_output [ self . name ] = " "
if not self . immediate :
sys . stdout . write ( {
' failure ' : ' f ' ,
' xfail ' : ' X ' ,
' skip ' : ' s ' ,
' success ' : ' . ' } . get ( result , " ?( %s ) " % result ) )
return
2018-07-30 09:22:34 +03:00
if self . name not in self . test_output :
2010-10-02 19:02:02 +04:00
self . test_output [ self . name ] = " "
self . test_output [ self . name ] + = " UNEXPECTED( %s ): %s \n " % ( result , testname )
2014-12-11 05:30:49 +03:00
if err is not None :
2014-12-14 00:37:51 +03:00
self . test_output [ self . name ] + = " REASON: %s \n " % str ( err [ 1 ] ) . strip ( )
2010-10-02 19:02:02 +04:00
if self . immediate and not self . verbose :
2011-12-04 04:55:23 +04:00
sys . stdout . write ( self . test_output [ self . name ] )
2010-10-02 19:02:02 +04:00
self . test_output [ self . name ] = " "
if not self . immediate :
sys . stdout . write ( {
2018-07-30 09:14:13 +03:00
' error ' : ' E ' ,
2010-10-02 19:02:02 +04:00
' failure ' : ' F ' ,
2011-12-04 04:55:23 +04:00
' uxsuccess ' : ' U ' ,
2010-10-02 19:02:02 +04:00
' success ' : ' S ' } . get ( result , " ? " ) )
2010-10-02 20:41:14 +04:00
def write_summary ( self , path ) :
f = open ( path , ' w+ ' )
2010-10-02 19:02:02 +04:00
if self . suitesfailed :
f . write ( " = Failed tests = \n " )
for suite in self . suitesfailed :
f . write ( " == %s == \n " % suite )
if suite in self . test_output :
2018-07-30 09:18:25 +03:00
f . write ( self . test_output [ suite ] + " \n \n " )
2010-10-02 19:02:02 +04:00
f . write ( " \n " )
if not self . immediate and not self . verbose :
for suite in self . suitesfailed :
2018-03-09 17:03:29 +03:00
print ( " = " * 78 )
print ( " FAIL: %s " % suite )
2010-10-02 19:02:02 +04:00
if suite in self . test_output :
2018-03-09 17:03:29 +03:00
print ( self . test_output [ suite ] )
print ( " " )
2010-10-02 19:02:02 +04:00
f . write ( " = Skipped tests = \n " )
for reason in self . skips . keys ( ) :
f . write ( reason + " \n " )
for name in self . skips [ reason ] :
f . write ( " \t %s \n " % name )
f . write ( " \n " )
f . close ( )
if ( not self . suitesfailed and
not self . statistics [ ' TESTS_UNEXPECTED_FAIL ' ] and
2011-12-04 04:55:23 +04:00
not self . statistics [ ' TESTS_UNEXPECTED_OK ' ] and
2010-10-02 19:02:02 +04:00
not self . statistics [ ' TESTS_ERROR ' ] ) :
ok = ( self . statistics [ ' TESTS_EXPECTED_OK ' ] +
self . statistics [ ' TESTS_EXPECTED_FAIL ' ] )
2018-03-09 17:03:29 +03:00
print ( " \n ALL OK ( %d tests in %d testsuites) " % ( ok , self . suites_ok ) )
2010-10-02 19:02:02 +04:00
else :
2018-03-09 17:03:29 +03:00
print ( " \n FAILED ( %d failures, %d errors and %d unexpected successes in %d testsuites) " % (
2010-10-02 19:02:02 +04:00
self . statistics [ ' TESTS_UNEXPECTED_FAIL ' ] ,
self . statistics [ ' TESTS_ERROR ' ] ,
2011-12-04 04:55:23 +04:00
self . statistics [ ' TESTS_UNEXPECTED_OK ' ] ,
2018-03-09 17:03:29 +03:00
len ( self . suitesfailed ) ) )
2010-10-02 19:02:02 +04:00
def skip_testsuite ( self , name , reason = " UNKNOWN " ) :
self . skips . setdefault ( reason , [ ] ) . append ( name )
if self . totalsuites :
2018-07-30 09:18:03 +03:00
self . totalsuites - = 1