Jakie są najlepsze praktyki nazywania klas testów jednostkowych i metod testowania?
Zostało to omówione wcześniej w SO, w Jakie są popularne konwencje nazewnictwa dla testów jednostkowych?
Nie wiem, czy to jest to bardzo dobre podejście, ale obecnie w moich projektów testowych, mam jeden do jednego mapowania między każdej klasie produkcji i klasy testowej, np Product
a ProductTest
.
W moich klasach testowych mam następnie metody z nazwami metod, które testuję, podkreślenie, a następnie sytuację i to, czego się spodziewam, np Save_ShouldThrowExceptionWithNullName()
.
unit-testing
naming-conventions
James Newton-King
źródło
źródło
test<MethodUnderTest>_<state>
np.testPop_emptyStack
Google-styleguide.googlecode.com/svn/trunk/javaguide.html 5.2.3 Nazwy metod. W razie wątpliwości śledź Google.Odpowiedzi:
Podoba mi się strategia nazywania Roya Osherove'a :
[UnitOfWork_StateUnderTest_ExpectedBehavior]
Zawiera wszystkie potrzebne informacje na temat nazwy metody w uporządkowany sposób.
Jednostka pracy może być tak mała jak pojedyncza metoda, klasa lub tak duża jak wiele klas. Powinien reprezentować wszystkie rzeczy, które mają być testowane w tym przypadku testowym i są pod kontrolą.
W przypadku zestawów używam typowego
.Tests
zakończenia, które moim zdaniem jest dość powszechne i takie samo dla klas (kończących się naTests
):[NameOfTheClassUnderTestTests]
Wcześniej używałem Urządzenia jako sufiksu zamiast Testów, ale myślę, że ten drugi jest bardziej powszechny, potem zmieniłem strategię nazewnictwa.
źródło
UpdateManager.Update()
. Mając to na uwadze, zwykle nazywam swoje testyWhenUpdating_State_Behaviour
lubWhenUpdating_Behaviour_State
. W ten sposób testuję określoną akcję klasy, unikając umieszczenia nazwy metody w nazwie testowej. Ale najważniejsze jest to, że muszę mieć pojęcie, jaka logika biznesowa zawodzi, gdy widzę nazwę testu zakończonego niepowodzeniemLubię stosować się do standardu nazewnictwa „Powinien” dla testów podczas nazywania urządzenia testowego po testowanym urządzeniu (tj. Klasie).
Aby zilustrować (używając C # i NUnit):
Dlaczego „powinien” ?
Uważam, że zmusza to autorów testów do nazwania testu zdaniem: „Powinno [być w jakimś stanie] [za / przed / kiedy] [akcja ma miejsce]”
Tak, pisanie „Powinieneś” wszędzie robi się trochę powtarzalne, ale jak powiedziałem, zmusza pisarzy do myślenia we właściwy sposób (może to być dobre dla nowicjuszy). Dodatkowo generalnie daje czytelną angielską nazwę testu.
Aktualizacja :
Zauważyłem, że Jimmy Bogard jest także fanem „powinien”, a nawet ma bibliotekę testów jednostkowych o nazwie Powinien .
Aktualizacja (4 lata później ...)
Dla zainteresowanych moje podejście do testów nazewniczych ewoluowało przez lata. Jeden z problemów ze wzorem „ Powinienem” opisać powyżej, ponieważ nie jest łatwo na pierwszy rzut oka stwierdzić, która metoda jest testowana. W przypadku OOP myślę, że bardziej sensowne jest rozpoczęcie nazwy testu od testowanej metody. W przypadku dobrze zaprojektowanej klasy powinno to skutkować czytelnymi nazwami metod testowych. Teraz używam formatu podobnego do
<method>_Should<expected>_When<condition>
. Oczywiście w zależności od kontekstu możesz zamienić czasowniki Powinien / Kiedy na coś bardziej odpowiedniego. Przykład:Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()
źródło
increasesBalanceWhenDepositIsMade()
.Podoba mi się ten styl nazewnictwa:
i tak dalej. Dla osoby niebędącej testerem naprawdę wyjaśnia, na czym polega problem.
źródło
should
Wolęwill
takOrdersWithNoProductsWillFail()
Will
nie jest właściwie właściwe, a tym samym błędnie mówisz czytelnikowi, że w żaden sposób test nie powiedzie się ... jeśli użyjeszWill
wyrażenia czegoś w przyszłości, co może się nie zdarzyć, jesteś niewłaściwe użycie, aleShould
jest to lepszy wybór, ponieważ wskazuje, że chcesz / chcesz, aby coś się wydarzyło, ale nie zrobiło to lub nie mogło, po uruchomieniu testu informuje, czy nie powiodło się / powiodło, więc nie możesz tego sugerować wcześniej jest to logiczne wytłumaczenie, jakie jest twoje? Dlaczego unikaszShould
?Kent Beck sugeruje:
Jedno urządzenie testowe na „jednostkę” (klasa twojego programu). Urządzenia testowe to same klasy. Nazwa urządzenia testowego powinna brzmieć:
Przypadki testowe (metody urządzeń testowych) mają nazwy takie jak:
Na przykład mając następującą klasę:
Urządzeniem testowym byłoby:
źródło
Nazwy klas . W przypadku nazw urządzeń testowych uważam, że „Test” jest dość powszechny w wszechobecnym języku wielu domen. Na przykład, w dziedzinie inżynierii:
StressTest
i w domenie kosmetyki:SkinTest
. Przykro mi, że nie zgadzam się z Kentem, ale użycie „Test” w moich urządzeniach testowych (StressTestTest
?) Jest mylące.„Jednostka” jest również często używana w domenach. Np
MeasurementUnit
. Czy klasa nazywanaMeasurementUnitTest
jest testem „Measurement” lub „MeasurementUnit”?Dlatego lubię używać przedrostka „Qa” dla wszystkich moich klas testowych. Np
QaSkinTest
aQaMeasurementUnit
. Nigdy nie jest mylony z obiektami domeny, a użycie przedrostka zamiast przyrostka oznacza, że wszystkie urządzenia testowe żyją razem wizualnie (przydatne, jeśli w projekcie testowym masz podróbki lub inne klasy wsparcia)Przestrzenie nazw . Pracuję w C # i utrzymuję moje klasy testowe w tej samej przestrzeni nazw co klasa, którą testują. Jest to wygodniejsze niż posiadanie osobnych testowych przestrzeni nazw. Oczywiście klasy testowe są w innym projekcie.
Nazwy metod testowych . Lubię nazywać moje metody WhenXXX_ExpectYYY. Wyjaśnia to warunek wstępny i pomaga w zautomatyzowanej dokumentacji (a la TestDox). Jest to podobne do porady na blogu testowym Google, ale z większą separacją warunków wstępnych i oczekiwań. Na przykład:
źródło
Używam koncepcji Given-When-Then . Spójrz na ten krótki artykuł http://cakebaker.42dh.com/2009/05/28/given-when-then/ . Artykuł opisuje tę koncepcję w kategoriach BDD, ale można jej również używać w TDD bez żadnych zmian.
źródło
Zobacz: http://googletesting.blogspot.com/2007/02/tott-naming-unit-tests-responsossible.html
W przypadku nazw metod testowych osobiście uważam, że używanie pełnych i udokumentowanych nazw jest bardzo przydatne (wraz z komentarzami Javadoc, które wyjaśniają dalej, co robi test).
źródło
Myślę, że jedną z najważniejszych rzeczy jest zachowanie spójności w konwencji nazewnictwa (i uzgodnienie tego z innymi członkami twojego zespołu). Wiele razy widzę mnóstwo różnych konwencji używanych w tym samym projekcie.
źródło
Niedawno opracowałem następującą konwencję nazywania moich testów, ich klas i zawierających projekty w celu maksymalizacji ich opisów:
Powiedzmy, że testuję
Settings
klasę w projekcie wMyApp.Serialization
przestrzeni nazw.Najpierw utworzę projekt testowy z
MyApp.Serialization.Tests
przestrzenią nazw.W ramach tego projektu i oczywiście przestrzeni nazw utworzę klasę o nazwie
IfSettings
(zapisaną jako IfSettings.cs ).Powiedzmy, że testuję tę
SaveStrings()
metodę. -> Wymienię testCanSaveStrings()
.Po uruchomieniu tego testu wyświetli się następujący nagłówek:
MyApp.Serialization.Tests.IfSettings.CanSaveStrings
Myślę, że to mówi mi bardzo dobrze, co testuje.
Oczywiście użyteczne jest to, że w języku angielskim rzeczownik „Testy” jest taki sam, jak czasownik „testy”.
Nazewnictwo testów nie ma ograniczeń co do kreatywności, dzięki czemu otrzymujemy pełne nagłówki zdań.
Zwykle nazwy testów będą musiały zaczynać się od czasownika.
Przykłady obejmują:
DetectsInvalidUserInput
)ThrowsOnNotFound
)WillCloseTheDatabaseAfterTheTransaction
)itp.
Inną opcją jest użycie „tego” zamiast „jeśli”.
Ten ostatni oszczędza mi jednak naciśnięć klawiszy i dokładniej opisuje to, co robię, ponieważ nie wiem, czy testowane zachowanie jest obecne, ale testuję, czy tak jest.
[ Edytuj ]
Po dłuższym użyciu powyższej konwencji nazewnictwa odkryłem, że prefiks If może być mylący podczas pracy z interfejsami. Tak się składa, że klasa testowa IfSerializer.cs wygląda bardzo podobnie do interfejsu ISerializer.cs na karcie „Otwórz pliki”. Może to być bardzo denerwujące przy przełączaniu między testami, testowaną klasą i jej interfejsem. W rezultacie chciałbym teraz wybrać to na razie jako przedrostek.
Dodatkowo teraz używam - tylko dla metod w moich klasach testowych, ponieważ nigdzie indziej nie jest to uważane za najlepszą praktykę - „_” do oddzielania słów w nazwach metod testowych jak w:
Uważam to za łatwiejsze do odczytania.
[ Zakończ edycję ]
Mam nadzieję, że zrodziło to kilka pomysłów, ponieważ uważam, że testy nazewnicze mają ogromne znaczenie, ponieważ mogą zaoszczędzić dużo czasu, który w innym przypadku poświęciłby na zrozumienie, co robią testy (np. Po wznowieniu projektu po dłuższej przerwie) .
źródło
W VS + NUnit zwykle tworzę foldery w moim projekcie, aby grupować testy funkcjonalne razem. Następnie tworzę klasy urządzeń do testów jednostkowych i nazywam je na podstawie rodzaju testowanej funkcjonalności. Metody [Test] mają nazwy
Can_add_user_to_domain
:źródło
Powinienem dodać, że utrzymywanie testów w tym samym pakiecie, ale w równoległym katalogu do testowanego źródła, eliminuje wzdęcie kodu, gdy tylko będziesz gotowy go wdrożyć bez konieczności wykonywania szeregu wzorców wykluczania.
Osobiście lubię najlepsze praktyki opisane w „JUnit Pocket Guide” ... trudno jest pokonać książkę napisaną przez współautora JUnit!
źródło
nazwa przypadku testowego dla klasy Foo powinna być FooTestCase lub coś podobnego (FooIntegrationTestCase lub FooAcceptanceTestCase) - ponieważ jest to przypadek testowy. na http://xunitpatterns.com/ można znaleźć niektóre standardowe konwencje nazewnictwa, takie jak test, przypadek testowy, urządzenie testowe, metoda testowa itp.
źródło