Poprawny unit test dodawania i odejmowanie

0

Mamy sobie kalkulator z dwiema metodami:

public class Calculator {

    public int addition(int a, int b){
        return a+b;
    }

    public int subtraction(int a, int b){
        return a-b;
    }
}

Zastanawiam się, jak powinny wyglądać dobre unit testy do takiej klasy. Czy powinnam podstawiać randomowe liczby ? A co ze skrajnymi ? Chyba nie będę robiła testów dla każdego przypadku ?
Póki co, mam takie coś i nie wydaje mi się, że to dobre testy :)

public class CalculatorTest {

    private Calculator SUT;

    @Before
    public void setUp(){
        SUT = new Calculator();
    }

    @Test
    public void addition() {
        int score = SUT.addition(2,4);
        assertEquals(6, score);
    }

    @Test
    public void subtraction() {
        int score = SUT.subtraction(6,3);
        assertEquals(3,score);
    }
}
6

Czy jest w ogóle sens dokładnie rozpatrywać takie akademickie przypadki?

2

Czy powinnam podstawiać randomowe liczby ? A co ze skrajnymi ? Chyba nie będę robiła testów dla każdego przypadku ?

W takich przypadkach używa się klona QuickCheck-a.

0
somekind napisał(a):

Czy jest w ogóle sens dokładnie rozpatrywać takie akademickie przypadki?

Dlaczego nie ma sensu ? Jest wiele kalkulatorów.

3
somekind napisał(a):

Czy jest w ogóle sens dokładnie rozpatrywać takie akademickie przypadki?

A nie ma? Zdecydowanie najłatwiej jest zbagatelizować jakąś pierdółkę i oczywistą oczywistość implementując coś, popsuć jakąś bzdetę, przeoczyć to przez uśpioną czujność, nie przetestować dokładnie, bo takie coś to trzeba chcieć zepsuć i nie ma sensu... No i potem klops, bo właśnie tam jest bug :D

Jakiś czas temu się tak wyłożyliśmy na pierdółce. Znaczy nie do końca wyłożyliśmy, bo jak dobrze pamiętam nie wyszło nawet poza testy przed złapaniem błędu - w każdym razie problem rozbijał się o durnowate konwersje dat w standardowej bibliotece Javy. W sumie to coś podobnego to tego tutaj programistycznego WTF Shaloma

1

@wioletta90: jedyne co ten kod robi, to wywołuje zdefiniowane w języku operatory, które kompilator właściwie przekłada na trywialne operacje procesora. Taki test testuje kompilator i procesor, nie Twój kod, nawet nie kod frameworka czy jakiejś biblioteki. Więc pytanie - jaką on wartość wnosi? Pozwoli uniknąć jakiegoś realnego błędu, który można popełnić podczas implementacji? Jak bardzo brak takiego testu utrudni znalezienie i naprawienie miejsca błędu, jeśli zostanie wykryty po opublikowaniu?
Niby możesz podejść do tego tak, jakby tam była jakaś sensowna logika, czyli rozpatrzyć dane wejściowe różnych kategorii oraz przypadki brzegowe. W takim przypadku to by było: 0, liczba dodania, liczba ujemna, +max, -max. Ale tak ogólnie, to lepiej sobie chyba wybrać jakiś ciekawszy przypadek do rozważań.

@superdurszlak: jak często implementujesz kalkulator z dodawaniem i odejmowaniem? Czy może po prostu uważasz, że dobrze mieć w projekcie trochę takich klas, bo łatwo je w 100% pokryć testami i się tym chwalić? :P
Co do kodu z przykładu @Shalom to przede wszystkim nie tyle programistyczny WTF, co nieprzeczytana dokumentacja. Ale pomijając już ten drobny szczegół, ten kod jest i tak daleko bardziej skomplikowany niż +.

1
somekind napisał(a):

Czy może po prostu uważasz, że dobrze mieć w projekcie trochę takich klas, bo łatwo je w 100% pokryć testami i się tym chwalić? :P

Bez przesady :D

Po prostu uważam, że najłatwiej zrobić głupi błąd w takim stosunkowo prostym klocku. Co się nadebugowałem LLVM by odkryć, że w jednym zahardkodowanym stringu brakuje paru literek, przez które adresy były obliczane za pomocą nie tej instrukcji..

Widocznie nikomu nie przyszło do głowy przetestować jakiś string z biblioteki standardowej :)

3

Ja bym testował:

  • MAX/MIN, żeby pokazać dokładnie jak zachowuje się ten kod przy przekręcaniu zakresów
  • losowe liczby mniejsze od max/2 żeby pokazać "normalne" zachowanie
2

Komentujecie ten kalkulator i sensowność testów jakby to był produkcyjny kod NASA :D
Przecież to zadanie ze studiów, które ma wymóc pisanie testów - wiadomo, że jest proste. Miała napisać testy do kalkulatora to pisze. Może prowadzący później zmieni coś w implementacji, żeby pokazać sensowność testów i zobaczyć jak reagują. To tylko ćwiczenie dla początkujących.

Chyba nie będę robiła testów dla każdego przypadku ?

Możesz robić ale będzie ich nieskończoność:)

Moja rada to przetestuj kilka przykładów niestandardowych:

  • kiedy wychodzi 0
  • kiedy odejmujesz ujemną
  • kiedy odejmujesz liczbę bardzo dużą
  • kiedy wynik przekracza zasięg inta (2,147,483,647) z dołu też

Ogólnie zrób z 5 tego typu testów na odejmowanie i z 5 na dodawanie i będzie ok. Jak dodasz mnożenie i dzielenie to można będzie kilka opcji dodać jak np brak precyzji przy dzieleniu itp.

1

Ja w takim przypadku zrobiłbym testy w postaci:

  • po jednym teście dla każdej kombinacji w: [int.MAX_VALUE, int.MIN_VALUE, 0, 1, -1, 2]
  • property testing tak jak @part pisał, co prawda model będzie tutaj identyczny z testem (co ogólnie oznacza, że z reguły albo SUT jest zbyt banalny by testować albo, że SUT jest zbyt skomplikowany by testować, w tym przypadku to pierwsze)
0

O testach się już wypowiedzieli. Ja natomiast mam uwagę co do samych nazw metod. Chętniej bym tutaj widział add oraz substract, czyli czasownikopodobne, zamiast tych, które masz teraz.

2

To skandal tak szybko zamykać dyskusję. Czyż ten kalkulator nie powinien testować reguł dla grupy abelowej nad Z? (+ uwzględnienie, że w komputerze nie mamy miejsca na przechowanie Z, stąd przypadki brzegowe wspominane we wcześniejszych odpowiedziach).

add( a, b ) == add (b, a)
add( a, add(b,c) ) == add(add (a,b),c)
add(a,-a)=0
add(a,0) = a

Co do implementacji, to po co implementować odejmowanie od zera? Wszak można użyć implementacji dodawania i zmienić tylko drugi z argumentów.

Mniej miejsca na pomyłki. Profit ;)

0

jedyne co ten kod robi, to wywołuje zdefiniowane w języku operatory, które kompilator właściwie przekłada na trywialne operacje procesora. Taki test testuje kompilator i procesor, nie Twój kod, nawet nie kod frameworka czy jakiejś biblioteki. Więc pytanie - jaką on wartość wnosi? Pozwoli uniknąć jakiegoś realnego błędu, który można popełnić podczas implementacji? Jak bardzo brak takiego testu utrudni znalezienie i naprawienie miejsca błędu, jeśli zostanie wykryty po opublikowaniu?

Ależ wygodne argumenty. Jak widać autor żyje w innej rzeczywistości, tam gdzie nie można popełnić błędu podczas implementacji.

Gdyby były porządne testy to i implementacja była by również porządna. Taka która by obsługiwała sytuacje wyjątkowe.

2

Gdyby były porządne testy to i implementacja była by również porządna.

Mój kod jest porządny dlatego nie muszę go testować.

3

Do odważnych świat należy

0
Berylo napisał(a):

Mój kod jest porządny dlatego nie muszę go testować.

... powiedział

:)

0
superdurszlak napisał(a):

... powiedział

Raczej bezedura, weri, weri anlajkli.

  1. Mało, który ptogramista tak mówi jednak
  2. Najciekawsze kasztany produkcyjne wrzuciłem w kodzie naprawdę nieźle przetestowanym. (Bo w słabo testowanym zwykle kasztany są banalne).
  3. Akurat wymieniłeś przypadki, gdzie raczej trudno było wiarygodnie przetestować.

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