Jak można TDD wykryć błąd, który można przetestować dopiero po jego naprawieniu?

13

Oto jeden przykład: Moja aplikacja internetowa zawiera elementy do przeciągania. Podczas przeciągania elementu przeglądarka tworzy „obraz widma”. Chcę usunąć „obraz ducha” podczas przeciągania i piszę test tego zachowania.

Mój problem polega na tym, że początkowo nie mam pojęcia, jak naprawić ten błąd, a jedynym sposobem na napisanie testu jest jego naprawienie.

W prostej funkcji, takiej jak let sum = (a, b) => a - b, możesz napisać test, dlaczego sum(1, 2)nie jest równy 3przed napisaniem jakiegokolwiek kodu.

W opisywanym przypadku nie mogę przetestować, ponieważ nie wiem, co to jest weryfikacja (nie wiem, co to powinno być).

Rozwiązaniem opisanego problemu jest:

let dataTransfer = e.dataTransfer
let canvas = document.createElement('canvas');
canvas.style.opacity = '0';
canvas.style.position = 'absolute';
canvas.style.top = '-1000px';
dataTransfer.effectAllowed = 'none';

document.body.appendChild(canvas);
dataTransfer.setDragImage(canvas, 0, 0);

Nie mogłem wiedzieć, że to jest rozwiązanie. Nie mogłem nawet napisać testu po znalezieniu rozwiązania online, ponieważ jedynym sposobem, w jaki mogłem wiedzieć, gdyby naprawdę działało, było dodanie tego kodu do mojej bazy kodu i sprawdzenie za pomocą przeglądarki, czy ma on pożądany efekt. Test musiał zostać napisany po kodzie, co jest niezgodne z TDD.

Jakie byłoby podejście TDD do tego problemu? Czy pisanie testu przed kodem jest obowiązkowe czy opcjonalne?

maximedupre
źródło
2
Przeprowadź swoje badania. Znajdź rozwiązanie ... a następnie napisz test, napraw i refaktoryzuj. Testy nie mają na celu (tylko) weryfikacji działania kodu, ale sprawdzenie w przyszłości kompletnego rozwiązania. Początkowo tworzysz test, aby zakończyć się niepowodzeniem, więc jaką właściwość będziesz testować? To jest jeden sposób na początek.
Juan Carlos Eduardo Romaina Ac
@Kilian Foth: Widzę twoje dobre intencje, zmieniając tytuł pytania, ale twoja edycja unieważniła części mojej odpowiedzi. Co więcej, nowy tytuł IMHO nie pasował dobrze do pytania. Więc cofnąłem się, bez obrazy.
Doc Brown

Odpowiedzi:

26

Kiedy dobrze cię zrozumiałem, po znalezieniu rozwiązania nie możesz nawet napisać wiarygodnego zautomatyzowanego testu dla swojego „widmowego obrazu” , ponieważ jedynym sposobem sprawdzenia poprawności działania jest spojrzenie na ekran i sprawdzenie, czy nie ma widmowego obrazu już więcej. Mam wrażenie, że twój oryginalny nagłówek zadał złe pytanie. Prawdziwe pytanie powinno brzmieć

  • jak automatycznie przetestować określone zachowanie graficznego interfejsu użytkownika?

Odpowiedź brzmi: w przypadku kilku problemów związanych z interfejsem użytkownika nie . Jasne, można spróbować zautomatyzować tworzenie interfejsu użytkownika pokazującego problem i spróbować zaimplementować coś w rodzaju porównania zrzutów ekranu, ale często jest to podatne na błędy, kruche i nieopłacalne.

Szczególnie niemożliwy jest dosłownie projekt interfejsu użytkownika „testowy” lub ulepszenie interfejsu użytkownika za pomocą wcześniej napisanych testów automatycznych. „Kierujesz” projektem interfejsu użytkownika, wprowadzając ulepszenia, pokazując wynik człowiekowi (sobie, niektórym testerom lub użytkownikowi) i prosząc o opinię.

Więc zaakceptuj fakt, że TDD nie jest srebrną kulą, a w przypadku niektórych problemów nadal testowanie ręczne ma większy sens niż testy automatyczne. Jeśli masz systematyczny proces testowania, być może z niektórymi dedykowanymi testerami, najlepszą rzeczą, jaką możesz zrobić, to dodać sprawę do ich planu testów.

Doktor Brown
źródło
Zasadniczo testowanie interfejsu użytkownika nie jest trywialne; możesz przypiąć tj. haszować wygenerowany obraz, możesz symulować / automatyzować, możesz nagrywać makra, możesz użyć zastrzeżonego rozwiązania, możesz korzystać z testów ręcznych, zależy od sytuacji i tego, jak niezbędne jest automatyczne testowanie interfejsu użytkownika dla twojego projektu.
ezoterik
1
@esoterik: tak, i wszystkie te zautomatyzowane techniki są podatne na błędy i kruche, jak już pisałem. Jedyne nie kruche podejście, jakie znam, to testowanie ręczne.
Doc Brown
3
Dzięki za odpowiedź. Myślę, że masz rację, niesłusznie mam nadzieję znaleźć srebrną kulę w TDD. Wydaje się, że nie ma skutecznego sposobu na przetestowanie tego, co chcę przetestować - porównanie zrzutu ekranu i wszystkie powyższe wydają się nie zapewniać wystarczającego zwrotu z inwestycji. W szczególności porównanie zrzutów ekranu wydaje się bardzo czasochłonne i, jak powiedziałeś, podatne na błędy.
maximedupre
1
@maximedupre: znalazłem tę reklamę narzędzia, które próbuje rozwiązać problem, ale mimo to artykuł wydaje się zgadzać z moją odpowiedzią w ogóle.
Doc Brown
5

Jakie byłoby podejście TDD do tego problemu? Czy pisanie testu przed kodem jest obowiązkowe czy opcjonalne?

Jednym ze sposobów jest zastosowanie analogu rozwiązania szczytowego .

James Shore tak to opisał:

Przeprowadzamy małe, izolowane eksperymenty, gdy potrzebujemy więcej informacji.

Podstawowa idea polega na tym, że odkładasz narzędzia projektowe , gdy zastanawiasz się, co się dzieje. Kiedy już masz łożyska, ponownie podnosisz narzędzia projektowe.

Sztuczka: przywracasz wiedzę z dochodzenia do bazy kodu produkcyjnego, ale nie przenosisz kodu . Zamiast tego odtwarzasz go, stosując zdyscyplinowane techniki projektowania.

Konie na kursy.

EDYTOWAĆ:

Jak można zautomatyzować test, jeśli defekt można dostrzec tylko ludzkim okiem?

Chciałbym zasugerować nieco inną pisownię: „Jak możesz zautomatyzować test, jeśli automatyzacja testu nie jest opłacalna?”

Oczywiście odpowiedź brzmi „nie”. Zamiast tego staraj się rozdzielić swoją implementację na dwie części - dużą część, w której testowanie jest opłacalne, i mniejszą część, która jest zbyt łatwa do złamania.

Istnieją dwa sposoby konstruowania projektu oprogramowania: Jednym ze sposobów jest uczynienie go tak prostym, aby oczywiście nie było braków - CAR Hoare

Tak więc podczas pracy z kodem strony trzeciej będziemy mieli bardzo cienką powłokę kodu, która działa jak serwer proxy dla biblioteki strony trzeciej. W teście zamieniamy tę powłokę na „test double”, który weryfikuje protokół , nie martwiąc się, że daje on pożądane efekty.

Do testowania integracji naszych kodów z prawdziwym kodem strony trzeciej korzystamy z innych technik (weryfikacja wizualna, wezwania pomocy technicznej, optymizm ...)

Przydatne może być trzymanie niektórych artefaktów demonstracyjnych, abyś mógł sprawdzić, czy twoje założenia nadal zachowują się podczas aktualizacji biblioteki innej firmy.

VoiceOfUnreason
źródło
Uwielbiam to, co ma do powiedzenia James Shore. Obecnie śledzę screencast www.letscodejavascript.com i dużo się uczę. Przeczytam linki, na które mnie wskazałeś.
maximedupre
Masz rację, czytam więcej o TDD i skokach. Zanim zaczniesz go testować, musisz wiedzieć, jak wygląda kod, który próbujesz sprawdzić. TDD nie może nauczyć cię niczego, czego jeszcze nie wiesz, ale może potencjalnie pokazać ci pewne rzeczy, których musisz się nauczyć, parafrazując Jamesa Shore'a. W związku z tym chciałbym zaproponować dodatkowy krok w TDD: Spike, Test, Fail, Pass, Refactor.
maximedupre
0

Po prostu z innej perspektywy, testowanie wokół interfejsu użytkownika / GUI może być wykonane nieco lepiej w odniesieniu do testów akceptacyjnych (testy zorientowane na przepływ pracy / funkcji biznesowych).

Myślę, że w sieci frameworki takie jak seleniowy webdriver mogą zbliżyć się do prawidłowego testu, ale narzut może być nieco większy i jest to zmiana w przebiegu TDD w odniesieniu do samych testów jednostkowych .

Część, która szczególnie pomogłaby w twojej sytuacji, to coś, co nazywa się Page Object Model ( https://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html ). Osiąga to wyraźne mapowanie GUI w czasie wykonywania na jakiś kod, albo przez nazywanie metod / zdarzeń / członków klasy.

Głównymi argumentami przeciwko temu byłyby koszty ogólne i że koszty te zwykle można było zobaczyć na końcu cyklu rozwoju. Narzutem jest to, że testy wymagają pewnego opakowania, które wydaje się tworzyć zduplikowaną pracę.

W przyszłości będzie to zależeć od kosztów / korzyści zespołu i firmy, więc dyskusja w celu ustalenia oczekiwań i poglądów może być korzystna.

eparham7861
źródło
Ostatnio testowałem e2e / testy funkcjonalne (z selenium webdriver) w TDD, ale koszty ogólne są zdecydowanie zbyt duże, jak powiedziałeś. Nie możesz być wydajnym programistą i robić TDD testami e2e. Korzystałem z POM, ale jedyną korzyścią, jaką mi to dało, była ulepszona architektura w mojej testowej bazie kodu.
maximedupre
Tak, myślę, że bardziej opłacalną opcją, którą widziałem od różnych firm do różnych zespołów, byłoby włączenie bardziej ręcznego procesu SQA, w którym zespół / członek zespołu jest wyznaczony do przeprowadzania tylko ręcznych testów z interfejsu użytkownika. Testy zawierają głównie zrzuty ekranu i dokumentację krok po kroku. Przynajmniej coś takiego dostarczyłoby dowodów na testowanie w kierunku aplikacji.
eparham7861
0

Jak wygląda obraz ducha? Jeśli utworzyłeś atrapę interfejsu użytkownika w jednym znanym kolorze, w którym umieścisz przeciągany element? Czy byłby określony kolor, gdyby istniał obraz ducha?

Następnie test mógłby przetestować brak koloru obrazu widma.

Taki test byłby rozsądnie trwały i wykonalny.

Esben Skov Pedersen
źródło
Wykonalne - tak. Trwałe - zależy. Po prostu zmiana koloru / motywu interfejsu użytkownika może przerwać test / testy, co nie wydaje mi się zbyt trwałe.
Sean Burton
1
Nie przetestowałbyś całego interfejsu użytkownika. Utworzyłbyś fikcyjny interfejs użytkownika dla komponentu przeciągnij i upuść.
Esben Skov Pedersen
Nie jestem pewien, jak osiągnąć to, co sugerujesz. Obraz widma w moim przypadku byłby półkryjącą repliką przeciąganego elementu. Obraz widma cały czas podąża za kursorem podczas przeciągania i upuszczania.
maximedupre
Tak. Będziesz musiał zautomatyzować przeciąganie. To nie byłby test jednostkowy, ale test e2e.
Esben Skov Pedersen