string
to int
def custom_convert_str_to_int(my_str: str) -> int | None:
_ = my_str
return 0
def test_custom_convert_str_to_int_smoke_test():
# happy path, "the function will not crash"
assert custom_convert_str_to_int("1") == 1
def test_custom_convert_str_to_int_when_invalid_input():
assert custom_convert_str_to_int("Alfa") is None
assert custom_convert_str_to_int("O is not 0") is None
assert custom_convert_str_to_int("3. 14") is None
def test_custom_convert_str_to_int_when_int_with_space():
assert custom_convert_str_to_int(" 7 ") == 7
def test_custom_convert_str_to_int_when_float_string():
assert custom_convert_str_to_int("3.14") == 4
def custom_convert_str_to_int(my_str: str) -> int | None:
try:
converted_float = float(my_str)
converted = math.ceil(converted_float)
except ValueError:
converted = None
return converted
mypy name_file.py
ruff name_file.py
// or pre-commit run --all-files
pytest name_file.py
Sometimes, due to N factors, certain parts of a function are uncontrollable or non-reproducible.
Examples include external I/O requests or calculations involving randomness. Additionally, the current code architecture makes traditional testing methods complex.
In such scenarios, we can use unittest.mock
to patch functions and mock inputs. In this example, we’ll assume the tax is dynamic, fetched via an I/O operation (e.g., an SQL query). The final price is calculated using the following equation:
total_price_with_tax = (price_un * (1 + federal_tax + state_tax)) * quantity
from pytest import approx
from unittest.mock import patch
from unittest.mock import Mock
def sql(query) -> None | float:
_ = query
return None
def _select_federal_tax(product_id: int) -> float:
federal_data = sql(f"select federal_tax from federal_table where id = {product_id}")
federal_tax = federal_data[0]
return federal_tax
def _select_state_tax(product_id: int) -> float:
state_data = sql(f"select state_tax from state_table where id = {product_id}")
state_tax = state_data[0]
return state_tax
def calc_total_price_with_tax(product_id: int, quantity: int, price_un: float) -> float:
federal_tax = _select_federal_tax(product_id=product_id)
state_tax = _select_state_tax(product_id=product_id)
tax_per_unit = (price_un * federal_tax) + (price_un * state_tax)
total_price_with_tax = (price_un + tax_per_unit) * quantity
return total_price_with_tax
def test_calc_total_price_with_tax_when_quantity_is_zero():
with (
patch("pricing._select_federal_tax") as mock_federal_tax,
patch("pricing._select_state_tax") as mock_state_tax,
):
mock_federal_tax.return_value = 0.05
mock_state_tax.return_value = 0.10
total_price = calc_total_price_with_tax(
product_id=Mock(), quantity=0, price_un=100
)
assert total_price == 0.0
def test_calc_total_price_with_tax_proporcional_to_quantity():
with (
patch("pricing._select_federal_tax") as mock_federal_tax,
patch("pricing._select_state_tax") as mock_state_tax,
):
mock_federal_tax.return_value = 0.10
mock_state_tax.return_value = 0.10
total_price = calc_total_price_with_tax(
product_id=Mock(), quantity=1, price_un=100
)
assert total_price == 120
total_price = calc_total_price_with_tax(
product_id=Mock(), quantity=10, price_un=100
)
assert total_price == 10 * 120
def test_calc_total_price_with_tax_with_zero_tax_is_price_times_quantity():
with (
patch("pricing._select_federal_tax") as mock_federal_tax,
patch("pricing._select_state_tax") as mock_state_tax,
):
mock_federal_tax.return_value = 0.0
mock_state_tax.return_value = 0.0
total_price = calc_total_price_with_tax(
product_id=Mock(), quantity=3, price_un=100
)
assert total_price == 3 * 100
def test_calc_total_price_with_tax_is_equal_to_the_given_formula():
price_un = 100
federal_tax = 0.1
state_tax = 0.05
quantity = 2
formula_total_price_with_tax = (price_un * (1 + federal_tax + state_tax)) * quantity
with (
patch("pricing._select_federal_tax") as mock_federal_tax,
patch("pricing._select_state_tax") as mock_state_tax,
):
mock_federal_tax.return_value = federal_tax
mock_state_tax.return_value = state_tax
total_price = calc_total_price_with_tax(
product_id=Mock(), quantity=quantity, price_un=price_un
)
# Due to float approximation error, it is sometimes necessary to use an 'approx'.
assert total_price == approx(formula_total_price_with_tax, abs=0.001)
# ... There are several other tests that can be done for this flow
Errors can still occur if sql returns an invalid value e.g.: grater than 1, NULL value or even or database connection issues. There must be validations of all external data of the application. As well as displaying an error message, if it is not possible to recover.
Remember, Tests must be part of the system architecture, a change in requirements cannot be “impossible/infeasible” due to tests.