Piszę testy jednostkowe systemu sterowania dla gry wideo. System ma kilka zachowań (unikaj tego obszaru z powodu przyczyny A, unikaj tego obszaru z powodu przyczyny B, każde z nich dodaje trochę kontekstu do mapy regionu. Oddzielna funkcja następnie analizuje mapę i wykonuje pożądany ruch.
Mam problem z podjęciem decyzji, jak napisać testy jednostkowe dla zachowań. Jak sugeruje TDD, interesuje mnie tylko to, jak zachowania wpływają na pożądany ruch. Na przykład unikanie z powodu powodu powinno skutkować odejściem od sugerowanej złej pozycji. Nie obchodzi mnie, w jaki sposób i dlaczego zachowanie dodaje kontekst do mapy, tyle że pożądany ruch jest z dala od pozycji.
Więc moje testy dla każdego zachowania konfigurują zachowanie, zapisują je na mapie, a następnie wykonują funkcję parsowania mapy w celu wypracowania pożądanego ruchu. Jeśli ten ruch spełnia moje wymagania, jestem szczęśliwy.
Jednak teraz moje testy zależą zarówno od poprawnego działania, jak i od prawidłowej funkcji analizy mapy. Jeśli funkcja parsowania zawiedzie, dostanę setki nieudanych testów zamiast kilku. Wiele przewodników po pisaniu testów sugeruje, że jest to zły pomysł.
Jeśli jednak przetestuję bezpośrednio wyniki wyjściowe zachowań, wyśmiewając mapę, to na pewno zbyt mocno wiążę się z implementacją? Jeśli mogę uzyskać ten sam pożądany ruch z mapy, używając nieco innego zachowania, testy powinny nadal przejść.
Więc teraz cierpię na dysonans poznawczy. Jak najlepiej ustrukturyzować te testy?
źródło
Odpowiedzi:
W idealnym świecie rzeczywiście istniałby zestaw idealnie ortogonalnych testów jednostkowych, wszystkie na tym samym poziomie abstrakcji.
W prawdziwym świecie zwykle masz testy na wielu różnych poziomach aplikacji, więc często testy wyższego poziomu wykonują funkcje, które zostały już przetestowane przez dedykowane testy niższego poziomu. (Wiele osób woli nazywać takie testy podsystemem / testem integracji wyższym poziomem niż testami jednostkowymi; niemniej jednak mogą one nadal działać w tym samym systemie testów jednostkowych, więc z technicznego punktu widzenia nie ma dużej różnicy).
Nie sądzę, że to zła rzecz. Chodzi o to, aby Twój kod został przetestowany w najlepszy sposób, który pasuje do twojego projektu i twojej sytuacji, a nie przestrzeganie „idealnego sposobu”.
źródło
Tego rodzaju testy wymyślają symulacje. Główna idea: piszesz próbkę dla swojego obiektu (mapa, zachowanie, postać, ...), a następnie piszesz testy przy użyciu tej próbki zamiast rzeczywistego obiektu. Ludzie czasami nazywają fałszywymi odcinkami i wierzę, że są inne słowa na oba.
W twoim przypadku pisałbyś próbną mapę, ilekroć chcesz przetestować zachowania, oraz inne próbne zachowanie, ilekroć chcesz przetestować mapę. Twoje kpiny byłyby idealnie prostsze niż rzeczywiste kpiące zachowania, zawierające tylko metody lub zmienne, których naprawdę potrzebujesz do tego testu. Być może będziesz musiał napisać inną próbkę dla każdego testu lub możesz być w stanie ponownie użyć niektórych prób. Niezależnie od tego, powinny one nadawać się do testu i nie powinny starać się być jak najbardziej realistyczne.
Jeśli podasz przykłady map lub zachowań, być może ktoś może podać przykłady kpiny, które możesz napisać. Nie ja, ponieważ nigdy nie programowałem bardziej zaawansowanej gry wideo niż Pong, a nawet wtedy śledziłem książkę, ale być może ktoś dobrze zorientowany zarówno w testowaniu jednostkowym, jak i tworzeniu gier.
źródło
Myślę, że próbujesz przetestować rzeczy, które są znacznie wyżej niż jednostka.
Większość testów behawioralnych wymagałaby pewnej inteligencji, aby stwierdzić, czy zachowuje się poprawnie. Nie można tego łatwo zrobić za pomocą testów automatycznych.
źródło