@@ -4,21 +4,48 @@ class AssertException(Exception):
4
4
pass
5
5
6
6
7
+ _print = print
8
+
9
+
10
+ '''Fix the dreaded Unicode Error Trap'''
11
+ def print (* args , ** kwargs ):
12
+ from sys import stdout
13
+ sep = kwargs .get ('sep' , ' ' )
14
+ end = kwargs .get ('end' , '\n ' )
15
+ file = kwargs .get ('file' , stdout )
16
+
17
+ def _replace (c ):
18
+ if ord (c ) >= 128 : return u'&#{};' .format (ord (c ))
19
+ return c
20
+ def _escape (s ): return '' .join (_replace (c ) for c in s )
21
+
22
+ _print (* map (_escape , args ), sep = _escape (sep ), end = _escape (end ), file = file )
23
+
24
+
7
25
def format_message (message ):
8
- return message .replace ("\n " , "<:LF:>" )
26
+ def _replace (c ):
27
+ if ord (c ) >= 65536 : return r'\U' + hex (ord (c ))[2 :].zfill (8 )
28
+ if ord (c ) >= 128 : return r'\u' + hex (ord (c ))[2 :].zfill (4 )
29
+ return c
30
+ def _escape (s ): return '' .join (_replace (c ) for c in s )
31
+ return _escape (message .replace ("\n " , "<:LF:>" ))
32
+
33
+
34
+ def display (type , message , label = "" , mode = "" ):
35
+ print ("\n <{0}:{1}:{2}>{3}" .format (type .upper (), mode .upper (), label , format_message (message )))
9
36
10
37
11
38
def expect (passed = None , message = None , allow_raise = False ):
12
39
if passed :
13
- print ( "< PASSED::> Test Passed" )
40
+ display ( ' PASSED' , ' Test Passed' )
14
41
else :
15
42
message = message or "Value is not what was expected"
16
- print ( "< FAILED::>{0}" . format ( message ) )
43
+ display ( ' FAILED' , message )
17
44
if allow_raise :
18
45
raise AssertException (message )
19
46
20
47
21
- def assert_equals (actual , expected , message = None , allow_raise = True ):
48
+ def assert_equals (actual , expected , message = None , allow_raise = False ):
22
49
equals_msg = "{0} should equal {1}" .format (repr (actual ), repr (expected ))
23
50
if message is None :
24
51
message = equals_msg
@@ -28,15 +55,14 @@ def assert_equals(actual, expected, message=None, allow_raise=True):
28
55
expect (actual == expected , message , allow_raise )
29
56
30
57
31
- def assert_not_equals (actual , expected , message = None , allow_raise = True ):
32
- equals_msg = \
33
- "{0} should not equal {1}" .format (repr (actual ), repr (expected ))
58
+ def assert_not_equals (actual , expected , message = None , allow_raise = False ):
59
+ equals_msg = "{0} should not equal {1}" .format (repr (actual ), repr (expected ))
34
60
if message is None :
35
61
message = equals_msg
36
62
else :
37
63
message += ": " + equals_msg
38
64
39
- expect (actual != expected , message , allow_raise )
65
+ expect (not ( actual == expected ) , message , allow_raise )
40
66
41
67
42
68
def expect_error (message , function ):
@@ -48,9 +74,67 @@ def expect_error(message, function):
48
74
expect (passed , message )
49
75
50
76
51
- def describe (message ):
52
- print ("<DESCRIBE::>{0}" .format (format_message (message )))
53
-
54
-
55
- def it (message ):
56
- print ("<IT::>{0}" .format (format_message (message )))
77
+ def pass_ (): expect (True )
78
+ def fail (message ): expect (False , message )
79
+
80
+
81
+ def assert_approx_equals (actual , expected , margin = 1e-9 , message = None , allow_raise = False ):
82
+ equals_msg = "{0} should be close to {1} with absolute or relative margin of {2}" .format (
83
+ repr (actual ), repr (expected ), repr (margin ))
84
+ if message is None : message = equals_msg
85
+ else : message += ": " + equals_msg
86
+ div = max (abs (actual ), abs (expected ), 1 )
87
+ expect (abs ((actual - expected ) / div ) < margin , message , allow_raise )
88
+
89
+
90
+ '''
91
+ Usage:
92
+ @describe('describe text')
93
+ def describe1():
94
+ @it('it text')
95
+ def it1():
96
+ # some test cases...
97
+ '''
98
+ def _timed_block_factory (opening_text ):
99
+ from timeit import default_timer as timer
100
+ from traceback import format_exception
101
+ from sys import exc_info
102
+
103
+ def _timed_block_decorator (s , before = None , after = None ):
104
+ display (opening_text , s )
105
+ def wrapper (func ):
106
+ if callable (before ): before ()
107
+ time = timer ()
108
+ try : func ()
109
+ except :
110
+ fail ('Unexpected exception raised' )
111
+ tb_str = '' .join (format_exception (* exc_info ()))
112
+ display ('ERROR' , tb_str )
113
+ display ('COMPLETEDIN' , '{:.2f}' .format ((timer () - time ) * 1000 ))
114
+ if callable (after ): after ()
115
+ return wrapper
116
+ return _timed_block_decorator
117
+
118
+ describe = _timed_block_factory ('DESCRIBE' )
119
+ it = _timed_block_factory ('IT' )
120
+
121
+
122
+ '''
123
+ Timeout utility
124
+ Usage:
125
+ @timeout(sec)
126
+ def some_tests():
127
+ any code block...
128
+ Note: Timeout value can be a float.
129
+ '''
130
+ def timeout (sec ):
131
+ def wrapper (func ):
132
+ from multiprocessing import Process
133
+ process = Process (target = func )
134
+ process .start ()
135
+ process .join (sec )
136
+ if process .is_alive ():
137
+ fail ('Exceeded time limit of {:.3f} seconds' .format (sec ))
138
+ process .terminate ()
139
+ process .join ()
140
+ return wrapper
0 commit comments