Czy powinienem mieć testy jednostkowe na znane wady?

37

Jeśli mój kod zawiera znaną wadę, która powinna zostać naprawiona, ale nie została jeszcze rozwiązana i nie zostanie naprawiona w bieżącej wersji i może nie zostać naprawiona w dającej się przewidzieć przyszłości, czy powinien zostać przeprowadzony nieudany test jednostkowy tego błędu w zestaw testowy? Jeśli dodam test jednostkowy, (oczywiście) się nie powiedzie, a przyzwyczajenie się do nieudanych testów wydaje się złym pomysłem. Z drugiej strony, jeśli jest to znana wada i znany jest przypadek awarii, wydaje się dziwne, aby trzymać ją z dala od zestawu testów, ponieważ w pewnym momencie należy ją naprawić, a test jest już dostępny.

Martijn
źródło
6
Nie wydaje mi się, tak cholernie, konkretnie pytam o test jednostkowy
Martijn
3
testy na znane wady są znane jako testy regresyjne , nie mają one nic wspólnego z testami jednostkowymi ... a ściślej, to drugie zależy od opinii programisty - twoje pytanie może nie jest w końcu duplikatem, ale raczej ankietą opinii. Szczególnie widoczne jest to, że odpowiedź, którą zaakceptowałeś, w ogóle nie używa terminu „testy jednostkowe”, ale dość rozsądnie nazywa te inaczej „znane testy
zakończone
3
Dzięki Michael, który ma pomóc w jaki sposób oznaczyć takich testów w JUnit, ale naprawdę nie na praktyce badawczej. komar, wciąż nie rozumiem, jak postrzegasz nieudany test jednostkowy jako test regresji. Dostaję również wyraźnie wrogi pasywny / agresywny klimat z twoich komentarzy. Jeśli uważasz, że powinienem zadawać pytania inaczej, powiedz to, ponieważ nie mogę odpowiedzieć na twoje obawy, jeśli wyrazisz je w ten sposób.
Martijn
3
@gnat: szczerze mówiąc, IMHO nie ma znaczenia, czy nazywamy testy tutaj testem „jednostkowym” czy „regresyjnym” - pytanie, które również podłączyłeś, ma inne znaczenie, a odpowiedzi tutaj nie mają zastosowania.
Doc Brown

Odpowiedzi:

51

Odpowiedź brzmi: tak, powinieneś je napisać i powinieneś je uruchomić.

Twoja platforma testowa potrzebuje kategorii „znanych testów zakończonych niepowodzeniem” i powinieneś oznaczyć te testy jako należące do tej kategorii. To, jak to zrobisz, zależy od frameworka.

Co ciekawe, nieudany test, który nagle przechodzi, może być tak samo interesujący, jak test pozytywny, który niespodziewanie się nie powiedzie.

david.pfx
źródło
7
Przykład powyższej funkcji w Unittest frameworku Python: docs.python.org/3.3/library/…
Jace Browning
5

Myślę, że powinieneś mieć test jednostkowy z bieżącym zachowaniem, aw komentarzach dodaj odpowiedni test i właściwe zachowanie. Przykład:

@Test
public void test() {
  // this is wrong, it should be fixed some time
  Assert.assertEquals(2, new Calculator().plus(2,2));
  // this is the expected behaviour, replace the above test when the fix is available
  // Assert.assertEquals(4, new Calculator().plus(2, 2));
}

W ten sposób, gdy poprawka jest dostępna, kompilacja zakończy się niepowodzeniem, zauważając, że test zakończył się niepowodzeniem. Kiedy spojrzysz na test, będziesz wiedział, że zmieniłeś zachowanie i test musi zostać zaktualizowany.

EDYCJA: Jak powiedział kapitan Man, w dużych projektach nie zostanie to naprawione w najbliższym czasie, ale ze względu na dokumentację oryginalna odpowiedź jest lepsza niż nic.

Lepszym sposobem na to jest zduplikowanie bieżącego testu, dzięki czemu klon potwierdzi prawidłową rzecz i @Ignorewyświetli komunikat, np.

@Test
public void test() {
  Assert.assertEquals(2, new Calculator().plus(2,2));
}

@Ignore("fix me, Calculator is giving the wrong result, see ticket BUG-12345 and delete #test() when fixed")
@Test
public void fixMe() {
  Assert.assertEquals(4, new Calculator().plus(2, 2));
}

Jest to zgodne z konwencją w twoim zespole, aby zmniejszyć liczbę @Ignoretestów d. W ten sam sposób, w jaki robisz to, wprowadzając lub zmieniając test w celu odzwierciedlenia błędu, z tym że nie zawiedziesz kompilacji, jeśli jest to krytyczne dla twojego zespołu, tak jak OP powiedział, że poprawka nie zostanie uwzględniona w bieżącej wersji .

Silviu Burcea
źródło
1
To zła rada. Nikt nigdy nie będzie próbował tego naprawić. Ludzie będą otwierać stare testy jednostkowe tylko wtedy, gdy wystąpią problemy z kompilacją lub niepowodzenia testów.
Captain Man
@CaptainMan Zgadzam się, zaktualizowałem swoją odpowiedź, aby zapewnić lepszy sposób informowania zespołu deweloperów o błędzie bez niepowodzenia kompilacji. Twoja opinia była uzasadniona w stosunku do oryginalnej odpowiedzi, którą zamieściłem 3 lata temu, uważam, że obecna odpowiedź jest bardziej odpowiednia. Zrobiłbyś to w inny sposób?
Silviu Burcea
Jest to prawie dokładnie to, co robię w rzadkich przypadkach, gdy z jakiegoś powodu nie mogę teraz naprawić błędu. Bardzo chciałbym usłyszeć, jak radzisz sobie z sytuacją @CaptainMan
RubberDuck
@RubberDuck Nie ma tu naprawdę żadnej idealnej sytuacji (poza naprawieniem błędu teraz haha). Dla mnie przynajmniej widzenie w wynikach testu „10 zaliczonych, 0 nieudanych, 1 pominiętych” jest przynajmniej pewną oznaką, że coś jest podejrzane dla osób, które się z tym nie zaznajomiły. Wolę takie @Ignorepodejście. Używanie tylko komentarza nie wydaje mi się dobrym pomysłem, ponieważ nie sądzę, że ludzie często otwierają testy jednostkowe, aby je sprawdzić (chyba, że ​​zawodzą lub (mam nadzieję), gdy zastanawiają się, dlaczego coś jest ignorowane ).
Captain Man
@RubberDuck Nie ma tu naprawdę żadnej idealnej sytuacji (poza naprawieniem błędu teraz haha). Dla mnie przynajmniej widzenie w wynikach testu „10 zaliczonych, 0 nieudanych, 1 pominiętych” jest przynajmniej pewną oznaką, że coś jest podejrzane dla osób, które się z tym nie zaznajomiły. Wolę takie @Ignorepodejście. Używanie tylko komentarza nie wydaje mi się dobrym pomysłem, ponieważ nie sądzę, że ludzie często otwierają testy jednostkowe, aby je sprawdzić (chyba, że ​​zawodzą lub (mam nadzieję), kiedy zastanawiają się, dlaczego coś jest pomijane ).
Captain Man
3

W zależności od narzędzia testowego możesz użyć funkcji omitlub pend.

Przykład w rubinie:

gem 'test-unit', '>= 2.1.1'
require 'test/unit'

MYVERSION = '0.9.0' #Version of the class you test 


class Test_omit < Test::Unit::TestCase
  def test_omit
    omit('The following assertion fails - it will be corrected in the next release')
    assert_equal(1,2)
  end

  def test_omit_if
    omit_if(MYVERSION < '1.0.0', "Test skipped for version #{MYVERSION}")
    assert_equal(1,2)
  end

end

omitPolecenie przeskakuje do testu, omit_ifłączy ją z badania - w moim przykładzie przetestować numer wersji i wykonać badanie tylko dla wersji gdzie oczekują błąd zostanie rozwiązany.

Dane wyjściowe mojego przykładu to:

Loaded suite test
Started
O
===============================================================================
The following assertion fails - it will be corrected in the next release [test_omit(Test_omit)]
test.rb:10:in `test_omit'
===============================================================================
O
===============================================================================
Test skipped for version 0.9.0 [test_omit_if(Test_omit)]
test.rb:15:in `test_omit_if'
===============================================================================


Finished in 0.0 seconds.

2 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, 2 omissions, 0 notifications
0% passed

Więc moja odpowiedź: Tak, zaimplementuj test. Ale nie myl testera z błędami, ponieważ wiesz, że to się nie powiedzie.

knut
źródło
2

Jeśli błąd jest świeży w twoim umyśle i masz teraz czas, aby napisać test jednostkowy, wtedy napisałbym go teraz i oznaczył jako znany błąd, aby nie zawieść samej kompilacji. Twój moduł śledzenia błędów powinien zostać zaktualizowany, aby odzwierciedlić, że istnieje test jednostkowy, który obecnie kończy się niepowodzeniem dla tego błędu, aby osoba wyznaczona do jego ostatecznej naprawy nie napisała go ponownie. Zakłada to, że błędny kod nie wymaga dużo refaktoryzacji i że API zmienia się znacząco - w takim przypadku lepiej nie pisać testu jednostkowego, dopóki nie będziesz miał lepszego pojęcia, jak należy napisać test .

kaared
źródło
1

Odpowiedź brzmi: NIE MA IMHO. Nie należy dodawać testu jednostkowego błędu, dopóki nie zaczniesz pracować nad poprawką błędu, a następnie nie napiszesz testu (ów), który dowodzi błędu i kiedy test (testy) nie powiedzie się zgodnie z raportem o błędzie ( s) przejdziesz i poprawisz rzeczywisty kod, aby testy przeszły pomyślnie, a błąd zostanie rozwiązany, a następnie zostanie objęty.

W moim świecie mielibyśmy manualny przypadek testowy, w którym QE zawiodły, dopóki błąd nie zostanie naprawiony. A my jako programiści zdawalibyśmy sobie z tego sprawę poprzez ręczne niepowodzenie TC i poprzez śledzenie błędów.

Powód, dla którego nie dodano nieudanych UT, jest prosty. UT są przeznaczone do bezpośredniej informacji zwrotnej i weryfikacji tego, co ja jako programista obecnie pracuję. UT są używane w systemie CI, aby upewnić się, że nie przypadkowo nie uszkodziłem czegoś w innym obszarze kodu dla tego modułu. UTU celowo zawodzący w znanym błędzie IMHO byłby nieproduktywny i po prostu źle.

grenangen
źródło
0

Przypuszczam, że odpowiedź naprawdę brzmi, to zależy. Bądź do tego pragmatyczny. Co zyskujesz teraz dzięki pisaniu? Może w twoim umyśle jest świeży?

Naprawiając błąd, warto udowodnić, że istnieje, pisząc test jednostkowy, który ujawnia błąd. Następnie naprawisz błąd, a test jednostkowy powinien przejść pomyślnie.

Czy masz teraz czas, aby napisać test jednostki, która zakończyła się niepowodzeniem? Czy jest więcej pilnych funkcji lub błędów, które należy zapisać / naprawić.

Zakładając, że masz właściwe oprogramowanie śledzenia błędów z błędem zalogowanych w nim, naprawdę nie ma potrzeby, aby napisać test jednostki niepowodzeniem teraz .

Prawdopodobnie możesz wprowadzić pewne zamieszanie, jeśli wprowadzisz niepomyślny test jednostkowy przed wydaniem, które odbywa się bez poprawki błędu.

ozz
źródło
0

Zazwyczaj czuję się nieswojo z powodu znanych błędów w zestawach testowych, ponieważ zbyt łatwo jest powiększać listę z czasem lub niepowiązane niepowodzenia w tych samych testach, aby można je było uznać za „oczekiwane”. To samo dotyczy okresowych awarii - w kodzie czai się coś złego. Głosowałbym za napisaniem testu dla obecnego kodu i tak, jak powinien być, gdy zostanie naprawiony, ale skomentowany lub wyłączony w jakiś sposób.

Rory Hunter
źródło