tl; dr
W Pivotal napisaliśmy Cedar, ponieważ używamy i kochamy Rspec w naszych projektach Ruby. Cedar nie ma na celu zastąpienia lub konkurowania z OCUnit; ma na celu wprowadzenie możliwości testowania w stylu BDD do Celu C, podobnie jak Rspec był pionierem w testowaniu w stylu BDD w Ruby, ale nie wyeliminował Test :: Unit. Wybór jednego lub drugiego jest w dużej mierze kwestią preferencji stylu.
W niektórych przypadkach zaprojektowaliśmy Cedar, aby wyeliminować pewne niedociągnięcia w sposobie działania OCUnit dla nas. W szczególności chcieliśmy móc używać debugera w testach, przeprowadzać testy z wiersza poleceń i kompilacji CI oraz uzyskiwać przydatne wyniki tekstowe wyników testów. Te rzeczy mogą być dla ciebie mniej lub bardziej przydatne.
Długa odpowiedź
Wybór między dwoma platformami testowymi, takimi jak Cedar i OCUnit (na przykład), sprowadza się do dwóch rzeczy: preferowanego stylu i łatwości użycia. Zacznę od stylu, ponieważ jest to po prostu kwestia opinii i preferencji; łatwość użycia jest zwykle zbiorem kompromisów.
Względy stylowe wykraczają poza używaną technologię lub język. Testy jednostkowe w stylu xUnit istnieją znacznie dłużej niż testy w stylu BDD, ale ta ostatnia szybko zyskała na popularności, głównie dzięki Rspec.
Podstawową zaletą testowania w stylu xUnit jest jego prostota i szerokie zastosowanie (wśród programistów, którzy piszą testy jednostkowe); prawie każdy język, w którym można rozważyć pisanie kodu, ma dostępne środowisko w stylu xUnit.
Frameworki w stylu BDD mają dwie główne różnice w porównaniu ze stylem xUnit: sposób strukturyzowania testu (lub specyfikacji) oraz składnia do pisania asercji. Dla mnie różnica strukturalna jest głównym wyróżnikiem. Testy xUnit są jednowymiarowe, z jedną metodą setUp dla wszystkich testów w danej klasie testów. Klasy, które testujemy, nie są jednak jednowymiarowe; często musimy testować działania w kilku różnych, potencjalnie sprzecznych kontekstach. Rozważmy na przykład prostą klasę ShoppingCart z metodą addItem: (do celów tej odpowiedzi użyję składni celu C). Zachowanie tej metody może się różnić, gdy wózek jest pusty, w porównaniu do tego, gdy wózek zawiera inne przedmioty; może się różnić, jeśli użytkownik wprowadził kod rabatowy; może się różnić, jeśli określony element może „ zostać wysłane wybraną metodą wysyłki; itd. Gdy te możliwe warunki przecinają się ze sobą, powstaje geometrycznie rosnąca liczba możliwych kontekstów; w testach w stylu xUnit często prowadzi to do wielu metod o nazwach takich jak testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. Struktura frameworków w stylu BDD pozwala ci indywidualnie organizować te warunki, co, moim zdaniem, ułatwia upewnienie się, że obejmuję wszystkie przypadki, a także łatwiej jest znaleźć, zmienić lub dodać indywidualne warunki. Na przykład przy użyciu składni Cedar powyższa metoda wygląda następująco: w testach w stylu xUnit często prowadzi to do wielu metod o nazwach takich jak testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. Struktura frameworków w stylu BDD pozwala ci indywidualnie organizować te warunki, co, moim zdaniem, ułatwia upewnienie się, że obejmuję wszystkie przypadki, a także łatwiej jest znaleźć, zmienić lub dodać indywidualne warunki. Na przykład przy użyciu składni Cedar powyższa metoda wygląda następująco: w testach w stylu xUnit często prowadzi to do wielu metod o nazwach takich jak testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. Struktura frameworków w stylu BDD pozwala ci indywidualnie organizować te warunki, co, moim zdaniem, ułatwia upewnienie się, że obejmuję wszystkie przypadki, a także łatwiej jest znaleźć, zmienić lub dodać indywidualne warunki. Na przykład przy użyciu składni Cedar powyższa metoda wygląda następująco:
describe(@"ShoppingCart", ^{
describe(@"addItem:", ^{
describe(@"when the cart is empty", ^{
describe(@"with no discount code", ^{
describe(@"when the shipping method applies to the item", ^{
it(@"should add the item to the cart", ^{
...
});
it(@"should add the full price of the item to the overall price", ^{
...
});
});
describe(@"when the shipping method does not apply to the item", ^{
...
});
});
describe(@"with a discount code", ^{
...
});
});
describe(@"when the cart contains other items, ^{
...
});
});
});
W niektórych przypadkach można znaleźć konteksty zawierające te same zestawy twierdzeń, które można WYSUSZIĆ przy użyciu współużytkowanych kontekstów przykładowych.
Druga główna różnica między frameworkami w stylu BDD a frameworami w stylu xUnit, asercja (lub „dopasowywanie”), po prostu sprawia, że styl specyfikacji jest nieco ładniejszy; niektórzy ludzie to lubią, inni nie.
To prowadzi do pytania o łatwość użycia. W takim przypadku każda struktura ma swoje zalety i wady:
OCUnit istnieje już znacznie dłużej niż Cedar i jest zintegrowany bezpośrednio z Xcode. Oznacza to, że łatwo jest utworzyć nowy cel testowy i przez większość czasu uruchomienie testów „po prostu działa”. Z drugiej strony okazało się, że w niektórych przypadkach, takich jak uruchomienie na urządzeniu z systemem iOS, uruchomienie testów OCUnit było prawie niemożliwe. Konfigurowanie specyfikacji Cedar wymaga nieco więcej pracy niż testy OCUnit, ponieważ masz bibliotekę i link do niej (nigdy nie jest to łatwe zadanie w Xcode). Pracujemy nad ułatwieniem konfiguracji, a wszelkie sugestie są mile widziane.
OCUnit uruchamia testy w ramach kompilacji. Oznacza to, że nie trzeba uruchamiać pliku wykonywalnego, aby uruchomić testy; jeśli jakiekolwiek testy zakończą się niepowodzeniem, kompilacja nie powiedzie się. To sprawia, że proces uruchamiania testów jest o jeden krok prostszy, a wyniki testów trafiają bezpośrednio do okna wyników kompilacji, co ułatwia ich zobaczenie. Wybraliśmy, aby specyfikacje Cedar były wbudowane w plik wykonywalny, który uruchamiasz osobno z kilku powodów:
- Chcieliśmy mieć możliwość korzystania z debuggera. Uruchamiasz specyfikacje Cedar tak samo, jak inne pliki wykonywalne, więc możesz używać debugera w ten sam sposób.
- Chcieliśmy łatwych testów logowania do konsoli. Możesz użyć NSLog () w testach OCUnit, ale dane wyjściowe trafiają do okna kompilacji, gdzie musisz rozłożyć etap kompilacji, aby go odczytać.
- Chcieliśmy łatwego do odczytania raportowania z testów, zarówno w wierszu poleceń, jak iw Xcode. Wyniki OCUnit ładnie wyświetlają się w oknie kompilacji w Xcode, ale kompilacja z wiersza poleceń (lub jako część procesu CI) powoduje, że wyniki testu przeplatają się z mnóstwem innych wyników kompilacji. Dzięki osobnym fazom kompilacji i uruchamiania Cedar oddziela dane wyjściowe, dzięki czemu wyniki testowe można łatwo znaleźć. Domyślny program uruchamiający Cedar kopiuje standardowy styl drukowania „”. dla każdej mijającej specyfikacji, „F” dla niespełniających specyfikacji itp. Cedar ma również możliwość korzystania z niestandardowych obiektów reportera, dzięki czemu można uzyskać wyniki w dowolny sposób, przy niewielkim wysiłku.
OCUnit to oficjalna platforma testowania jednostek dla Celu C, obsługiwana przez Apple. Apple ma w zasadzie nieograniczone zasoby, więc jeśli chcą coś zrobić, zostanie to zrobione. I w końcu to jest piaskownica Apple, w którą gramy. Jednak drugą stroną tej monety jest to, że Apple otrzymuje codziennie rzędu bajillionów próśb o wsparcie i raportów o błędach. Są wyjątkowo dobrzy w radzeniu sobie z nimi wszystkimi, ale mogą nie być w stanie poradzić sobie z problemami zgłaszanymi natychmiast lub wcale. Cedar jest znacznie nowszy i mniej upieczony niż OCUnit, ale jeśli masz pytania, problemy lub sugestie, wyślij wiadomość na listę mailingową Cedar (cedar-discuss@googlegroups.com), a my zrobimy co w naszej mocy, aby ci pomóc. Ponadto możesz rozwidlić kod z Github (github.com/pivotal/cedar) i dodać wszystko, co Twoim zdaniem brakuje.
Przeprowadzanie testów OCUnit na urządzeniach z iOS może być trudne. Szczerze mówiąc, nie próbowałem tego od dłuższego czasu, więc mogło być łatwiej, ale ostatnim razem po prostu nie mogłem uzyskać testów OCUnit pod kątem działania jakiejkolwiek funkcji UIKit. Kiedy pisaliśmy Cedar, upewniliśmy się, że możemy przetestować kod zależny od UIKit zarówno na symulatorze, jak i na urządzeniach.
Na koniec napisaliśmy Cedar do testów jednostkowych, co oznacza, że tak naprawdę nie jest porównywalny z projektami takimi jak UISpec. Minęło sporo czasu, odkąd próbowałem używać UISpec, ale zrozumiałem, że koncentruje się przede wszystkim na programowym sterowaniu interfejsem użytkownika na urządzeniu z systemem iOS. W szczególności zdecydowaliśmy, że nie będziemy starać się, aby Cedar wspierał tego rodzaju specyfikacje, ponieważ Apple miał (wtedy) ogłosić UIAutomation.