Mam coś takiego:
public byte[] EncodeMyObject(MyObject obj)
Testowałem tak:
byte[] expectedResults = new byte[3]{ 0x01, 0x02, 0xFF };
Assert.IsEqual(expectedResults, EncodeMyObject(myObject));
EDYCJA: Dwa proponowane przeze mnie sposoby to:
1) Używanie zakodowanych oczekiwanych wartości, jak w powyższym przykładzie.
2) Używanie dekodera do dekodowania zakodowanej tablicy bajtów i porównywanie obiektów wejścia / wyjścia.
Problem, który widzę w metodzie 1, polega na tym, że jest ona bardzo krucha i wymaga dużej ilości zakodowanych wartości.
Problem z metodą 2 polega na tym, że testowanie enkodera zależy od prawidłowego działania dekodera. Jeśli koder / dekoder są równo uszkodzone (w tym samym miejscu), testy mogą dać fałszywie dodatnie wyniki.
Mogą to być jedyne sposoby przetestowania tego rodzaju metody. Jeśli tak jest, to dobrze. Zadaję pytanie, aby sprawdzić, czy istnieją lepsze strategie dla tego typu testów. Nie mogę ujawnić wewnętrznych elementów konkretnego enkodera, nad którym pracuję. Pytam ogólnie, jak byś rozwiązał ten problem, i nie uważam, żeby elementy wewnętrzne były ważne. Załóżmy, że dany obiekt wejściowy zawsze wytworzy tę samą wyjściową tablicę bajtów.
źródło
myObject
przejść odmyObject
do{ 0x01, 0x02, 0xFF }
? Czy ten algorytm można rozbić i przetestować? Powód, dla którego obecnie pytam, wygląda na to, że masz test, który dowodzi, że jedna magiczna rzecz wytwarza inną magiczną rzecz. Twoja jedyna pewność polega na tym, że jedno wejście daje jedno wyjście. Jeśli potrafisz złamać algorytm, możesz zyskać dalsze zaufanie do algorytmu i mniej polegać na magicznych wejściach i wyjściach.Odpowiedzi:
Jesteś w trochę nieznośnej sytuacji. Jeśli miałeś format statyczny, w którym byłeś kodowany, pierwszą metodą byłaby droga. Gdyby to był tylko twój własny format i nikt inny nie musiałby dekodować, to druga metoda byłaby dobrym rozwiązaniem. Ale tak naprawdę nie pasujesz do żadnej z tych kategorii.
Chciałbym spróbować załamać poziom abstrakcji.
Zacznę więc od czegoś na poziomie bitowym, że coś przetestuję
Chodzi o to, że autor tekstów wie, jak wypisywać najbardziej prymitywne typy pól, takie jak ints.
Bardziej złożone typy zostaną zaimplementowane przy użyciu i przetestowane:
Zauważ, że pozwala to uniknąć jakiejkolwiek wiedzy na temat sposobu pakowania rzeczywistych bitów. Zostało to przetestowane w poprzednim teście, a do tego testu założymy, że działa.
Następnie na kolejnym poziomie abstrakcji mielibyśmy
dlatego też nie staramy się uwzględniać wiedzy o tym, w jaki sposób kodowane są zmienne, daty lub liczby. W tym teście interesuje nas tylko kodowanie produkowane przez encodeObject.
Ostateczny wynik jest taki, że jeśli format dat zostanie zmieniony, będziesz musiał naprawić testy, które faktycznie dotyczą dat, ale wszystkie inne kody i testy nie dotyczą sposobu, w jaki daty są faktycznie kodowane, a po zaktualizowaniu kodu, aby która działa, wszystkie testy przejdą dobrze.
źródło
Zależy. Jeśli kodowanie jest czymś całkowicie naprawionym, gdzie każda implementacja ma tworzyć dokładnie takie same dane wyjściowe, nie ma sensu sprawdzanie niczego innego niż weryfikacja przykładowych danych wejściowych odwzorowanych na dokładnie oczekiwane wyniki. To najbardziej oczywisty test i prawdopodobnie również najłatwiejszy do napisania.
Jeśli jest miejsce do poruszania się z alternatywnymi wyjściami, jak w standardzie MPEG (np. Istnieją pewne operatory, które możesz zastosować do wejścia, ale możesz swobodnie kompromisować wysiłek kodowania w porównaniu z jakością wyjściową lub przestrzenią dyskową), wtedy lepiej zastosować zdefiniowaną strategię dekodowania danych wyjściowych i sprawdź, czy jest ona taka sama jak na wejściu - lub, jeśli kodowanie jest stratne, że jest dość zbliżona do oryginalnego wejścia. Jest to trudniejsze do zaprogramowania, ale chroni cię przed wszelkimi przyszłymi ulepszeniami twojego enkodera.
źródło
Przetestuj to
encode(decode(coded_value)) == coded_value
idecode(encode(value)) == value
. Jeśli chcesz, możesz dać losowy wkład do testów.Nadal możliwe jest, że zarówno koder, jak i dekoder są uszkodzone w komplementarny sposób, ale wydaje się to mało prawdopodobne, chyba że masz koncepcyjne nieporozumienie ze standardem kodowania. Wykonywanie zakodowanych testów kodera i dekodera (tak jak już to robisz) powinno temu zapobiec.
Jeśli masz dostęp do innej implementacji tego, o której wiadomo, że działa, możesz przynajmniej użyć go, aby uzyskać pewność, że twoja implementacja jest dobra, nawet jeśli użycie jej w testach jednostkowych byłoby niemożliwe.
źródło
decode(encode(char))
nie byłby równychar
(byłby równychar+2
).Testuj zgodnie z wymaganiami .
Jeśli wymaganiem jest tylko „kodowanie do strumienia bajtów, który po zdekodowaniu tworzy równoważny obiekt”, to po prostu przetestuj koder dekodując. Jeśli piszesz zarówno koder, jak i dekoder, po prostu przetestuj je razem. Nie mogą mieć „pasujących błędów”. Jeśli pracują razem, test kończy się pomyślnie.
Jeśli istnieją inne wymagania dotyczące strumienia danych, musisz je przetestować, sprawdzając zakodowane dane.
Jeśli kodowany format jest wstępnie zdefiniowany, albo będziesz musiał zweryfikować zakodowane dane w stosunku do oczekiwanego wyniku, jak to zrobiłeś, lub (lepiej) uzyskać dekoder referencyjny, któremu można zaufać w celu weryfikacji. Zastosowanie dekodera referencyjnego eliminuje możliwość błędnej interpretacji specyfikacji formatu.
źródło
W zależności od używanej struktury testowej i paradygmatu możesz nadal używać do tego wzoru Arrange Act Assert, tak jak powiedziałeś.
Powinieneś znać wymagania
EncodeMyObject()
i możesz użyć tego wzorca do przetestowania każdego z nich pod kątem poprawnych i niepoprawnych kryteriów, poprzez ułożenie każdego z nich i zakodowanie oczekiwanego wynikuexpected
, podobnie dla dekodera.Ponieważ oczekiwane są zakodowane na stałe, będą kruche, jeśli wprowadzisz ogromną zmianę.
Możesz być w stanie zautomatyzować za pomocą czegoś opartego na parametrach (spójrz na Pex ) lub jeśli robisz DDD lub BDD, spójrz na gerkin / ogórek .
źródło
Ty decydujesz, co jest dla Ciebie ważne.
Czy jest dla Ciebie ważne, aby Obiekt przetrwał podróż w obie strony, a dokładny format drutu nie jest tak naprawdę ważny? A może dokładny format przewodowy jest ważną częścią funkcjonalności twojego kodera i dekodera?
Jeśli to pierwsze, to po prostu upewnij się, że obiekty przetrwają podróż w obie strony. Jeśli zarówno koder, jak i dekoder są uszkodzone w dokładnie komplementarny sposób, tak naprawdę to nie obchodzi.
Jeśli to drugie, musisz przetestować, czy format drutu jest zgodny z oczekiwaniami dla danych wejściowych. Oznacza to albo testowanie formatu bezpośrednio, albo użycie implementacji referencyjnej. Ale po przetestowaniu podstaw możesz uzyskać wartość z dodatkowych testów w obie strony, które powinny być łatwiejsze do napisania w objętości.
źródło