W moim obecnym projekcie trudno mi znaleźć dobre rozwiązanie do tworzenia skalowalnych testów integracyjnych, które nie mają skutków ubocznych. Trochę wyjaśnienia na temat właściwości wolnych od skutków ubocznych: chodzi głównie o bazę danych; po zakończeniu testów nie powinno być żadnych zmian w bazie danych (należy zachować stan). Może skalowalność i zachowanie stanu nie idą w parze, ale naprawdę chcę naciskać na lepsze rozwiązanie.
Oto typowy test integracji (testy dotykają warstwy bazy danych):
public class OrderTests {
List<Order> ordersToDelete = new ArrayList<Order>();
public testOrderCreation() {
Order order = new Order();
assertTrue(order.save());
orderToDelete.add(order);
}
public testOrderComparison() {
Order order = new Order();
Order order2 = new Order();
assertFalse(order.isEqual(order2);
orderToDelete.add(order);
orderToDelete.add(order2);
}
// More tests
public teardown() {
for(Order order : ordersToDelete)
order.delete();
}
}
Jak można sobie wyobrazić, takie podejście daje niezwykle powolne testy. Po zastosowaniu do całych testów integracyjnych testowanie tylko niewielkiej części systemu zajmuje około 5 sekund. Mogę sobie wyobrazić, że liczba ta wzrośnie, gdy zasięg wzrośnie.
Jakie byłoby inne podejście do pisania takich testów? Jedną z alternatyw, o której myślę, jest rodzaj zmiennych globalnych (w ramach klasy) i wszystkie metody testowe mają tę zmienną. W rezultacie powstaje i usuwanych jest tylko kilka zamówień; co skutkuje szybszymi testami. Myślę jednak, że wprowadza to większy problem; testy nie są już izolowane, a ich zrozumienie i analiza staje się coraz trudniejsza.
Może się zdarzyć, że testy integracyjne nie będą przeprowadzane tak często, jak testy jednostkowe; dlatego niska wydajność może być do zaakceptowania dla nich. W każdym razie dobrze byłoby wiedzieć, czy ktoś wymyślił alternatywy dla poprawy skalowalności.