Selektor-Wolny Scenariusze Ogorkow

Link: https://bjeanes.com/2010/09/selector-free-cucumber-scenarios

Używam Ogórka, ponieważ prawie pierwszego dnia usłyszałem o tym. Pracowałem nad wieloma projektami, które polegały na jego obecności w celu niezawodnego rozwoju. Dlatego włożyłem wiele wysiłku w udoskonalenie mojej infrastruktury Cucumber, aby to fantastyczne narzędzie było jeszcze lepsze. Zamierzam podzielić się jednym takim kawałkiem kodu, który sprawia, że rozwój z Cucumber jest jeszcze większy.

Problem

Pracowałem nad wieloma aplikacjami internetowymi i, jak jestem pewien, wielu z was wie, dość często rozwój aplikacji internetowej koncentruje się przede wszystkim na funkcjonalności, a interfejs i styl są włączone później. Może się zdarzyć, że klient nie wie jeszcze, czego chce dla swojego projektu lub że chce najpierw skoncentrować swój budżet na prototypowaniu aplikacji.

Jest to w porządku, z wyjątkiem faktu, że zmiana HTML i CSS aplikacji internetowej po opracowaniu wielu funkcji jest fantastycznym sposobem na złamanie wszystkich testów integracyjnych.

Jest to szczególnie prawdziwe, jeśli masz scenariusze podobne do następujących:

When I fill in “Username” with “bjeanes” within And I press “Sign up!” within “.main-panel form#signup-formThen I should see “You have successfully signed up” within “.flash.notice

Problem polega oczywiście na tym, że projektanci mogą zmienić HTML, który kiedyś był .main-panel form#signup-formw coś bardziej seksownego i bardziej semantycznego.

Rozwiązanie

Ten problem nie różni się od już rozwiązanego; wszyscy odeszliśmy od zakodowanych adresów URL, takich jak „/ users / new”, do naszych widoków i scenariuszy Cucumber i zastępując je odpowiednio, new_user_pathi the signup page.

Dlaczego więc nie zastosować tej samej formuły, która paths.rbsłuży do usuwania adresów URL ze scenariuszy do naszej sytuacji za pomocą selektorów?

Oto, co dodam do wszystkich nowych projektów:

# I'm in features/step_definitions/web_ext_steps.rb  When /^(.*) within ([^:"]+)$/ do |step, scope|   with_scope(selector_for(scope)) do     When step   end end  # Multi-line version of above When /^(.*) within ([^:"]+):$/ do |step, scope, table_or_string|   with_scope(selector_for(scope)) do     When "#{step}:", table_or_string   end end  

I:

# I'm in features/support/selectors.rb  module HtmlSelectorsHelper   def selector_for(scope)     case scope     when /the body/       "html > body"     else       raise "Can't find mapping from \"#{scope}\" to a selector.\n" +         "Now, go and add a mapping in #{__FILE__}"     end   end end  World(HtmlSelectorsHelper)

Stosowanie rozwiązania

Mój poprzedni przykład błędnego scenariusza Ogórek staje się teraz:

When I fill in "Username" with "bjeanes" within the sign up form And I press "Sign up!" within the sign up form Then I should see "You have successfully signed up" within the notice flash

A opis selectors.rbprzypadku otrzymuje następujące dodatki:

case   # ...    when /the sign up form/     ".main-panel form#signup-form"   when /the (notice|error|info) flash/     ".flash.#{$1}"    # ... end

Zwróć uwagę, że scenariusz identyfikuje rzeczy na naszej stronie według ich identyfikatorów semantycznych, a nie przez kruche lokalizacje CSS lub XPath, które są podatne na zmiany. Jako bonus terazJeśli kiedy się zmieniają, ścieżki muszą być aktualizowane tylko w jednym miejscu w naszym zestawie testów Ogórek!

Patching Ogórek

Czuję się dość mocno, że CSS i XPath nie należą do naszych plików funkcji, ponieważ nie tylko zachęcają do kruchej próby (jak pokazano powyżej), ale także dlatego, że selektory te są całkowicie nieistotne dla użytkowników końcowych, a to jest rodzaj głównego punktu używanie DSL w języku naturalnym do opisywania naszych testów integracyjnych, tj. zakładanie butów użytkownika.

Naprawdę chciałbym załatać to z powrotem do Cucumber i całkowicie planuję to zrobić, pod warunkiem, że dostanę czas.

Mam czas, a oto moja prośba o ściągnięcie, aby ją połączyć.

Rozszerzanie rozwiązania

Zauważ, że mój HtmlSelectorsHelpermoduł obsługuje tylko selektory CSS. To dlatego, że nigdy nie potrzebowałem XPath w tym kontekście. Zmodyfikowanie moich przykładów byłoby bardzo proste, jednak dzięki kombinacji wielu wartości zwracanych i splat. To ćwiczenie dla czytelnika (lub mnie, jeśli skończy się łataniem Ogórka).

Ostatnie słowo

Przepraszam za długość tego artykułu, ale gratuluję ci, że udało ci się to zrobić przez cały ten czas!

Mam teraz tak wiele pomysłów na blogu, że musiałem stworzyć nową kategorię w Things.app, aby pomieścić je wszystkie. Oznacza to, że będę dążyć do tego, aby w ciągu kilku następnych tygodni uzyskać kilka dodatkowych postów i wyjść, w tym porównanie wydajności różnych enkapsulacji danych dla interfejsów API aplikacji internetowych na iPhone (tj. Czy lepiej jest używać Plists, JSON lub XML?) i post, dlaczego uważam, że powinno być 8 akcji RESTful, a nie 7, które Railsy domyślnie zalecają.