#default_exp test
#export
from local.core.imports import *
from local.notebook.showdoc import *
from PIL import Image
Helper functions to quickly write tests in notebooks
We can check that code raises an exception when that's expected (test_fail
). To test for equality or inequality (with different types of things) we define a simple funciton test
that compares two object with a given cmp
operator.
#export
def test_fail(f, msg='', contains=''):
"Fails with `msg` unless `f()` raises an exception and (optionally) has `contains` in `e.args`"
try: f()
except Exception as e:
assert not contains or contains in str(e)
return
assert False,f"Expected exception but none raised. {msg}"
def _fail(): raise Exception("foobar")
test_fail(_fail, contains="foo")
def _fail(): raise Exception()
test_fail(_fail)
#export
def test(a, b, cmp,cname=None):
"`assert` that `cmp(a,b)`; display inputs and `cname or cmp.__name__` if it fails"
if cname is None: cname=cmp.__name__
assert cmp(a,b),f"{cname}:\n{a}\n{b}"
test([1,2],[1,2], operator.eq)
test_fail(lambda: test([1,2],[1], operator.eq))
test([1,2],[1], operator.ne)
test_fail(lambda: test([1,2],[1,2], operator.ne))
show_doc(all_equal)
all_equal
[source]
all_equal
(a
,b
)
Compares whether a
and b
are the same length and have the same contents
test(['abc'], ['abc'], all_equal)
show_doc(equals)
equals
[source]
equals
(a
,b
)
Compares a
and b
for equality; supports sublists, tensors and arrays too
test([['abc'],['a']], [['abc'],['a']], equals)
#export
def nequals(a,b):
"Compares `a` and `b` for `not equals`"
return not equals(a,b)
test(['abc'], ['ab' ], nequals)
Just use test_eq
/test_ne
to test for ==
/!=
. test_eq_type
check things are equals and of the same type. We define them using test
:
#export
def test_eq(a,b):
"`test` that `a==b`"
test(a,b,equals, '==')
test_eq([1,2],[1,2])
test_eq([1,2],map(int,[1,2]))
test_eq(array([1,2]),array([1,2]))
test_eq(array([1,2]),array([1,2]))
test_eq([array([1,2]),3],[array([1,2]),3])
test_eq(dict(a=1,b=2), dict(b=2,a=1))
test_fail(lambda: test_eq([1,2], 1), contains="==")
test_eq({'a', 'b', 'c'}, {'c', 'a', 'b'})
df1 = pd.DataFrame(dict(a=[1,2],b=['a','b']))
df2 = pd.DataFrame(dict(a=[1,2],b=['a','b']))
test_eq(df1,df2)
test_eq(df1.a,df2.a)
class T(pd.Series): pass
test_eq(df1.iloc[0], T(df2.iloc[0]))
#export
def test_eq_type(a,b):
"`test` that `a==b` and are same type"
test_eq(a,b)
test_eq(type(a),type(b))
if isinstance(a,(list,tuple)): test_eq(map(type,a),map(type,b))
test_eq_type(1,1)
test_fail(lambda: test_eq_type(1,1.))
test_eq_type([1,1],[1,1])
test_fail(lambda: test_eq_type([1,1],(1,1)))
test_fail(lambda: test_eq_type([1,1],[1,1.]))
#export
def test_ne(a,b):
"`test` that `a!=b`"
test(a,b,nequals,'!=')
test_ne([1,2],[1])
test_ne([1,2],[1,3])
test_ne(array([1,2]),array([1,1]))
test_ne(array([1,2]),array([1,1]))
test_ne([array([1,2]),3],[array([1,2])])
test_ne([3,4],array([3]))
test_ne([3,4],array([3,5]))
test_ne(dict(a=1,b=2), ['a', 'b'])
test_ne(['a', 'b'], dict(a=1,b=2))
#export
def is_close(a,b,eps=1e-5):
"Is `a` within `eps` of `b`"
if hasattr(a, '__array__') or hasattr(b,'__array__'):
return (abs(a-b)<eps).all()
if isinstance(a, (Iterable,Generator)) or isinstance(b, (Iterable,Generator)):
return is_close(np.array(a), np.array(b), eps=eps)
return abs(a-b)<eps
#export
def test_close(a,b,eps=1e-5):
"`test` that `a` is within `eps` of `b`"
test(a,b,partial(is_close,eps=eps),'close')
test_close(1,1.001,eps=1e-2)
test_fail(lambda: test_close(1,1.001))
test_close([-0.001,1.001], [0.,1.], eps=1e-2)
test_close(np.array([-0.001,1.001]), np.array([0.,1.]), eps=1e-2)
test_close(array([-0.001,1.001]), array([0.,1.]), eps=1e-2)
#export
def test_is(a,b):
"`test` that `a is b`"
test(a,b,operator.is_, 'is')
test_fail(lambda: test_is([1], [1]))
a = [1]
test_is(a, a)
#export
def test_shuffled(a,b):
"`test` that `a` and `b` are shuffled versions of the same sequence of items"
test_ne(a, b)
test_eq(Counter(a), Counter(b))
a = list(range(50))
b = copy(a)
random.shuffle(b)
test_shuffled(a,b)
test_fail(lambda:test_shuffled(a,a))
a = 'abc'
b = 'abcabc'
test_fail(lambda:test_shuffled(a,b))
a = ['a', 42, True]
b = [42, True, 'a']
test_shuffled(a,b)
#export
def test_stdout(f, exp, regex=False):
"Test that `f` prints `exp` to stdout, optionally checking as `regex`"
s = io.StringIO()
with redirect_stdout(s): f()
if regex: assert re.search(exp, s.getvalue()) is not None
else: test_eq(s.getvalue(), f'{exp}\n' if len(exp) > 0 else '')
test_stdout(lambda: print('hi'), 'hi')
test_fail(lambda: test_stdout(lambda: print('hi'), 'ho'))
test_stdout(lambda: 1+1, '')
test_stdout(lambda: print('hi there!'), r'^hi.*!$', regex=True)
#export
def test_warns(f, show=False):
with warnings.catch_warnings(record=True) as w:
f()
test_ne(len(w), 0)
if show:
for e in w: print(f"{e.category}: {e.message}")
test_warns(lambda: warnings.warn("Oh no!"), {})
test_fail(lambda: test_warns(lambda: 2+2))
test_warns(lambda: warnings.warn("Oh no!"), show=True)
<class 'UserWarning'>: Oh no!
#export
TEST_IMAGE = 'images/puppy.jpg'
im = Image.open(TEST_IMAGE).resize((128,128)); im
#export
TEST_IMAGE_BW = 'images/mnist3.png'
im = Image.open(TEST_IMAGE_BW).resize((128,128)); im
#export
def test_fig_exists(ax):
"Test there is a figure displayed in `ax`"
assert ax and len(np.frombuffer(ax.figure.canvas.tostring_argb(), dtype=np.uint8))
fig,ax = plt.subplots()
ax.imshow(array(im));
test_fig_exists(ax)
#hide
from local.notebook.export import notebook2script
notebook2script(all_fs=True)
Converted 00_test.ipynb. Converted 01_core.ipynb. Converted 01a_utils.ipynb. Converted 01b_dispatch.ipynb. Converted 01c_torch_core.ipynb. Converted 02_script.ipynb. Converted 03_dataloader.ipynb. Converted 04_transform.ipynb. Converted 05_data_core.ipynb. Converted 06_data_transforms.ipynb. Converted 07_vision_core.ipynb. Converted 08_pets_tutorial.ipynb. Converted 09_vision_augment.ipynb. Converted 10_data_block.ipynb. Converted 11_layers.ipynb. Converted 11a_vision_models_xresnet.ipynb. Converted 12_optimizer.ipynb. Converted 13_learner.ipynb. Converted 14_callback_schedule.ipynb. Converted 14a_callback_data.ipynb. Converted 15_callback_hook.ipynb. Converted 15a_vision_models_unet.ipynb. Converted 16_callback_progress.ipynb. Converted 17_callback_tracker.ipynb. Converted 18_callback_fp16.ipynb. Converted 19_callback_mixup.ipynb. Converted 20_metrics.ipynb. Converted 21_vision_learner.ipynb. Converted 22_tutorial_imagenette.ipynb. Converted 23_tutorial_transfer_learning.ipynb. Converted 30_text_core.ipynb. Converted 31_text_data.ipynb. Converted 32_text_models_awdlstm.ipynb. Converted 33_text_models_core.ipynb. Converted 34_callback_rnn.ipynb. Converted 35_tutorial_wikitext.ipynb. Converted 36_text_models_qrnn.ipynb. Converted 37_text_learner.ipynb. Converted 38_tutorial_ulmfit.ipynb. Converted 40_tabular_core.ipynb. Converted 41_tabular_model.ipynb. Converted 42_tabular_rapids.ipynb. Converted 50_data_block_examples.ipynb. Converted 60_medical_imaging.ipynb. Converted 65_medical_text.ipynb. Converted 90_notebook_core.ipynb. Converted 91_notebook_export.ipynb. Converted 92_notebook_showdoc.ipynb. Converted 93_notebook_export2html.ipynb. Converted 94_notebook_test.ipynb. Converted 95_index.ipynb. Converted 96_data_external.ipynb. Converted 97_utils_test.ipynb. Converted notebook2jekyll.ipynb.