def divide_anti_pattern(a, b):
try:
result = a / b
except:
result = None
return result
def divide_best_practice(a, b):
result = None
try:
result = a / b
except ZeroDivisionError:
print('Type error: division by 0.')
except TypeError:
# E.g., if b is a string
print("Type error: division by '{0}'.".format(b))
except Exception as e:
# handle any other exception
print("Error '{0}' occurred. Arguments {1}.".format(e.args))
else:
# Excute if no exception occurred
print('No errors')
finally:
# Excute always
if result is None:
result = 0
return result
import pytest
from pytest import raises
from tests.anti_patterns.exception import divide_anti_pattern, divide_best_practice
class TestDivideAntiPattern:
def test_divide_anti_pattern(self):
assert divide_anti_pattern(5, 5) == 1
def test_divide_anti_pattern_with_divide_zero(self):
assert divide_anti_pattern(5, 0) == None
class TestDivideBestPractice:
def test_divide_best_practice(self):
assert divide_best_practice(5, 4) == 1.25
def test_divide_best_practice_with_divide_zero(self):
with raises(ZeroDivisionError):
divide_best_practice(15, 0)
def test_divide_best_practice_with_divide_zero2(self):
with raises(ZeroDivisionError):
print(1/0)
(reservation) untitled1 (master) ✗ py.test tests/anti_patterns/test_exception.py
================================================= test session starts =================================================
platform darwin -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
rootdir: /Users/re4lfl0w/PycharmProjects/untitled1/tests, inifile: pytest.ini
plugins: cov-2.2.0, django-2.9.1, xdist-1.13.1
collected 5 items
tests/anti_patterns/test_exception.py ...F.
====================================================== FAILURES =======================================================
__________________________ TestDivideBestPractice.test_divide_best_practice_with_divide_zero __________________________
self = <test_exception.TestDivideBestPractice object at 0x1065bada0>
def test_divide_best_practice_with_divide_zero(self):
with raises(ZeroDivisionError):
> divide_best_practice(15, 0)
E Failed: DID NOT RAISE
tests/anti_patterns/test_exception.py:21: Failed
------------------------------------------------ Captured stdout call -------------------------------------------------
Type error: division by 0.
If you catch it, raises no longer Sees it,
If you just call divide_best_practice outside a test, you will see that it won't raise ZeroDivisionError either. That's because, as @RonnyPfannschmidt said, you are catching it and just printing a message, effectively swallowing it to the caller. So pytest is correct here.
If you want the caller to see the exception, you have to re-raise it yourself:
except ZeroDivisionError:
print('Type error: division by 0.')
raise
@RonnyPfannschmidt Thank you.
@nicoddemus Thank you. I realized your example code. I forget 'raise'. ok. understand. Always write 'raise' in except??
If you want to propagate the exception to the caller, then yes. The are situations where you might want to handle the exception locally though.
Most helpful comment
If you catch it, raises no longer Sees it,