Czy RSpec i Cucumber naprawdę są tego warte?


12

Wiem, że większość programistów RoR testuje uzależnionych i rozumiem zalety dużego pakietu testowego, ale kiedy zaczynam testowanie, nigdy nie dostaję tak dużego pakietu i zawsze zastanawiam się: „Czy testuję właściwą drogę? Czy jest naprawdę wydajny?”. Często mam do czynienia z testami integracyjnymi testującymi tylko sposób działania aplikacji.

Po pierwsze, czy testowanie naprawdę jest tego warte? Mam na myśli, czy czas poświęcony na pisanie testów naprawdę jest tego wart?

Następnie używam RSpec, niedawno odkryłem Ogórek, używałem go przez jakiś czas, ale nie wiem, czy napisanie tych wszystkich kroków jest naprawdę warte kłopotu? Wiem, że mogę ponownie użyć kroków, ale nigdy nie wiem, czy te kroki są zbyt pełne, czy nie: na przykład korzystam z, Given I am logged in as (.+)ale nie wiem, czy muszę powiedzieć w swojej definicji, Given there's a user called $1ponieważ może zduplikować użytkownika, jeśli kiedykolwiek został utworzony ale nie zawsze warto mieć krok wcześniej Given I am logged in as (.+). Jest to całkiem sporo kodu, który może być może rzadko przydatny. Wydaje mi się, że nie ma nowych błędów w testowanych częściach każdego dnia ... Czy więc Ogórek jest naprawdę opłacalny w porównaniu z RSpec?

Odpowiedzi:


13

Moje „ah-ha!” chwile na temat testowania w Ruby i Railsach nadeszły, kiedy naprawdę usiadłem i przeczytałem ostateczne zasoby na ten temat, książki Rspec i Cucumber . Podzielam twoją początkową pogardę dla Ogórka, ale potem zdałem sobie sprawę, że patrzę na zdjęcie z całkiem niewłaściwego punktu widzenia.

Zasadniczo w Cucumber chodzi o BDD (programowanie oparte na zachowaniu) - używasz Cucumber do planowania swoich funkcji, nad czym będziesz dalej pracować. Hmm, następnie chcesz, aby użytkownicy mogli promować posty na forum lub coś takiego (aby ukraść przykład;)) Więc piszesz coś prostego.

Given I am logged in
And I can see the post "BDD is awesome"
When I vote the post up
Then the post should have one more vote
And the page should show a message thanking me for my vote.

Zauważ, że nie ma tam żadnych odniesień do żadnego powiązanego kodu. To przychodzi w twoich krokach. Podczas refaktoryzacji kodu może być konieczna zmiana definicji kroków, ale zachowanie (funkcja) nigdy nie będzie musiało się zmieniać.

Teraz za każdym razem, gdy uruchamiasz funkcję Ogórek, zostaniesz prawie poprowadzony przez proces testowania tej funkcji za pomocą TDD (programowanie testowe). Odbywa się to na niższym poziomie za pomocą RSpec.

Pierwsze uruchomienie - moja definicja pierwszego kroku jest niezdefiniowana. Skopiuj blok, aby go zdefiniować, powiedzmy user_steps.rb, a nawet session_steps.rb, ponieważ dotyczy on użytkowników i ich sesji. Jak zdefiniujesz, że użytkownik jest zalogowany? Możesz przeprowadzić je przez proces logowania.

Given /^I am logged in$/ do
  visit login_path
  fill_in :name, :with => 'Joe'
  fill_in :password, :with => 'Password'
  click_button 'submit'
end

Powinien być szczęśliwy. Drugi krok.

Given /^I can see the post "(.+)"$/ do |name|
  visit post_path(Post.find_by_name(name))
end

Znowu dość łatwe. Pamiętaj, że jeśli całkowicie przerobimy proces logowania lub sposób, w jaki nasze posty są definiowane i wyświetlane, nie musimy zmieniać tego zachowania. Trzeci krok.

When /^I vote the post up$/ do
  pending 
end 

Tutaj zaczynasz mówić o nowej funkcjonalności, ale nie wiesz jeszcze, jak to będzie działać. Jak głosujesz na post? Możesz kliknąć obraz +1 lub coś, co wysyła wiadomość ajax do kontrolera, który zwraca JSON, lub coś takiego. Teraz możesz przejść do czystych testów Rspec.

  • Przetestuj swój widok, aby upewnić się, że wyświetlany jest obraz +1,
  • Przetestuj swój kontroler, czy zachowuje się poprawnie, gdy otrzyma dane zapytanie we właściwym formacie (zarówno szczęśliwe, jak i nieszczęśliwe ścieżki - co jeśli otrzymany zostanie niepoprawny identyfikator posta? Co się stanie, jeśli użytkownik wykorzysta swoje 25 ocen pozytywnych w ciągu jednego dnia? Czy prawidłowo zwiększa liczbę głosów?)
  • Przetestuj skrypt JavaScript, aby poprawnie reagował, gdy dostanie kroplę JSON w odpowiednim formacie (czy aktualizuje obraz +1, aby pokazać, że został użyty? (Myśląc o Google+ tutaj ...) Czy wyświetla wiadomość z podziękowaniem? Itp. )

Wszystko to nie wpływa na zachowanie - ale kiedy skończysz testowanie na niższym poziomie, wypełnienie definicji kroku głosowania posta będzie banalne. To może być tak proste jak click_link '+1'. Pozostałe etapy to testowanie wyników, które znowu powinny być łatwe do zrobienia. A kiedy skończysz, wiesz, że Twoja funkcja jest kompletna i gotowa. Jeśli konieczne zachowanie się zmieni, możesz ulepszyć swoją funkcję, w przeciwnym razie możesz poprawić kod implementacyjny w sposób całkowicie bezpieczny.

Mam nadzieję, że to ma sens. Wszystko to nie mieści się w mojej głowie, ale myślę, że pokazuje różnicę między BDD i TDD oraz dlaczego Cucumber i RSpec służą różnym potrzebom.


To było dla mnie bardzo pomocne. Ale mam jeszcze jedno pytanie: rozpocząłem projekt przy użyciu RSpec do testowania zarówno kontrolerów, jak i widoków, kod jest w około 90% objęty testami. Czy uważasz, że naprawdę potrzebuję Ogórka i spędzam teraz czas na pisaniu kroków i scenariuszy? To znaczy, i tak mogę to wszystko zrobić z RSpec.
Cydonia7

@ Skydreamer: Prawdopodobnie nie jest to konieczne, ale może to być dobra praktyka. Tak długo, jak robisz testy, jesteś na dobrej drodze :)
sevenseacat

10

Moim zdaniem testowanie jest sztuką. Robiąc TDD (używając RSpec lub innego frameworka) początkowo wydaje się, że „marnujesz swój czas”. Jest to zrozumiałe, ponieważ nie piszesz żadnego kodu produkcyjnego.

Jednak zaczynasz dostrzegać korzyści z TDD, gdy musisz ulepszyć bazę kodu, jednocześnie upewniając się, że wszystko inne nadal działa. TDD pomaga wychwycić błędy regresji jak najwcześniej. Dzięki temu zaoszczędziłem wiele dni pracy, ponieważ skoncentrowałem się na testach, które wykazały moje błędy.

Ponadto posiadanie testów może być korzystne dla recenzji kodu, ponieważ recenzent może zobaczyć, jakie scenariusze testujesz i jak ma być używany kod.

Gdy zaczniesz się huśtać w TDD, robienie czegokolwiek innego będzie złe.


2
+1, choć mówi z doświadczenia, „wejście w huśtawkę TDD” jest sam w sobie herkulesowym przedsięwzięciem i jest bardzo trudne dla większości programistów.
Wayne Molina

@Wayne M: Zgoda. Wsiadanie do rowka TDD jest trudne, ale korzyści są ogromne. :)
David Weiser,

Ciężko jest to lekko ująć ... od lat próbuję obejść to :)
Wayne Molina

Och tak, to jest warte wysiłku.
sevenseacat

2

Uważam, że masz rację na froncie Ogórka. Pisanie tych wszystkich kroków jest dużym problemem, a korzyści nie uzasadniają bólu. Napisałem obszernie o sześciu wadach używania Ogórka tutaj: Po co zawracać sobie głowę testowaniem ogórka?

Testy jednostkowe i regularne testy integracyjne, wykonywane za pomocą Rspec lub Test :: Unit, mają wiele sensu, ale na szczęście są one znacznie szybsze niż testy ogórkowe. Na przykład możesz użyć czystego Ruby zamiast walczyć z nieprzyzwoitą i niezręczną składnią Korniszona.


2
Mogę całkiem bezpiecznie powiedzieć, że nie zgadzam się z każdym z twoich punktów na temat testowania ogórka. * Nie psuje dobrych edytorów tekstu (mój gedit podświetli i autouzupełnia go w porządku) * Nie powinieneś kopiować żadnej konfiguracji testowej z istniejącej konfiguracji Rspec do konfiguracji Cucumber (dwa zestawy testów działają na bardzo różnych poziomach szczegółowości), * jeśli nie możesz być konsekwentny w nazywaniu swoich stron, co nie jest winą Ogórka (Railsy nie pozwolą ci nazywać różnych tras w różnych dniach, więc dlaczego Ogórek?) (ciąg dalszy)
sevenseacat

1
* Mówisz, jaka jest konwencja na temat plików kroków, ale potem mówisz, że nie wiesz, gdzie szukać konwencji? Dlaczego promowanie postu miałoby być inne niż post_steps.rb? * Twoje funkcje nie powinny być kodem, więc nie ma znaczenia dla tekstu - twoje funkcje są dokumentacją tego, jak zachowuje się Twoja aplikacja; * I na koniec, mogę jedynie krytykować „zniechęcające ponowne użycie kodu” , gdy robisz to źle .
sevenseacat

2

Osobiście w to wierzę RSpec testing is a definite must. Powiedzmy na przykład, że chcesz napisać nową funkcję, która ma również odniesienie do innej funkcji, a do tej funkcji można odwoływać się za pomocą innych modułów lub metod. Jak więc upewnić się, że to, co piszesz, nie psuje żadnej innej części aplikacji?

Załóżmy, że masz dużą aplikację i że zakodowałeś coś trywialnego w porównaniu z ogólną aplikacją. Czy przetestujesz ponownie całą aplikację, klikając każdy link w aplikacji, aby upewnić się, że działa za każdym razem, gdy zmieniasz pojedynczy wiersz kodu?

Uważam jednak, że testowanie ogórka nie jest koniecznością. Myślę, że testowanie integracji przy użyciu samego RSpec ma większy sens, dopóki klient nie sprawdzi testów. Co z mojego doświadczenia jest rzadkie. Jeśli twój zespół składa się wyłącznie z programistów, myślę, że powinieneś raczej zastąpić kroki Ogórka do testowania funkcji RSpec. I myślę, że po RSpec 3 DSL testy są dość czytelne.

Np .:

Definicja kroku ogórka:

Given /^I am logged in$/ do
  visit login_path
  fill_in :name, :with => 'Joe'
  fill_in :password, :with => 'Password'
  click_button 'submit'
end

Test funkcji RSpec:

feature 'Given the user is logged in' do
      visit login_path
      fill_in :name, :with => 'Joe'
      fill_in :password, :with => 'Password'
      click_link_or_button 'submit'
end

Myślę, że zamiast funkcji Cucumber, funkcje RSpec robią to samo bez dodatkowego bólu głowy związanego z pisaniem kolejnych definicji kroków.

Poza tym jest to wyłącznie twoja własna preferencja.

Mam nadzieję, że to pomoże ci trochę zrozumieć.


0

Moim zdaniem najpierw należy rozróżnić praktyki i konkretne ramy. Ogórek to nie BDD, RSpec to nie TDD.

Jeśli chcesz przetestować system RSpec jako dobre narzędzie, możesz wykonać TDD lub BDD za pomocą RSpec, w rzeczywistości TDD i BDD są tym samym. Ktoś mówi: „BDD to TDD zrobione poprawnie” i całkowicie się z tym zgadzam, BDD przede wszystkim chodzi o testowanie cech / zachowań zamiast testowania metod / klas. W rzeczywistości TDD, którą opisuje Kent Beck o swoich funkcjach, ale BDD pomaga wielu ludziom zrozumieć tę kluczową różnicę i jej wielki wkład od Dana Northa dla społeczności programistów.

Użyj Ogórka, jeśli uważasz, że potrzebujesz lepszego narzędzia do komunikowania się z ludźmi biznesu, na przykład, jeśli ogórek pozwala, aby ludzie biznesu lub właściciel produktu pomagali zespołowi w pisaniu lub korygowaniu scenariuszy. Inni ludzie lubią ogórki, ponieważ te scenariusze są naprawdę dobrą dokumentacją systemu na żywo, jeśli uważasz, że potrzebujesz tego typu dokumentacji, spróbuj ogórka.

W podsumowaniu:

  • Jeśli chcesz zrobić TDD / BDD samodzielnie lub w zespole -> spróbuj RSpec
  • Jeśli chcesz mieć lepszy sposób komunikowania się z biznesem dzięki Historiom użytkowników i scenariuszom -> spróbuj ogórka
  • Jeśli chcesz na żywo dokumentować funkcje swojego systemu -> spróbuj ogórka.

Oczywiście dwa ostatnie wiążą się z wysokimi kosztami, musisz ocenić, czy naprawdę tego potrzebujesz, i warte wysiłku, to oczywiście zależy całkowicie od twojego projektu i twojego środowiska oraz od decyzji.

Ale zawsze pamiętaj, że RSpec i Cucumber to tylko narzędzia, a narzędzia rozwiązują konkretne problemy, jaki problem chcesz rozwiązać ?, zadaj sobie to pytanie i prawdopodobnie jesteś w lepszej pozycji, aby wybrać odpowiednie narzędzie. Lepszym programistą jest podejmowanie tych decyzji, a nie korzystanie z frameworka / narzędzia / biblioteki / technologii X lub Y.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.