W jaki sposób zarządza się fikcyjnymi danymi używanymi do testów? Przechowywać je w odpowiednich jednostkach? W osobnym projekcie testowym? Załaduj je Serializerem z zasobów zewnętrznych? Lub po prostu odtworzyć je w razie potrzeby?Strategie testów danych i testów jednostkowych w modułowym stosie aplikacji
Mamy stos aplikacji z kilkoma modułami, w zależności od innego, z każdym elementem zawierającym. Każdy moduł ma własne testy i wymaga użycia danych fikcyjnych.
Teraz moduł, który ma wiele zależności, będzie potrzebować wielu fałszywych danych z innych modułów. Jednak nie publikują swoich fałszywych obiektów, ponieważ są częścią zasobów testowych, więc wszystkie moduły muszą ustawiać wszystkie fałszywe obiekty, których potrzebują ponownie.
także: większość pól w naszych jednostkach nie są pustych więc nawet uruchomione transakcje przeciwko warstwie obiektu wymaga od nich zawiera jakąś wartość, przez większość czasu z dalszymi ograniczeniami jak wyjątkowość, długości, itp
Czy istnieje najlepsza praktyka wyjścia z tego lub wszystkie rozwiązania kompromisowe?
Więcej szczegółów
Nasz stos wygląda tak:
jeden moduł:
src/main/java --> gets jared (.../entities/*.java contains the entities)
src/main/resources --> gets jared
src/test/java --> contains dummy object setup, will NOT get jared
src/test/resources --> not jared
Używamy Maven obsłużyć zależności. Przykładem
moduł:
- Moduł A ma jakieś fikcyjne przedmioty
- Moduł B potrzebuje własnych obiektów i tak samo jak moduł A
Wariant A)
Moduł testowy T może przechowywać wszystkie fałszywe obiekty i dostarczać je w zakresie testowym (aby załadowane zależności nie były jared) do wszystkich testów we wszystkich modułach. Czy to będzie działało? Znaczenie: Jeśli załadować T w A i uruchomienia instalacji w NIE będzie zawierać odniesienia wprowadzone przez T szczególnie nie B? Wtedy jednak A będzie wiedział o datamodelu B.
Opcja b)
Moduł A dostarcza manekina obiektów gdzieś w src/main/java../entities/dummy
pozwalając B je zdobyć podczas nie wie o B „s dane fikcyjne
Opcja c)
Każdy moduł zawiera zasoby zewnętrzne, które są serializowanymi sztucznymi obiektami. Mogą być deserializowane przez środowisko testowe, które ich potrzebuje, ponieważ ma zależność od modułu, do którego należą. Będzie to wymagało jednak, aby każdy moduł tworzył i serializował swoje fałszywe obiekty i jak by to zrobić? Jeśli z innym testem jednostkowym wprowadza zależności między testami jednostkowymi, które nigdy nie powinny się zdarzyć lub ze skryptem, będzie trudny do debugowania i nie będzie elastyczny.
Wariant d)
Użyj mock ramy i przypisać wymagane pola ręcznie dla każdego testu, ile potrzeba. Problem polega na tym, że większość pól w naszych jednostkach nie jest null, a zatem będzie wymagać wywołania setterów lub konstruktorów, co spowoduje, że znowu będziemy na początku.
Co nie chcemy
nie chcemy, aby skonfigurować statyczny z bazy danych statycznych jak struktura wymagane obiekty będzie ciągle zmieniać. Dużo teraz, trochę później. Tak więc chcemy, aby hibernacja ustawiała wszystkie tabele i kolumny i wypełniała je danymi w czasie testowania jednostkowego. Również statyczna baza danych wprowadziłaby wiele potencjalnych błędów i zależności między testami.
Czy moje myśli zmierzają we właściwym kierunku? Jaka jest najlepsza praktyka radzenia sobie z testami wymagającymi dużej ilości danych? Będziemy dysponować kilkoma współzależnymi modułami, które będą wymagać obiektów wypełnionych pewnymi danymi z kilku innych modułów.
EDIT
Niektóre więcej informacji o tym, jak robimy to teraz w odpowiedzi na drugą odpowiedź:
więc dla uproszczenia, że mamy trzy moduły: Person
, Product
, Order
. Person
będzie testować kilka metod, za pomocą menedżera MockPerson
obiektu:
(w osobę/src/test/java :)
public class MockPerson {
public Person mockPerson(parameters...) {
return mockedPerson;
}
}
public class TestPerson() {
@Inject
private MockPerson mockPerson;
public testCreate() {
Person person = mockPerson.mockPerson(...);
// Asserts...
}
}
Klasa MockPerson
nie zostaną zapakowane.
To samo dotyczy testy produktu:
(w produktu/src/test/java :)
public class MockProduct() { ... }
public class TestProduct {
@Inject
private MockProduct mockProduct;
// ...
}
MockProduct
jest potrzebne, ale nie zostaną zapakowane.
Teraz Testy Zamówienie będzie wymagać MockPerson
i MockProduct
, więc teraz mamy obecnie trzeba tworzyć zarówno jak MockOrder
przetestować Order
.
(w zlecenia/src/test/java :)
Są duplikaty i będą musiały być zmieniane za każdym razem Person
lub Product
Zmiany
public class MockProduct() { ... }
public class MockPerson() { ... }
Jest to jedyna klasa powinno być tutaj:
public class MockOrder() { ... }
public class TestOrder() {
@Inject
private order.MockPerson mockPerson;
@Inject
private order.MockProduct mockProduct;
@Inject
private order.MockOrder mockOrder;
public testCreate() {
Order order = mockOrder.mockOrder(mockPerson.mockPerson(), mockProduct.mockProduct());
// Asserts...
}
}
The probl em jest, że teraz musimy zaktualizować person.MockPerson
i order.MockPerson
, gdy zmienimy Person
.
Czy nie lepiej jest opublikować Mocks przy użyciu słoika, aby każdy inny test, który ma taką zależność, mógł po prostu wywołać Mock.mock i uzyskać ładnie skonfigurowany obiekt? A może to ciemna strona - prosta droga?
Hej, cwash! Dziękuję za wskaźnik fabryczny. Pamiętam, że korzystałem z tego w samouczku rails;) To może być rozwiązanie, muszę to sprawdzić dalej. – Pete
@Pete - fajnie, czy możesz zostawić notatkę/aktualizację, informując nas, co postanowiłeś? – cwash
Wygląda więc na to, że możemy go użyć jako centralnego importera danych. W końcu jednak jest to tylko opcja a), co oznacza, że jakiś projekt zewnętrzny będzie zawierał wszystkie wymagane generatory danych. Wciąż zastanawiasz się, czy to najlepsza droga. Mając nadzieję na więcej opinii na ten temat ... – Pete