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
2014-12-14 23:27:03 +03:00
from samba . subunit import iso8601
2014-12-11 05:30:49 +03:00
import unittest
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
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
while fh :
l = fh . readline ( )
2010-03-30 02:30:52 +04:00
if l == " " :
break
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 :
2014-12-11 05:30:49 +03:00
dt = iso8601 . parse_date ( arg . rstrip ( " \n " ) )
2010-09-13 23:31:08 +04:00
except TypeError , e :
print " Unable to parse time line: %s " % arg . rstrip ( " \n " )
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
grp = re . match ( " (.*?)( \ [)?([ \t ]*)( multipart)? \n " , arg )
( 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
while fh :
l = fh . readline ( )
2010-03-30 02:30:52 +04:00
if l == " " :
break
2010-03-30 00:25:25 +04:00
msg_ops . control_msg ( l )
if l == " ] \n " :
terminated = True
break
else :
reason + = l
2010-08-26 05:50:08 +04:00
2010-09-14 05:47:04 +04:00
remote_error = subunit . RemoteError ( reason . decode ( " utf-8 " ) )
2010-03-30 00:25:25 +04:00
if not terminated :
statistics [ ' TESTS_ERROR ' ] + = 1
2010-09-14 05:47:04 +04:00
msg_ops . addError ( subunit . RemotedTestCase ( testname ) , subunit . RemoteError ( u " reason ( %s ) interrupted " % result ) )
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 :
2010-04-11 00:35:57 +04: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 :
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 :
2010-04-11 00:35:57 +04: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 :
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 :
statistics [ ' TESTS_ERROR ' ] + = 1
exitcode = 1
msg_ops . addError ( subunit . RemotedTestCase ( testname ) , subunit . RemoteError ( u " Test was never started " ) )
else :
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 :
2010-04-11 00:35:57 +04: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 :
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 " :
statistics [ ' TESTS_SKIP ' ] + = 1
# 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 " :
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 " %
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! " ) )
2010-03-30 00:25:25 +04: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
2014-12-11 05:30:49 +03:00
class SubunitOps ( TestProtocolClient , TestsuiteEnabledTestResult ) :
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 ) :
2010-04-06 05:55:10 +04: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 :
f = open ( filename , ' r ' )
try :
for l in f :
l = l . strip ( )
if l == " " or l [ 0 ] == " # " :
continue
if " # " in l :
( regex , reason ) = l . split ( " # " , 1 )
ret [ regex . strip ( ) ] = reason . strip ( )
else :
ret [ l ] = None
finally :
f . close ( )
2010-04-06 05:55:10 +04:00
return ret
2010-03-30 14:46:26 +04:00
def find_in_list ( regexes , fullname ) :
2010-04-06 05:55:10 +04:00
for regex , reason in regexes . iteritems ( ) :
2010-03-30 14:46:26 +04:00
if re . match ( regex , fullname ) :
if reason is None :
return " "
return reason
return None
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 ) :
pass # We regenerate control messages, so ignore this
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 :
self . output + = msg
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 :
self . output = " "
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 )
2010-09-14 00:29:38 +04:00
self . error_added + = 1
self . total_error + = 1
2014-12-11 05:30:49 +03:00
self . _ops . addError ( test , err )
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 )
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 )
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 )
2014-03-12 18:12:42 +04:00
self . uxsuccess_added + = 1
self . total_uxsuccess + = 1
2015-01-30 04:07:17 +03:00
self . _ops . addUnexpectedSuccess ( 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 )
2010-09-14 00:29:38 +04:00
xfail_reason = find_in_list ( self . expected_failures , test . id ( ) )
2011-12-04 03:23:02 +04:00
if xfail_reason is None :
xfail_reason = find_in_list ( self . flapping , test . id ( ) )
2010-09-14 00:29:38 +04:00
if xfail_reason is not None :
2010-03-30 14:46:26 +04:00
self . xfail_added + = 1
self . total_xfail + = 1
2014-12-11 05:30:49 +03:00
self . _ops . addExpectedFailure ( test , err )
2010-09-14 00:29:38 +04:00
else :
2010-03-30 14:46:26 +04:00
self . fail_added + = 1
self . total_fail + = 1
2014-12-11 05:30:49 +03:00
self . _ops . addFailure ( test , err )
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 )
2011-12-04 03:23:02 +04:00
xfail_reason = find_in_list ( self . expected_failures , test . id ( ) )
if xfail_reason is not None :
self . uxsuccess_added + = 1
self . total_uxsuccess + = 1
2015-02-02 01:20:42 +03:00
self . _ops . addUnexpectedSuccess ( 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 )
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 :
self . expected_failures = { }
2011-12-04 03:23:02 +04:00
if flapping is not None :
self . flapping = flapping
else :
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 ,
2010-10-02 19:02:02 +04:00
totaltests = None ) :
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
if not name in self . test_output :
print " no output for name[ %s ] " % name
if result in ( " success " , " xfail " ) :
self . suites_ok + = 1
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
if not self . name in self . test_output :
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 ( {
' error ' : ' E ' ,
' 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 :
f . write ( self . test_output [ suite ] + " \n \n " )
f . write ( " \n " )
if not self . immediate and not self . verbose :
for suite in self . suitesfailed :
print " = " * 78
print " FAIL: %s " % suite
if suite in self . test_output :
print self . test_output [ suite ]
print " "
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 ' ] )
print " \n ALL OK ( %d tests in %d testsuites) " % ( ok , self . suites_ok )
else :
2011-12-04 04:55:23 +04: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 ' ] ,
2010-10-02 19:02:02 +04:00
len ( self . suitesfailed ) )
def skip_testsuite ( self , name , reason = " UNKNOWN " ) :
self . skips . setdefault ( reason , [ ] ) . append ( name )
if self . totalsuites :
self . totalsuites - = 1