Gdy coś jest zbyt proste do testowania.

0

Chodzą po mnie różne wątpliwości wobec tego czy warto spędzać czas tworząc testy dla banalnych funkcji. To znaczy, gdy funkcja w gruncie rzeczy jest aliasem na jakąś standardowa bądź zewnętrzną funkcje albo, gdy jest to tylko opakowany switch przekazujący sterowanie dalej, albo gdy funkcja to tylko jedna linia kodu z operatorem logicznym mająca na celu uprościć wyrażenie.

No ja domyślam się, że programista może nawet w takich banałach wyjebać się na ryj, ale no.. cholernie szkoda czasu na testowanie tego samego w kilku miejscach : /

Też mnie zastanawia, czy jeśli podejmujecie decyzje, że funkcję F nie będziecie testować to w jaki sposób to oznaczacie w dokumentacji testu?

1

Jeżeli funkcja jest banalna to test też będzie banalny. Napisanie banalnego testu zajmuje bardzo mało czasu. Dlaczego w takim razie nie napisać takiego testu w razie wątpliwości?

0

Testy pisze się też na przyszłość, skąd wniosek, że te kod się nie zmieni, wrapper pozostanie wrapperem, nie stanie się własną implementacją?

0

Testy, z tego jak ja rozumiem testy jednostkowe (ATSD: powiązany post: http://4programmers.net/Forum/Off-Topic/196190-informacje_o_testach_-_ogolne_i_szczegolowe?p=832562#id832562 ) tyczą się nie pojedynczych funkcji, a funkcjonalności klasy. Moim zdaniem możesz testować wiele funkcji w jednym teście (w ramach rozsądku). A funkcji całkowicie prywatnych możesz (powinieneś?) w ogóle nie testować.

Jeśli klasa jest wrapperem, to możesz np zrobić konstruktor (np o widoczności package private) przyjmujący opakowywany obiekt, a w teście do konstruktora podać mock i sprawdzić czy mock ma w dobry sposób wywoływane funkcje.

0

Jeżeli funkcja jest banalna to test też będzie banalny. Napisanie banalnego testu zajmuje bardzo mało czasu. Dlaczego w takim razie nie napisać takiego testu w razie wątpliwości?

Dajmy, że mam w kodzie 3 funkcje { foo(x), boo(x), moo(x) }.
Funkcje boo i foo są przetestowane, natomiast funkcja moo zwraca wartość wyrażenia: foo(x) or boo(x).
Co byś tu testował w teście moo? Wszystkie założenia postawione wobec foo i wobec boo? To zaciemnianie, bo te same asserty wlekłbym w kilku miejscach. Potem gdybym zmodyfikowałbym boo to musiałbym też pamiętać, że w moo też trzeba dowalić kilka assertów : / Eh..

Testy pisze się też na przyszłość, skąd wniosek, że te kod się nie zmieni, wrapper pozostanie wrapperem, nie stanie się własną implementacją?
No i to mnie gryzie : /

Moim zdaniem możesz testować wiele funkcji w jednym teście (w ramach rozsądku). A funkcji całkowicie prywatnych możesz (powinieneś?) w ogóle nie testować.

Jeśli klasa jest wrapperem, to możesz np zrobić konstruktor (np o widoczności package private) przyjmujący opakowywany obiekt, a w teście do konstruktora podać mock i sprawdzić czy mock ma w dobry sposób wywoływane funkcje.
Odlatujesz, ja nie o to pytam.

2

@Autor testujesz oczywiście samą funkcję moo() mockując działanie foo() i boo(). Jak? Po prostu sprawdzasz czy dla odpowiedniego parametru moo() wywołana zostaje poprawnie funkcja boo i foo (większość frameworków mockujących pozwala na takie rzeczy).

0

Dzięki Shalom za odpowiedź.

0

Czytałem o mockach[0], ale tam miałem przykłady, gdy mają identyczny interfejs i po prostu zwracają gotowe wartości bez wielkich obliczeń, bez połączeń z bazą danych, one po prostu symulują obiekty. Mimo to nie bardzo łapię jak to ma się do sprawdzania poprawnych wywołań na podstawie przekazanego parametru.

def foo():
    pass

def boo():
    pass


def moo(x):
    if x > 0:
        foo()
    else:
        moo()

Gdy testuje moo jak mogę się dowiedzieć, że została wywołana funkcja foo bądź moo?
Załóżmy, że test wywołuje moo z dodatnim argumentem i jak mam wyczaić, że foo się wywołało.

Proszę o jakiś przykład, niekoniecznie w Python. Może to być Java, C#, Ruby...

[0] - http://helion.pl/ksiazki/junit-pragmatyczne-testy-jednostkowe-w-javie-andy-hunt-dave-thomas,junit.htm

0

Przykład dla JUnit + Powermock + Easymock przy zalożeniu że metody foo,boo,moo są w klasie Klasa

Klasa mock = createNicePartialMockForAllMethodsExcept(Klasa.class,"moo"); //tworzymy mocka dla wszystkich metod oprócz moo()
mock.foo();
expectLastCall().once();
replayAll();

mock.moo(argument);
verifyAll();

Taki kod przetestuje czy po wywołaniu mock.moo(argument) zostanie raz wywołana metoda foo()

0

Tak czułem, ale taka opcja odpada, bo w moim przypadku postawione założenie nie jest spełnione : /
Te funkcje są porozrzucane po modułach, np jedna to standardowa, a druga to moja własna, a ta trzecia korzysta z obu.
Co radzisz robić?

0

Nie widzę jaki tu masz problem. Mockować zwykle da się absolutnie wszystko (z Powermockiem to już w ogóle ;]).

0

Nie bardzo wiedziałem jak można mockować funkcje z pozostałych modułów.
Póki co próbowałem zrozumieć jakby miało funkcjonować i napisałem taki kod.
Niebawem poszukam do mockowania odpowiedniego libu, ale chciałbym wiedzieć,
czy coś podobnego miałeś na myśli?

from mod1 import boo
from mod2 import moo

def foo(x):
    if x < 0:
        boo(x)
    else:
        moo(x)

# zapamietaj referencje
old_boo = boo
old_moo = moo

def mock_boo(*args, **kargs):
    print('called mock_boo')
    return old_boo(*args, **kargs)
    
def mock_moo(*args, **kargs):
    print('called mock_moo')
    return old_moo(*args, **kargs)

from sys import modules
modules[__name__].__dict__['boo'] = mock_boo
modules[__name__].__dict__['moo'] = mock_moo

foo(10)

modules[__name__].__dict__['boo'] = old_boo
modules[__name__].__dict__['moo'] = old_moo

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