Jedna asercja per test case i testowanie metody z różnymi wartościami

0

Załóżmy, że mamy klasę, która reprezentuje jakiś przedział. Potrzebujemy dodać do niej funkcjonalność, która sprawdzi, czy jakaś liczba zawiera się w danym przedziale.
Liczba może znajdować się:

  • poza przedziałem z lewej
  • w przedziale
  • poza przedziałem z prawej.
public class IntervalTest {

    @Test
    public void Includes_NumberWithinAnInterval_ReturnsTrue() {
        Interval interval = new Interval(5, 10);

        int number = 7;

        assertTrue(interval.includes(7));
    }

    @Test
    public void Includes_NumberOutsideAnInterval_ReturnsFalse() {
        Interval interval = new Interval(5, 10);

        int outsideLeftBoundary = 2;
        int outsideRightBoundary = 12;

        assertFalse(interval.includes(outsideLeftBoundary));
        assertFalse(interval.includes(outsideRightBoundary));
    }
}

[Pytanie 1] Czy w tym wypadku rozbijalibyście test Includes_NumberOutsideAnInterval_ReturnsFalse na dwa osobne testy, czy takie dwie asercje, niejako powiązane ze sobą, mogą znajdować się w jednej metodzie?

[Pytanie 2] Spotkałem się już z takimi przypadkami, gdzie metody tego typu działały tylko dla liczb parzystych, albo tylko dla liczb pierwszych. Czy w tym wypadku napisalibyście coś w tym rodzaju:

    @Test
    public void Includes_NumberWithinAnInterval_ReturnsTrue() {
        int leftBoundary = 5;
        int rightBoundary = 10;
        
        Interval interval = new Interval(leftBoundary, rightBoundary);

        for (int i = leftBoundary; i <= rightBoundary; i++) {
            assertTrue(interval.includes(i));
        }
    }

[Pytanie 3] Czy jeżeli do moj klasy Interval dodam ficzer pozwalający na sprecyzowanie granic przedziału (przedział otwarty/zamknięty, lewostronnie otwartyi itd.) to dla każdej takiej kombinacji * zawiera/nie zawiera powinienem mieć oddzielny test?
[Pytanie 4] Załóżmy, że dochodzi metoda overlaps, która sprawdza, czy przedziały się nakładają. Ta metoda wywołuję tylko metodę includes. Czy w tym wypadku powinienem dodać testy dla metody overlaps pokrywające wszystkie przypadki użycia, czy wystarczy, że moja metoda includes jest otestowana? Bo de facto jak coś się zepsuje w metodzie includes, to metoda overlaps też przestanie działać.

0

Ktoś coś? :)

2

Powinniśmy wprowadzić zasadę jedno pytanie na wątek bo napchałeś tu tyle że pewnie nikomu się nie chce odpowiadać ;)

Generalnie zasada jedna asercja na test jest bez sensu. Jedyna dobra zasada to zdrowy rozsądek. Jasne że jak napchasz 1000 asercji w teście to potem nie wiadomo o co chodzi, ale jeśli masz coś mocno powiązanego ze sobą to nie ma sensu cudować byleby nie mieć dwóch asercji.

Są "generatory" testów w runtime i tego bym użył. Bo przecież te wszystkie testy będą takie same. Potem dodajesz tylko konfiguracje testu dla kolejnego feature i voila.

Czemu nie zrobic w takim razie tylko testu dla overlaps? Albo idąc dalej, po co w ogóle 2 metody skoro wystarczyłaby jedna? Ewentualnie zawsze możesz mockować jedną i zrobić jeden test, ale jego wartość w twoim przypadku będzie znikoma.

1

W takim przypadku dążyłbym do rozwiązania w stylu:

  @TestCase(7, Returns = true)
  @TestCase(2, Returns = false)
  @TestCase(12, Returns = false)
    public void Includes_ShouldProperlyCheckIfValueIsInRange(int valueToCheck) {

        Interval interval = new Interval(5, 10);
        return interval.includes(valueToCheck);
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1