2009-08-25 5 views
16

Nasz zespół ma setki testów integracyjnych, które trafiają do bazy danych i sprawdzają wyniki. Mam dwie klasy bazowe dla wszystkich testów integracyjnych, jedną dla testów tylko do odczytu i jedną dla testów tworzenia/aktualizacji/usuwania. Klasa bazowa tylko do odczytu regeneruje bazę danych podczas TestFixtureSetup, więc wykonuje się tylko raz dla każdej klasy testowej. Klasa bazowa CUD odnawia bazę danych przed każdym testem. Każda klasa repozytorium ma swoją własną odpowiednią klasę testową.Najlepsze praktyki testowania integracji

Jak można sobie wyobrazić, to cała sprawa zajmuje trochę czasu (zbliża się 7-8 minut biegać i szybko rośnie). Uruchomienie tego działania jako części naszego CI (CruiseControl.Net) nie stanowi problemu, ale uruchomienie lokalnie zajmuje dużo czasu i naprawdę uniemożliwia ich uruchomienie przed zatwierdzeniem kodu.

Moje pytanie brzmi: czy istnieją najlepsze praktyki, które pomogą przyspieszyć wykonywanie tego typu testów integracyjnych?

jestem w stanie wykonać je w pamięci (a la SQLite), ponieważ używamy jakąś specyficzną funkcjonalność bazy danych (obliczonych kolumn, itp), które nie są obsługiwane w SQLite.

Cały zespół musi być w stanie je wykonać, więc uruchomienie ich na lokalnej instancji SQL Server Express lub coś może być podatne na błędy, chyba że ciągi połączeń są takie same dla tych wystąpień.

W jaki sposób realizujesz to w swoim sklepie i co działa dobrze?

Dzięki!

Odpowiedz

5

Jestem programistą java, ale miałem do czynienia z podobnym problemem. Zauważyłem, że uruchamianie instancji lokalnej bazy danych działa dobrze ze względu na szybkość (brak danych do przesłania przez sieć) i ponieważ w ten sposób nie masz rywalizacji w bazie testów integracji.

Ogólne podejście używamy do rozwiązania tego problemu jest stworzenie skryptów kompilacji do zapoznania się z ciągów połączenia bazy danych z pliku konfiguracyjnego, a następnie utworzyć jeden plik na środowisko. Na przykład jeden plik dla WORKSTATION, inny dla CI. Następnie ustawiasz skrypty budowania, aby odczytać plik konfiguracyjny na podstawie określonego środowiska. Buduje się na stacji roboczej programisty uruchamianej przy użyciu konfiguracji WORKSTATION, a kompilacje działające w środowisku CI używają ustawień CI.

Pomaga również ogromnie jeśli cały schemat bazy danych mogą być tworzone z jednego skryptu, więc każdy programista może szybko skonfigurować lokalną bazę danych do testowania. Można nawet rozszerzyć tę koncepcję do następnego poziomu i dodać skrypt konfiguracji bazy danych do procesu budowania, tak aby cała konfiguracja bazy danych mogła być skryptowana, aby nadążyć za zmianami w schemacie bazy danych.

11

w NUnit można ozdobić swoje zajęcia testowe (lub metody) z atrybutem np

[Category("Integration")] 
public class SomeTestFixture{ 
    ... 
} 
[Category("Unit")] 
public class SomeOtherTestFixture{ 
    ... 
} 

Następnie można zastrzec w procesie budowania na serwerze, że wszystkie kategorie się uruchomić i po prostu wymagają swoich twórców uruchomić podzbiór dostępnych kategorii testowych. Jakie kategorie są wymagane do uruchomienia zależy od tego, co zrozumiesz lepiej niż ja. Istotą jest to, że są w stanie przetestować na poziomie jednostki, a serwer wykonuje testy integracyjne.

+1

+1 To prawie to, co robimy w mojej pracy. Na naszym CIS testy jednostkowe są przeprowadzane co każdy test i testy integracyjne raz dziennie. – mezoid

+2

gdzie pracujemy uruchamiamy testy integracji dla każdej kompilacji. im częściej uruchamiasz testy integracyjne, tym lepiej. –

+1

@Ken_Liu - na pewno. Często jest to równoważenie dostępnych cykli procesora na serwerze CI z liczbą zatwierdzeń w danym momencie. To będzie się różnić dla każdego zespołu/środowiska programistycznego. – grenade

3

Czy wykonałeś jakieś pomiary (używając timerów lub podobnych), aby ustalić, gdzie testy spędzają większość czasu?

Jeśli już wiesz, że odtworzenie bazy danych jest dlaczego są one czasochłonne inne podejście byłoby zregenerować bazę raz transakcje użytku zachować stan między testami.Każdy test typu CUD uruchamia transakcję podczas instalacji i wykonuje wycofanie w rozłączeniu. Może to znacznie skrócić czas spędzony na konfiguracji bazy danych dla każdego testu, ponieważ wycofanie transakcji jest tańsze niż odtwarzanie pełnej bazy danych.

+0

Tak, widziałem już ten pomysł wcześniej, ale co, jeśli część testowanego kodu używa samej transakcji (pamiętaj, to są testy integracji)? Wtedy wszystko się zepsuje, więc nie sądzę, aby było to w ogóle praktyczne. – sleske

+1

Jeśli przeprowadzasz jawne zarządzanie transakcjami wewnątrz swoich metod, masz absolutną rację. To podejście sprawdza się najlepiej w przypadkach, gdy do obsługi transakcji używasz aspektów lub proxy. Zastosowaliśmy to podejście w projekcie opartym na Spring, a konfiguracja testu integracji zastąpiła serwer proxy transakcją zarządzaną testem jednostkowym. Pracował jak urok. – henrik

3

Mamy instancję SQL Server Express z tą samą definicją DB, uruchomioną dla każdego komputera jako części środowiska programistycznego. W przypadku uwierzytelniania systemu Windows ciągi połączeń są stabilne - w łańcuchu nie ma nazwy użytkownika/hasła.

Co naprawdę chcielibyśmy zrobić, ale jeszcze nie, zobaczmy, czy możemy uruchomić nasz system na SQL Server Compact Edition, który jest podobny do SQLite z silnikiem SQL Server. Następnie możemy uruchomić je w pamięci i ewentualnie równolegle (z wieloma procesami).

+0

mmm SQL Compact. to * byłoby * słodkie! – grenade

+0

Podobał mi się pomysł! –

13

Zachowaj oddzielne testy szybkiego (jednostkowego) i powolnego (integracyjnego), aby można było je uruchomić oddzielnie. Użyj dowolnej metody grupowania/kategoryzacji testów, która jest dostarczana przez Twoją strukturę testową. Jeśli struktura testowania nie obsługuje grupowania testów, przenieś testy integracji do osobnego modułu, który ma tylko testy integracyjne.

Szybkie testy powinny zająć tylko kilka sekund i powinny mieć wysoki zasięg. Tego rodzaju testy pozwalają programistom na bezwzględną refaktoryzację, ponieważ mogą dokonać niewielkiej zmiany i przeprowadzić wszystkie testy i być pewni, że zmiana niczego nie złamie.

Powolne testy mogą potrwać wiele minut, a upewnią się, że poszczególne komponenty działają prawidłowo. Kiedy programiści dokonują zmian, które mogą przerwać coś, co jest testowane przez testy integracyjne, ale nie testy jednostkowe, powinni przeprowadzić testy integracji przed zatwierdzeniem. W przeciwnym razie powolne testy są uruchamiane przez serwer CI.