Specs i ScalaTest to dobre narzędzia dla zadowolonych użytkowników, ale różnią się na kilka sposobów. Prawdopodobnie będziesz chciał wybrać jedno z nich jako główne narzędzie testowe w Scali, ale nie musisz rezygnować z drugiego, ponieważ możesz użyć fragmentów obu. Jeśli na przykład podoba Ci się FeatureSpec
składnia ScalaTest i składnia Mockito specyfikacji, możesz umieścić oba pliki jar w swojej ścieżce klas i używać obu jednocześnie. Tutaj spróbuję uchwycić główne różnice w filozofii projektowania, które zauważyłem między specyfikacjami a ScalaTest.
Prawdopodobnie główna różnica filozoficzna między tymi narzędziami polega na tym, że specyfikacje są przeznaczone do rozwoju opartego na zachowaniu (BDD), podczas gdy ScalaTest jest bardziej ogólny. ScalaTest zapewnia cechy, które można łączyć ze sobą, aby uzyskać preferowane zachowanie w klasach testowych, w tym BDD, a także można łatwo zdefiniować własne zachowanie, jeśli chcesz czegoś innego.
ScalaTest podpory BDD poprzez swoje Spec
, FeatureSpec
, WordSpec
, FlatSpec
, i GivenWhenThen
cechy, a także posiada cechy, które można mieszać w celu uzyskać ładny składnię dopasowujący. Jeśli lubisz „powinno”, mieszasz w ShouldMatchers. Jeśli lubisz „must”, wmieszaj się MustMatchers
. Ale jeśli podoba ci się BDD, ale nie lubisz składni dopasowującej, możesz po prostu użyć jednej z cech Spec ScalaTest bez mieszania cechy dopasowującej. Specs ma klasę Specification, którą rozszerzasz i musisz użyć słowa „must” w swoich wyrażeniach dopasowujących. Widoczna tutaj duża różnica filozoficzna polega na tym, że ScalaTest daje dużo więcej możliwości wyboru. Aby ułatwić nawigację po tej przestrzeni wyboru, przedstawiam tutaj drzewo decyzyjne:
http://www.scalatest.org/quick_start
Składnia dopasowania różni się również w przypadku ScalaTest i specyfikacji. W ScalaTest próbowałem zobaczyć, jak daleko mogę się posunąć z notacją operatorową, i skończyło się na wyrażeniach dopasowujących, które czytają bardzo podobnie do zdań angielskich, ze spacjami między słowami. Składnia dopasowująca specyfikacje łączy słowa bardziej ze sobą w przypadku wielbłąda.
Specyfikacje mają więcej dopasowań niż ScalaTest i myślę, że odzwierciedla to różnicę w podejściu do projektowania. Właściwie usunąłem prawdopodobnie 2/3 składni dopasowującej, którą zbudowałem i rozważałem do wydania. Dodam więcej dopasowań w przyszłych wydaniach, ale chciałem się upewnić, że przed dodaniem czegoś użytkownicy rzeczywiście chcieli czegoś. Jednak dopasowania ScalaTest zawierają dynamiczną składnię dopasowującą właściwości, która zajmuje część tego luzu. Na przykład w Specyfikacjach możesz napisać na java.io.File
:
file must beDirectory
Spowoduje to wywołanie isDirectory
i upewnienie się, że to prawda. ScalaTest nie ma obecnie żadnych specjalnych java.io.Files
dopasowań, ale w ScalaTest możesz po prostu użyć dynamicznej kontroli w następujący sposób:
file must be a ('directory)
Za każdym razem, gdy przekażesz symbol w after be
, użyje on odbicia do wyszukania (w tym przypadku) metody lub pola o nazwie directory
lub metody o nazwie isDirectory
. Istnieje również sposób na uczynienie tego statycznym, definiując a BePropertyMatcher
(co zwykle wymaga tylko 2 lub 3 wierszy kodu). Więc zasadniczo w ScalaTest staram się zapewnić większą funkcjonalność przy mniejszym API.
Inna ogólna różnica w podejściu projektowym między specyfikacjami a ScalaTest dotyczy niejawnych konwersji. Domyślnie uzyskujesz tylko jedną niejawną konwersję, gdy używasz ScalaTest, która jest tą, która umieszcza ===
operator na wszystkim. (Jeśli potrzebujesz, możesz „wyłączyć” tę niejawną konwersję za pomocą jednej linii kodu. Jedynym powodem, dla którego musisz to zrobić, jest próba przetestowania czegoś, co ma własny ===
operator, i wystąpi konflikt. ) ScalaTest definiuje wiele innych niejawnych konwersji, ale aby ich użyć, musisz jawnie „zaprosić” je do swojego kodu poprzez dodanie cechy lub wykonanie importu. Kiedy rozszerzasz klasęSpecification
w specyfikacjach myślę, że domyślnie otrzymujesz dziesiątki niejawnych konwersji. Nie jestem pewien, jak bardzo będzie to miało znaczenie w praktyce, ale myślę, że ludzie będą chcieli testować kod, który używa ich własnych implikacji, a czasami może wystąpić konflikt między implikacjami struktury testowej a kodem produkcyjnym. Kiedy tak się stanie, myślę, że łatwiej będzie obejść problem w ScalaTest niż w specyfikacji.
Kolejną różnicą w podejściu projektowym, którą zauważyłem, jest komfort obsługi. Jednym z celów, jakie miałem, było to, że każdy programista patrząc na kod testowy innej osoby, który używa ScalaTest, byłby w stanie odgadnąć, jakie jest znaczenie, bez szukania czegokolwiek w dokumentacji ScalaTest. Chciałem, aby kod klienta ScalaTest był zupełnie oczywisty. Jednym ze sposobów, w jaki cel ten się ujawnił, jest to, że ScalaTest jest bardzo konserwatywny w stosunku do operatorów. W ScalaTest definiuję tylko pięciu operatorów:
===
, co oznacza równe
>
, co oznacza większe niż
<
, mniej niż
>=
, większe lub równe
<=
mniejszy lub równy.
Otóż to. Więc te rzeczy wyglądają jak to, co oznaczają. Jeśli widzisz w kodzie innej osoby:
result should be <= 7
Mam nadzieję, że nie będziesz musiał przechodzić do dokumentacji API, aby odgadnąć, co to <=
oznacza. Z kolei specyfikacje są znacznie bardziej swobodne w przypadku operatorów. Nie ma w tym nic złego, ale to jest różnica. Operatorzy mogą uczynić kod bardziej zwięzłe, ale kompromis jest być może trzeba biec do dokumentacji, gdy znajdziesz takie rzeczy jak ->-
, >>
, |
, |>
, !
, lub ^^^
(które mają specjalne znaczenie w Specs) w pamięci kolegi kodu testowego.
Inną filozoficzną różnicą jest to, że staram się nieco ułatwić w ScalaTest używanie funkcjonalnego stylu, gdy trzeba udostępnić urządzenie, podczas gdy Specs domyślnie kontynuuje tradycję setUp
i tearDown
podejście spopularyzowane przez JUnit, w którym ponownie przypisuje się zmienne przed każdym testem. Jeśli jednak chcesz przetestować w ten sposób, w ScalaTest jest to również bardzo łatwe. Wystarczy dodać BeforeAndAfter
cechę.
Aby uzyskać więcej informacji na temat ScalaTest, możesz obejrzeć prezentację „Get Higher with ScalaTest”, którą wygłosiłem na konferencji Devoxx 2009 tutaj:
http://parleys.com/play/514892260364bc17fc56bde3/chapter0/about