Czy powinny istnieć testy jednostkowe złożonych wyrażeń regularnych?

34

Czy powinienem pisać testy jednostkowe dla złożonych wyrażeń regularnych w mojej aplikacji?

  • Z jednej strony: są łatwe do przetestowania, ponieważ format wejściowy i wyjściowy jest często prosty i dobrze zdefiniowany, i często mogą stać się tak złożone, więc ich testy są szczególnie cenne.
  • Z drugiej strony: one same rzadko stanowią część interfejsu niektórych jednostek. Lepiej byłoby przetestować interfejs i zrobić to w sposób, który pośrednio testuje wyrażenia regularne.

EDYTOWAĆ:

Zgadzam się z doktorem Brownem, który w swoim komentarzu zauważa, że ​​jest to szczególny przypadek jednostkowych testów komponentów wewnętrznych .

Ale ponieważ wyrażenia regularne komponentów wewnętrznych mają kilka specjalnych cech:

  1. Wyrażenie jednowierszowe może być naprawdę złożone, bez oddzielnego modułu.
  2. Regeksy odwzorowują dane wejściowe na dane wyjściowe bez żadnych skutków ubocznych, a zatem są naprawdę łatwe do osobnego przetestowania.
Lii
źródło
12
„sami rzadko stanowią część interfejsu jakiejś jednostki”. - jeśli twoje klasy mają ciekawy kod ukryty głęboko pod interfejsem, podziel je. To jest przykład tego, jak myślenie o tess może poprawić projektowanie.
Nathan Cooper
3
To samo pytanie w bardziej ogólny sposób: które elementy wewnętrzne powinny być testowane jednostkowo? Zobacz programmers.stackexchange.com/questions/16732/…
Doc Brown
W pewnym sensie powiązane, patrz Regex101. Mają sekcję do pisania testów jednostkowych dla twojego wyrażenia regularnego. Na przykład: regex101.com/r/tR3mJ2/2
David mówi Przywróć Monikę
3
Zastrzeżenie - ten komentarz jest moją skromną opinią: 1 przede wszystkim uważam, że złożone wyrażenia regularne są czystym złem - zobacz także blog.codinghorror.com/... 2 prawdziwa wartość testowania takich wyrażeń pojawia się, gdy testujesz je na dużej bazie danych dane blog.codinghorror.com/testing-with-thetforce 3 Mam dziwne przeczucie, że testy te nie są dokładnie testami jednostkowymi
Boris Treukhov

Odpowiedzi:

101

Odkładając na bok dogmatyzm, prawdziwe pytanie brzmi, czy zapewnia ono wartość jednostkowym testom złożonych wyrażeń regularnych. Wydaje się całkiem jasne, że zapewnia wartość (niezależnie od tego, czy wyrażenie regularne jest częścią interfejsu publicznego), jeśli wyrażenie regularne jest wystarczająco złożone, ponieważ pozwala na znajdowanie i odtwarzanie błędów i zapobieganie regresjom.

JacquesB
źródło
25
+1, chociaż jeśli to jest wyrażenie regularne kompleks dość, że jest to problem, to prawdopodobnie ma sens, aby przenieść go w „otoki” jednostki z odpowiednimi metodami ( isValid, parse, tryParse, lub cokolwiek, zależnie dokładnie jak to jest używany), tak że kod klienta nie musi wiedzieć, że jest obecnie implementowany za pomocą wyrażenia regularnego. Jednostka owijająca miałaby wówczas szczegółowe testy, które - znowu - nie musiałyby znać aktualnej implementacji. Testy te oczywiście de facto testują regex, ale w sposób niezależny od implementacji.
ruakh
1
Reg ex to program, choć w wyspecjalizowanym i bardzo zwięzłym języku. Jako takie, testowanie jest odpowiednie dla nietrywialnych wyrażeń ... Z pewnością kod wywołujący wyrażenie powinien zostać przetestowany, co może pośrednio przetestować zarezerwowane.
keshlam
6
@ruakh Dobrze powiedziane. Zaletą klasy otoki dla wyrażenia regularnego jest to, że można ją łatwo zastąpić zwykłym kodem, jeśli będzie to konieczne. Kod ze złożonymi wejściami / wyjściami powinien zawsze mieć testy jednostkowe, ponieważ bez niego debugowanie jest niezwykle trudne. Jeśli potrzebujesz zapoznać się z dokumentacją, aby zrozumieć efekty kodu, powinien on mieć testy jednostkowe. Jeśli jest to szybkie odwzorowanie 1: 1, takie jak konwersja typów, nie ma problemu. Regeksy szybko przekraczają ten punkt wymagania dokumentów.
Aaron3468
4
@Lii: Regexes nie zasługuje na żadne specjalne traktowanie. Wyrażenie regularne jest w tym przypadku jednostką, więc testujemy je.
JacquesB,
1
@ruakh Miałem właśnie napisać odpowiedź na ten temat. Zgadzam się, że użycie wyrażenia regularnego jest szczegółem implementacji. Liczy się to, że rzeczy sprawdzają się, kiedy powinny, i nie sprawdzają, kiedy powinny. Przetestuj FooValidatorjego wejścia i wyjścia, a następnie nie martw się o to, jak to się robi. ++
RubberDuck
21

Regex może być potężnym narzędziem, ale nie jest to narzędzie, któremu można zaufać, jeśli nadal będzie działać, jeśli wprowadzisz nawet niewielkie zmiany w złożonych wyrażeniach regularnych.

Stwórz więc wiele testów dokumentujących przypadki, które powinien obejmować. I stwórz wiele testów, które dokumentują przypadki, które powinny zakończyć się niepowodzeniem, jeśli zostaną użyte do weryfikacji.

Ilekroć potrzebujesz zmienić wyrażenia regularne, dodajesz nowe przypadki jako testy, modyfikujesz wyrażenia regularne i mam nadzieję na najlepsze.

Gdybym był w organizacji, która generalnie nie używałaby testów jednostkowych, nadal napisałbym program testowy, który przetestowałby każde wyrażenie regularne, którego byśmy użyli. Zrobiłbym to nawet w swoim własnym czasie, gdybym musiał, moje włosy nie muszą tracić więcej koloru.

Zgięty
źródło
3

Wyrażenia regularne są kodem wraz z resztą aplikacji. Powinieneś przetestować, czy kod ogólnie robi to, czego oczekujesz. Ma to kilka celów:

  • Testy są dokumentacją wykonalną. Wyraźnie pokazuje, czego potrzebujesz do wykonania kodu. Jeśli jest testowany, jest to ważne.
  • Przyszli opiekunowie mogą być pewni, że jeśli je zmodyfikują, testy zapewnią, że zachowanie się nie zmieni.

Ponieważ istnieje dodatkowa przeszkoda do pokonania, ponieważ kod w innym języku jest osadzony z resztą, najprawdopodobniej powinieneś poświęcić tę dodatkową uwagę na korzyść konserwacji.

Thorbjørn Ravn Andersen
źródło
1

Krótko mówiąc, powinieneś przetestować swoją aplikację, kropka. Niezależnie od tego, czy testujesz wyrażenie regularne za pomocą automatycznych testów, które uruchamiają go w oderwaniu, jako część większej czarnej skrzynki, czy też po prostu majstrujesz przy niej ręcznie, jest to kwestia dodatkowa, o której musisz upewnić się, że działa.

Główną zaletą testów jednostkowych jest oszczędność czasu. Pozwalają Ci przetestować tę rzecz tyle razy, ile chcesz teraz lub w dowolnym momencie w przyszłości. Jeśli istnieje jakikolwiek powód, aby sądzić, że wyrażenie regularne zostanie w dowolnym momencie poddane refaktoryzacji, poprawione, otrzyma więcej ograniczeń itp., To tak, prawdopodobnie potrzebujesz testów regresji, a kiedy to zmienisz, będziesz musiał przejść przez godzinę zastanowienia się nad wszystkimi przypadkami krawędzi, żebyś go nie złamał. To lub nauczysz się żyć ze strachem przed kodem i po prostu nigdy go nie zmieniaj.

sara
źródło
3
Zrozumiałem zasadę; jeśli potrzebuję dokumentów do napisania i sprawdzenia kodu, będę potrzebował testu jednostkowego. Zaoszczędzili mi wielu bólów głowy, wyłapywania zerowych wskaźników, braku typów i niepoprawnych wyników. Dają również użytkownikowi końcowemu możliwość naprawy kodu zgodnie ze specyfikacją przy minimalnym wysiłku, gdy nieuchronnie się zepsuje.
Aaron3468
-1

Z drugiej strony: one same rzadko stanowią część interfejsu niektórych jednostek. Lepiej byłoby przetestować interfejs i zrobić to w sposób, który pośrednio testuje wyrażenia regularne.

Myślę, że sam na to odpowiedziałeś. Regeksy w jednostce są najprawdopodobniej szczegółem implementacji.

To, co jest potrzebne do testowania SQL, prawdopodobnie dotyczy także wyrażeń regularnych. Kiedy zmieniasz kawałek SQL, prawdopodobnie uruchamiasz go ręcznie przez jakiegoś klienta SQL, aby sprawdzić, czy daje to, czego oczekujesz. To samo dotyczy zmiany wyrażenia regularnego. Używam narzędzia wyrażenia regularnego z przykładowymi danymi wejściowymi, aby sprawdzić, czy robi to, czego oczekuję.

Przydaje mi się komentarz w pobliżu wyrażenia regularnego z próbką tekstu, który powinien pasować.

Christiaan
źródło
Kiedy zmieniasz fragment SQL, prawdopodobnie uruchamiasz go ręcznie przez jakiegoś klienta SQL, aby sprawdzić, czy daje to to, czego oczekujesz. ” Ale ten rodzaj odpowiedzi odpowiada na pytanie w inny sposób ... Jeśli potrzebuję lub myślę, że warto ręcznie przetestuj wyrażenia regularne, a zamiast tego powinienem wykonać test jednostkowy. Właśnie to sprawia, że ​​decyzja jest trudna!
Lii
To naprawdę zależy. To, czego oczekujesz od testów jednostkowych, to możliwość wprowadzania zmian. Jak często zmieniasz określone wyrażenie regularne? Jeśli odpowiedź jest często, to zdecydowanie stwórz dla niej test.
Christiaan,
8
Wszystkie inne rzeczy są jednakowe, lepiej mieć automatyczny test niż „test ręcznie”.
Robert Harvey
1
Dlaczego nie przetestowałbyś wyrażenia regularnego przy użyciu automatyzacji?
Tony Ennis,
1
Jest to część metody i wszystko, co próbowałem powiedzieć, to to, że nie ma potrzeby szczegółowego testowania wyrażenia regularnego, jeśli już testujesz tę metodę. Ale jeśli to zrobisz, prawdopodobnie lepiej wyodrębnić wyrażenie regularne do osobnej funkcji, którą testujesz w izolacji.
Christiaan,
-5

Jeśli musisz zapytać, odpowiedź brzmi tak.

Załóżmy, że pojawi się jakiś FNG i myśli, że może „poprawić” regex. Teraz jest FNG, więc automatycznie idiotą. Dokładnie taka osoba, która nigdy nie powinna dotykać twojego cennego kodu w żadnym wypadku! Ale może jest spokrewniony z PHB czy coś takiego, więc nic nie możesz zrobić.

Tyle że wiesz, że PHB pociągnie cię za kopanie i krzyczenie z powrotem do tego projektu, aby „może dać facetowi kilka wskazówek na temat tego, jak popełniłeś ten bałagan”, gdy wszystko pójdzie źle. Zapisujesz więc wszystkie przypadki, które dokładnie rozważyłeś , budując swoje piękne dzieło ekspresji.

A ponieważ spisałeś je wszystkie, masz dwie trzecie drogi do posiadania zestawu przypadków testowych, ponieważ - spójrzmy prawdzie w oczy - przypadki testowe wyrażeń regularnych są trudne do uruchomienia po zbudowaniu frameworka.

Teraz masz zestaw warunków brzegowych, alternatyw i oczekiwanych rezultatów. I nagle przypadki testowe stały się dokumentacją tak, jak obiecano we wszystkich tych postach na moim blogu Agile. Wskazujesz tylko FNG, że jeśli jego „poprawa” nie przejdzie istniejących przypadków testowych, to nie jest to duża poprawa, prawda? I gdzie są proponowane przez niego nowe przypadki testowe, które wykazują pewien problem z oryginalnym kodem, który ponieważ działa, nie musi być modyfikowany, nigdy !!!

Austin Hastings
źródło
3
co to jest FNG? Nie wydaje mi się to złą odpowiedzią, ale brakuje mi definicji FNG (bo googlin po prostu daje wyniki, które nie są ze sobą powiązane, więc może ta odpowiedź została po prostu odrzucona z powodu FNG?)
GameDeveloper
1
Podejrzewam, że Google zabrał cię we właściwe miejsce. ;-) ( en.wikipedia.org/wiki/FNG_syndrome )
Austin Hastings
O ile nie jesteś absolutnym geniuszem programistycznym, bardziej doświadczeni programiści zastanowią się nad tym, co robisz, jak patrzysz na nowego faceta. Możesz rozważyć bycie bardziej pokornym.
Thorbjørn Ravn Andersen