Skip to content

Commit

Permalink
Merge pull request #126 from fastai/typed
Browse files Browse the repository at this point in the history
add context manager for failed tests
  • Loading branch information
jph00 authored Oct 12, 2020
2 parents 35be479 + 6f257e7 commit d9891fe
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 17 deletions.
1 change: 1 addition & 0 deletions fastcore/_nbdev.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"TEST_IMAGE": "00_test.ipynb",
"TEST_IMAGE_BW": "00_test.ipynb",
"test_fig_exists": "00_test.ipynb",
"TestFail": "00_test.ipynb",
"defaults": "01_foundation.ipynb",
"copy_func": "01_foundation.ipynb",
"patch_to": "01_foundation.ipynb",
Expand Down
17 changes: 15 additions & 2 deletions fastcore/test.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/00_test.ipynb (unless otherwise specified).

__all__ = ['test_fail', 'test', 'nequals', 'test_eq', 'test_eq_type', 'test_ne', 'is_close', 'test_close', 'test_is',
'test_shuffled', 'test_stdout', 'test_warns', 'TEST_IMAGE', 'TEST_IMAGE_BW', 'test_fig_exists']
'test_shuffled', 'test_stdout', 'test_warns', 'TEST_IMAGE', 'TEST_IMAGE_BW', 'test_fig_exists', 'TestFail']

# Cell
from .imports import *
from .utils import *
from collections import Counter
from contextlib import redirect_stdout

Expand Down Expand Up @@ -95,4 +96,16 @@ def test_warns(f, show=False):
# Cell
def test_fig_exists(ax):
"Test there is a figure displayed in `ax`"
assert ax and len(ax.figure.canvas.tostring_argb())
assert ax and len(ax.figure.canvas.tostring_argb())

# Cell
class TestFail:
"A context manager to allow you to test if an exception (ex) is raised. Optionally, search the exception's error message with a regex."
def __init__(self, ex:Exception, regex:str=None):store_attr()
def __enter__(self): pass
def __exit__(self, type, value, traceback):
if isinstance(value, self.ex):
if self.regex:
assert re.search(self.regex, ' '.join(value.args)) is not None, f"Did not find regex:{self.regex} in Exception message."
return True
else: raise TypeError(f"An error of {self.ex} was not raised.")
45 changes: 42 additions & 3 deletions nbs/00_test.ipynb

Large diffs are not rendered by default.

66 changes: 54 additions & 12 deletions nbs/02_utils.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@
{
"data": {
"text/plain": [
"<__main__._t at 0x7f945b39e070>"
"<__main__._t at 0x7fbd57805430>"
]
},
"execution_count": null,
Expand Down Expand Up @@ -2171,7 +2171,7 @@
{
"data": {
"text/plain": [
"['h', 'g', 'f', 'b', 'd', 'e', 'a', 'c']"
"['h', 'c', 'g', 'd', 'a', 'e', 'b', 'f']"
]
},
"execution_count": null,
Expand Down Expand Up @@ -2964,7 +2964,7 @@
{
"data": {
"text/plain": [
"(Path('../fastcore/all.py'), Path('00_test.ipynb'))"
"(Path('../fastcore/__init__.py'), Path('00_test.ipynb'))"
]
},
"execution_count": null,
Expand Down Expand Up @@ -3513,7 +3513,7 @@
{
"data": {
"text/plain": [
"8"
"4"
]
},
"execution_count": null,
Expand Down Expand Up @@ -3645,6 +3645,47 @@
" return functools.update_wrapper(_f, f)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`typed` validates argument types at **runtime**. This is in contrast to [MyPy](http://mypy-lang.org/) which only offers static type checking.\n",
"\n",
"For example, a `TypeError` will be raised if we try to pass an integer into the first argument of the below function: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"@typed\n",
"def discount(price:int, pct:float): \n",
" return (1-pct) * price\n",
"\n",
"with TestFail(TypeError): discount(100.0, .1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also optionally allow multiple types by enumarating the types in a tuple as illustrated below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def discount(price:(int,float), pct:float): \n",
" return (1-pct) * price\n",
"\n",
"assert 90.0 == discount(100.0, .1)"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -3654,11 +3695,12 @@
"@typed\n",
"def foo(a:int, b:str='a'): return a\n",
"test_eq(foo(1, '2'), 1)\n",
"test_fail(partial(foo, 1, 2))\n",
"\n",
"with TestFail(TypeError): foo(1,2)\n",
"\n",
"@typed\n",
"def foo()->str: return 1\n",
"test_fail(partial(foo))\n",
"with TestFail(TypeError): foo()\n",
"\n",
"@typed\n",
"def foo()->str: return '1'\n",
Expand Down Expand Up @@ -3791,7 +3833,7 @@
"text/markdown": [
"<h4 id=\"ProcessPoolExecutor\" class=\"doc_header\"><code>class</code> <code>ProcessPoolExecutor</code><a href=\"\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n",
"\n",
"> <code>ProcessPoolExecutor</code>(**`max_workers`**=*`64`*, **`on_exc`**=*`print`*, **`pause`**=*`0`*, **\\*\\*`kwargs`**) :: [`ProcessPoolExecutor`](/utils.html#ProcessPoolExecutor)\n",
"> <code>ProcessPoolExecutor</code>(**`max_workers`**=*`4`*, **`on_exc`**=*`print`*, **`pause`**=*`0`*, **\\*\\*`kwargs`**) :: [`ProcessPoolExecutor`](/utils.html#ProcessPoolExecutor)\n",
"\n",
"Same as Python's ProcessPoolExecutor, except can pass `max_workers==0` for serial execution"
],
Expand Down Expand Up @@ -3922,11 +3964,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"0 2020-10-08 18:38:18.973557\n",
"1 2020-10-08 18:38:19.223553\n",
"2 2020-10-08 18:38:19.475253\n",
"3 2020-10-08 18:38:19.725614\n",
"4 2020-10-08 18:38:19.976216\n"
"1 2020-10-12 21:15:11.361062\n",
"0 2020-10-12 21:15:11.612469\n",
"2 2020-10-12 21:15:11.863159\n",
"3 2020-10-12 21:15:12.113859\n",
"4 2020-10-12 21:15:12.366331\n"
]
}
],
Expand Down

0 comments on commit d9891fe

Please sign in to comment.