Jeszcze słowo o TDD

O TDD napisano wiele, sam napisałem całkiem sporo i mówiłem całkiem sporo podczas kilku prelekcji. Używam TDD od ponad 5 lat już. Powinienem być super mega ninja pro TDD master. Mimo tego jakiś czas temu, pisząc bardzo prosty kod, na prawdę super prosty, naszła mnie taka refleksja:

Jest zielone, jest ok.

[csharp]
[Fact]
public void Example_test()
{
    _pinger.Ping().Returns(c =>
    {
        throw new Exception();
    });
    Assert.DoesNotThrow(()=>_monitor.CheckAvaliability());
    _destinationSystem.Received(1).Ping(Arg.Is<IDiagnostics>(diag => diag.State == ""));
}
[/csharp]

Powyższy kawałek kodu używa NSubstitute (.Ping().Returns(c=>…..) do mockownia. Oraz XUnit-a do testów. Napisałem test jak wyżej, napisałem kod. Niby wszystko zielone, niby ok. Jakimś cudem jednak pokusiło mnie, żeby dorzucić AutoData. AutoData to taki sprytny atrybut, który pozwala generować dane testowe. W moim przypadki Message z wyjątki ma znaczenie, dlatego stwierdziłem, że Message można spokojnie generować – tutaj kod jest taki, że mam pudełko, które jak zrobi coś złego to to złe ma wyjść z drugiej strony – case dla AutoData jak malowany.

[csharp]
[Theory,AutoData]
public void Example_test(string exceptionMessage)
{
    _pinger.Ping().Returns(c =>
    {
        throw new Exception(exceptionMessage);
    });<
    Assert.DoesNotThrow(()=>_monitor.CheckAvaliability());
    _destinationSystem.Received(1).Ping(Arg.Is<IDiagnostics>(diag => diag.State == exceptionMessage));
}
[/csharp]

No i zonk!!! Test już nie bardzo to przechodzi. Pomyślałem, bez jaj, przecież implementacja jest tak prosta, że tego nie da się zepsuć – nawet nie wiem po co pisałem na to test, ale nie uprzedzajmy faktów…. Debug testu i….. okazało się, że jednak w kodzie gdzie łapię wyjątek, to oprócz logowania tak jak to powinno być to już message-a  nie przepisuję. Kto by pomyślał.

Testy jednostkowe nie dają 100% gwarancji, że powstanie kod bez bugów, nie dają nawet jakiejkolwiek gwarancji, co jednak dają, to dużo wyższą szansę, że powstały kod będzie miał mniej bugów niż bez testów. W moim przypadku, okazało się, ze prosta refaktoryzacja – lub bez AutoData dodanie kilku przypadków testowych, pozwoliła złapać buga zanim kod poszedł na produkcję.