Los errores sirven
En mi anterior post hice un refactor a un código, verifique los tests que tenia, y además le agregue más tests usando based property tests.
Que aplicado no?
Así es, cuando hice el refactor metí un hermoso bugcito, que no fue lo peor de todo, ya que lo "mucho" peor fue que los tests seguían pasando, y me hizo acordar a una gran frase
Tener tests malos, es mucho peor que tener codigo fallando
El Bug
El código refactorizado ayer termino así:
def is_first_weekday_of_month(weekday: int) -> bool:
"""Determine if today is the first weekday of the month.
:param weekday: weekday we want to identify (starting as monday -> 0)
"""
weekday = datetime.today().weekday()
day = datetime.today().day
return weekday == weekday and day <= 7
Vieron el error? (yo la primera vez no lo ví y estaba super claro)
Última línea:
return weekday == weekday and day <= 7
Estoy sobre-escribiendo weekday
, por lo tanto la primera condición siempre es verdadera, y lo único que hace el metodo es decirme si el dia esta en la primer semana 🤦🏻♂️.
Y ahora, por que los tests pasaban? vamos a analizarlos
Tests incompletos
El test con hypothesis verificaba si el mismo dia a testear era el primero de la semana, por lo tanto la primer condición no se verificaba nunca.
El test con pytest + parametrize, estaba casi bien hecho, pero el set de datos elegidos no probaba nunca con un dia diferente al lunes
que sea de la primer semana.
Vamos a actualizar el primer test, agregando un caso más:
@pytest.mark.parametrize(
"date,expected",
[
("2021-10-04 03:21:34", True),
("2021-10-11 03:21:34", False),
("2021-07-15 03:21:34", False),
("2021-07-26 03:21:34", False),
("2021-02-01 03:21:34", True),
("2021-12-06 03:21:34", True),
("2021-06-07 03:21:34", True),
("2021-06-03 03:21:34", False), # Caso faltante
],
)
def test_is_first_monday_of_month(date, expected):
with freeze_time(date):
assert dates_utils.is_first_weekday_of_month(PyDay.MONDAY.value) == expected
Corremos de nuevo los tests...
$ pytest -k test_is_first_monday_of_month
FAILED test_is_first_monday_of_month[2021-06-03 03:21:34-False] - assert True == False
1 failed, 7 passed
Genial! ahora los tests atinan un poco mas, y podemos volver a creer en la humanidad (?).
Vamos a corregir el código para resolver el error:
def is_first_weekday_of_month(weekday: int) -> bool:
"""Determine if today is the first weekday of the month.
:param weekday: weekday we want to identify (starting as monday -> 0)
"""
today = datetime.today()
current_weekday = today.weekday()
day = today.day
return current_weekday == weekday and day <= 7
Largamos los tests nuevamente...
$ pytest -k test_is_first_monday_of_month
8 passed
Conclusiones
Lo mejor de esto fue reforzar la idea de los "tests malos que hacen mal", pero tambien agradezco mucho recibir feedback en los posts!
Para la próxima, estoy viendo como utilizar hypothesis pero de una mejor manera, y este caso es un buen candidato!
Un saludo de He-Man para todos: