Skip to content

Commit 5e959d8

Browse files
Bubbler-4kazk
authored andcommitted
Add expect_no_error and improve timeout (#1)
* Add `expect_no_error(message, function, exception=BaseException)` Tests if the function, when run, does not raise any exception that can be caught by `exception`. Generates a failed assertion if not met. * Improve `@timeout(sec)` The wrapped function is again wrapped inside `expect_no_error`, so that any exception raised inside the child process can be caught right there. If this happens, generates a failed assertion. * Fix formatting Fixes codewars/codewars-runner-cli#698
1 parent 2aa3348 commit 5e959d8

File tree

1 file changed

+52
-16
lines changed

1 file changed

+52
-16
lines changed

cw-2.py

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
from __future__ import print_function
22

3+
34
class AssertException(Exception):
45
pass
56

7+
68
def format_message(message):
79
return message.replace("\n", "<:LF:>")
810

911

1012
def display(type, message, label="", mode=""):
11-
print("\n<{0}:{1}:{2}>{3}".format(type.upper(), mode.upper(), label, format_message(message)))
13+
print("\n<{0}:{1}:{2}>{3}".format(
14+
type.upper(), mode.upper(), label, format_message(message)))
1215

1316

1417
def expect(passed=None, message=None, allow_raise=False):
@@ -32,7 +35,8 @@ def assert_equals(actual, expected, message=None, allow_raise=False):
3235

3336

3437
def assert_not_equals(actual, expected, message=None, allow_raise=False):
35-
equals_msg = "{0} should not equal {1}".format(repr(actual), repr(expected))
38+
r_actual, r_expected = repr(actual), repr(expected)
39+
equals_msg = "{0} should not equal {1}".format(r_actual, r_expected)
3640
if message is None:
3741
message = equals_msg
3842
else:
@@ -43,21 +47,40 @@ def assert_not_equals(actual, expected, message=None, allow_raise=False):
4347

4448
def expect_error(message, function, exception=Exception):
4549
passed = False
46-
try: function()
47-
except exception: passed = True
48-
except: pass
50+
try:
51+
function()
52+
except exception:
53+
passed = True
54+
except Exception:
55+
pass
56+
expect(passed, message)
57+
58+
59+
def expect_no_error(message, function, exception=BaseException):
60+
passed = True
61+
try:
62+
function()
63+
except exception:
64+
passed = False
65+
except Exception:
66+
pass
4967
expect(passed, message)
5068

5169

5270
def pass_(): expect(True)
71+
72+
5373
def fail(message): expect(False, message)
5474

5575

56-
def assert_approx_equals(actual, expected, margin=1e-9, message=None, allow_raise=False):
57-
equals_msg = "{0} should be close to {1} with absolute or relative margin of {2}".format(
58-
repr(actual), repr(expected), repr(margin))
59-
if message is None: message = equals_msg
60-
else: message += ": " + equals_msg
76+
def assert_approx_equals(
77+
actual, expected, margin=1e-9, message=None, allow_raise=False):
78+
msg = "{0} should be close to {1} with absolute or relative margin of {2}"
79+
equals_msg = msg.format(repr(actual), repr(expected), repr(margin))
80+
if message is None:
81+
message = equals_msg
82+
else:
83+
message += ": " + equals_msg
6184
div = max(abs(actual), abs(expected), 1)
6285
expect(abs((actual - expected) / div) < margin, message, allow_raise)
6386

@@ -70,26 +93,33 @@ def describe1():
7093
def it1():
7194
# some test cases...
7295
'''
96+
97+
7398
def _timed_block_factory(opening_text):
7499
from timeit import default_timer as timer
75100
from traceback import format_exception
76101
from sys import exc_info
77-
102+
78103
def _timed_block_decorator(s, before=None, after=None):
79104
display(opening_text, s)
105+
80106
def wrapper(func):
81-
if callable(before): before()
107+
if callable(before):
108+
before()
82109
time = timer()
83-
try: func()
84-
except:
110+
try:
111+
func()
112+
except Exception:
85113
fail('Unexpected exception raised')
86114
tb_str = ''.join(format_exception(*exc_info()))
87115
display('ERROR', tb_str)
88116
display('COMPLETEDIN', '{:.2f}'.format((timer() - time) * 1000))
89-
if callable(after): after()
117+
if callable(after):
118+
after()
90119
return wrapper
91120
return _timed_block_decorator
92121

122+
93123
describe = _timed_block_factory('DESCRIBE')
94124
it = _timed_block_factory('IT')
95125

@@ -102,10 +132,16 @@ def some_tests():
102132
any code block...
103133
Note: Timeout value can be a float.
104134
'''
135+
136+
105137
def timeout(sec):
106138
def wrapper(func):
107139
from multiprocessing import Process
108-
process = Process(target=func)
140+
msg = 'Should not throw any exception inside timeout'
141+
142+
def wrapped():
143+
expect_no_error(msg, func)
144+
process = Process(target=wrapped)
109145
process.start()
110146
process.join(sec)
111147
if process.is_alive():

0 commit comments

Comments
 (0)