Używając C #, potrzebuję klasy o nazwie, User
która ma nazwę użytkownika, hasło, aktywną flagę, imię, nazwisko, imię i nazwisko itp.
Powinny istnieć metody uwierzytelniania i zapisywania użytkownika. Czy po prostu napiszę test dla metod? I czy muszę się martwić o testowanie właściwości, skoro są one getterami i ustawiającymi .Net?
c#
unit-testing
tdd
nbro
źródło
źródło
Odpowiedzi:
Wiele świetnych odpowiedzi na to pytanie dotyczy również mojego pytania: „ Początek TDD - Wyzwania? Rozwiązania? Zalecenia? ”
Chciałbym również polecić zajrzenie do mojego wpisu na blogu (który był częściowo zainspirowany moim pytaniem), otrzymałem kilka dobrych opinii na ten temat. Mianowicie:
Mam nadzieję, że to oznacza, że możemy odejść od „pobierających i ustawiających” :)
źródło
Przetestuj swój kod, a nie język.
Test jednostkowy, taki jak:
Integer i = new Integer(7); assert (i.instanceOf(integer));
jest użyteczne tylko wtedy, gdy piszesz kompilator i istnieje niezerowa szansa, że twoja
instanceof
metoda nie działa.Nie testuj rzeczy, na których egzekwowaniu możesz polegać. W twoim przypadku skupiłbym się na twoich metodach uwierzytelniania i zapisywania - i napisałbym testy, które upewniłyby się, że mogą z wdziękiem obsługiwać wartości null w dowolnym lub wszystkich tych polach.
źródło
To wciągnęło mnie w testy jednostkowe i bardzo mnie ucieszyło
Właśnie zaczęliśmy przeprowadzać testy jednostkowe. Od dawna wiedziałem, że dobrze będzie zacząć, ale nie miałem pojęcia, jak zacząć i co ważniejsze, co przetestować.
Następnie musieliśmy przepisać ważny fragment kodu w naszym programie księgowym. Ta część była bardzo złożona, ponieważ obejmowała wiele różnych scenariuszy. Część o której mówię to sposób na opłacenie faktur sprzedaży i / lub zakupu już wprowadzonych do systemu księgowego.
Po prostu nie wiedziałem, jak zacząć go kodować, ponieważ było tak wiele różnych opcji płatności. Faktura może wynosić 100 USD, ale klient przelał tylko 99 USD. Być może wysłałeś faktury sprzedaży do klienta, ale dokonałeś również zakupu od tego klienta. Więc sprzedałeś go za 300 $, ale kupiłeś za 100 $. Możesz oczekiwać, że Twój klient zapłaci Ci 200 USD, aby uregulować saldo. A co, jeśli sprzedałeś za 500 USD, ale klient zapłaci Ci tylko 250 USD?
Więc miałem bardzo złożony problem do rozwiązania z wieloma możliwościami, że jeden scenariusz działałby idealnie, ale byłby błędny na innym typie kombinacji faktury / płatności.
Tutaj na ratunek przyszedł test jednostkowy.
Zacząłem pisać (w kodzie testowym) sposób tworzenia listy faktur, zarówno sprzedaży, jak i zakupów. Następnie napisałem drugą metodę tworzenia faktycznej płatności. Zwykle użytkownik wprowadzałby te informacje za pośrednictwem interfejsu użytkownika.
Następnie stworzyłem pierwszą metodę TestMethod, testując bardzo prostą płatność za jedną fakturę bez żadnych rabatów. Cała akcja w systemie miałaby miejsce, gdyby płatność bankowa została zapisana w bazie danych. Jak widać, utworzyłem fakturę, utworzyłem płatność (transakcję bankową) i zapisałem transakcję na dysku. W moich potwierdzeniach umieszczam, jakie powinny być prawidłowe liczby kończące się w transakcji bankowej i na połączonej fakturze. Po transakcji sprawdzam liczbę płatności, kwoty płatności, kwotę rabatu i saldo faktury.
Po zakończeniu testu szedłem do bazy danych i dwukrotnie sprawdzałem, czy jest tam to, czego się spodziewałem.
Po napisaniu testu zacząłem kodować metodę płatności (część klasy BankHeader). W kodowaniu zająłem się tylko kodem, aby wykonać pierwszy test. Nie myślałem jeszcze o innych, bardziej złożonych scenariuszach.
Uruchomiłem pierwszy test, naprawiłem mały błąd, dopóki mój test nie przeszedł.
Potem zacząłem pisać drugi test, tym razem z rabatem od płatności. Po napisaniu testu zmodyfikowałem metodę płatności, aby obsługiwała rabaty.
Testując poprawność z rabatem płatności, testowałem również prostą płatność. Oczywiście oba testy powinny przejść pomyślnie.
Potem przeszedłem do bardziej złożonych scenariuszy.
1) Pomyśl o nowym scenariuszu
2) Napisz test dla tego scenariusza
3) Uruchom ten pojedynczy test, aby sprawdzić, czy przejdzie
4) Gdyby tak się nie stało, debugowałbym i modyfikowałbym kod, dopóki nie przejdzie.
5) Modyfikując kod, wykonywałem wszystkie testy
W ten sposób udało mi się stworzyć moją bardzo złożoną metodę płatności. Bez testów jednostkowych nie wiedziałem, jak rozpocząć kodowanie, problem wydawał się przytłaczający. Dzięki testowaniu mogłem zacząć od prostej metody i rozszerzać ją krok po kroku, mając pewność, że prostsze scenariusze nadal będą działać.
Jestem przekonany, że zastosowanie testów jednostkowych zaoszczędziło mi kilku dni (lub tygodni) kodowania i mniej więcej gwarantuje poprawność mojej metody.
Jeśli później pomyślę o nowym scenariuszu, mogę po prostu dodać go do testów, aby sprawdzić, czy działa, czy nie. Jeśli nie, mogę zmodyfikować kod, ale nadal mam pewność, że inne scenariusze nadal działają poprawnie. Pozwoli to zaoszczędzić dni i dni w fazie konserwacji i naprawiania błędów.
Tak, nawet przetestowany kod może nadal zawierać błędy, jeśli użytkownik robi rzeczy, o których nie pomyślałeś lub uniemożliwiłeś mu zrobienie
Poniżej znajduje się tylko kilka testów, które utworzyłem, aby przetestować moją metodę płatności.
public class TestPayments { InvoiceDiaryHeader invoiceHeader = null; InvoiceDiaryDetail invoiceDetail = null; BankCashDiaryHeader bankHeader = null; BankCashDiaryDetail bankDetail = null; public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date) { ...... ...... } public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount) { ...... ...... ...... } [TestMethod] public void TestSingleSalesPaymentNoDiscount() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("119", true, 1, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); } [TestMethod] public void TestSingleSalesPaymentDiscount() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("119", true, 2, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); } [TestMethod] [ExpectedException(typeof(ApplicationException))] public void TestDuplicateInvoiceNumber() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("100", true, 2, "01-09-2008")); list.Add(CreateSales("200", true, 2, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 3, 300, 0); bankHeader.Save(); Assert.Fail("expected an ApplicationException"); } [TestMethod] public void TestMultipleSalesPaymentWithPaymentDiscount() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("119", true, 11, "01-09-2008")); list.Add(CreateSales("400", true, 12, "02-09-2008")); list.Add(CreateSales("600", true, 13, "03-09-2008")); list.Add(CreateSales("25,40", true, 14, "04-09-2008")); bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount); Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount); Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount); Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance); } [TestMethod] public void TestSettlement() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase bankHeader = CreateMultiplePayments(list, 22, 200, 0); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance); }
źródło
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
Jeśli naprawdę są trywialne, nie przejmuj się testowaniem. Np. Jeśli są zaimplementowane w ten sposób;
public class User { public string Username { get; set; } public string Password { get; set; } }
Jeśli z drugiej strony robisz coś sprytnego (np. Szyfrowanie i odszyfrowywanie hasła w programie pobierającym / ustawiającym), przeprowadź test.
źródło
Zasada jest taka, że musisz przetestować każdy fragment logiki, który napiszesz. Jeśli zaimplementowałeś jakąś konkretną funkcjonalność w getterach i setterach, myślę, że warto je przetestować. Jeśli przypisują wartości tylko do niektórych pól prywatnych, nie przejmuj się.
źródło
To pytanie wydaje się być pytaniem, gdzie można nakreślić granicę, które metody są testowane, a które nie.
Metody ustawiające i pobierające do przypisywania wartości zostały stworzone z myślą o spójności i przyszłym wzroście oraz z przewidywaniem, że po pewnym czasie seter / getter może przekształcić się w bardziej złożone operacje. Sensowne byłoby wprowadzenie testów jednostkowych tych metod, również ze względu na spójność i przyszły rozwój.
Podstawowym celem jest niezawodność kodu, zwłaszcza podczas wprowadzania zmian w celu dodania dodatkowych funkcji. Nie wiem, czy ktokolwiek kiedykolwiek został zwolniony za włączenie seterów / pobierających do metodologii testowania, ale jestem pewien, że są ludzie, którzy chcieliby przetestować metody, które jako ostatnie byli świadomi lub pamiętają, były prostymi opakowaniami ustawiania / pobierania, ale to nie było dłuższa sprawa.
Być może inny członek zespołu rozszerzył metody set / get o logikę, która teraz wymaga przetestowania, ale nie stworzyła testów. Ale teraz Twój kod wywołuje te metody i nie zdajesz sobie sprawy, że uległy zmianie i wymagają dogłębnych testów, a testy, które wykonujesz podczas programowania i kontroli jakości, nie wywołują defektu, ale prawdziwe dane biznesowe z pierwszego dnia wydania tak. uruchomić go.
Dwaj koledzy z drużyny będą teraz debatować nad tym, kto upuścił piłkę i nie przeszedł testów jednostkowych, gdy zestaw / zostanie przekształcony w celu uwzględnienia logiki, która może zawieść, ale nie jest objęta testem jednostkowym. Kolega z zespołu, który pierwotnie napisał zestaw / dostaje, będzie miał łatwiejsze wyjście z tego czystego, jeśli testy zostaną wdrożone od pierwszego dnia na prostym zestawie / otrzymach.
Uważam, że kilka minut „zmarnowanego” czasu na pokrycie WSZYSTKICH metod testami jednostkowymi, nawet trywialnymi, może zaoszczędzić dni bólu głowy i utraty pieniędzy / reputacji firmy oraz czyjejś pracy.
A fakt, że owinąłeś trywialne metody testami jednostkowymi, może być zauważony przez młodszego kolegę z zespołu, gdy zmienią trywialne metody na nietrywialne i skłonią ich do aktualizacji testu, a teraz nikt nie ma kłopotów, ponieważ defekt został powstrzymany od osiągnięcia produkcji.
Sposób, w jaki kodujemy i dyscyplina, którą widać w naszym kodzie, mogą pomóc innym.
źródło
Kolejna odpowiedź kanoniczna. To, jak sądzę, od Rona Jeffriesa:
źródło
Testowanie kodu standardowego jest stratą czasu, ale jak mówi Slavo, jeśli dodasz efekt uboczny do swoich metod pobierających / ustawiających, powinieneś napisać test towarzyszący tej funkcjonalności.
Jeśli tworzysz programowanie sterowane testami, powinieneś najpierw napisać kontrakt (np. Interfejs), a następnie napisać test (y), aby wypróbować ten interfejs, który dokumentuje oczekiwane wyniki / zachowanie. Następnie napisz swoje metody samodzielnie, bez dotykania kodu w testach jednostkowych. Na koniec pobierz narzędzie do pokrycia kodu i upewnij się, że testy sprawdzają wszystkie ścieżki logiki w kodzie.
źródło
Naprawdę trywialny kod, taki jak metody pobierające i ustawiające, które nie mają żadnego dodatkowego zachowania poza ustawieniem pola prywatnego, to przesada. W 3.0 C # ma nawet cukier składniowy, w którym kompilator zajmuje się polem prywatnym, więc nie musisz tego programować.
Zwykle piszę wiele bardzo prostych testów sprawdzających zachowanie, jakiego oczekuję od moich zajęć. Nawet jeśli to proste rzeczy, takie jak dodanie dwóch liczb. Dużo przełączam między pisaniem prostego testu a pisaniem kilku wierszy kodu. Powodem tego jest to, że mogę wtedy zmieniać kod bez obawy, że zepsuję rzeczy, o których nie pomyślałem.
źródło
Powinieneś wszystko przetestować. W tej chwili masz metody pobierające i ustawiające, ale któregoś dnia możesz je nieco zmienić, na przykład walidację lub coś innego. Testy, które napiszesz dzisiaj, zostaną jutro wykorzystane, aby upewnić się, że wszystko działa jak zwykle. Pisząc test, należy zapomnieć o rozważaniach typu „teraz to trywialne”. W kontekście zwinnym lub opartym na testach powinieneś testować zakładając przyszłą refaktoryzację. Czy próbowałeś też wprowadzić naprawdę dziwne wartości, takie jak ekstremalnie długie ciągi lub inne „złe” treści? Cóż, nie powinieneś ... nigdy zakładać, jak bardzo Twój kod może zostać wykorzystany w przyszłości.
Ogólnie uważam, że pisanie obszernych testów użytkowników jest z jednej strony wyczerpujące. Z drugiej strony, chociaż zawsze daje nieoceniony wgląd w to, jak powinna działać Twoja aplikacja i pomaga odrzucić łatwe (i fałszywe) założenia (takie jak: nazwa użytkownika zawsze będzie miała mniej niż 1000 znaków).
źródło
W przypadku prostych modułów, które mogą znaleźć się w zestawie narzędzi lub w projekcie typu open source, należy przetestować jak najwięcej, w tym trywialne metody pobierające i ustawiające. Należy pamiętać, że generowanie testu jednostkowego podczas pisania określonego modułu jest dość proste i proste. Dodawanie metod pobierających i ustawiających to minimalny kod i można je obsługiwać bez większego zastanowienia. Jednak po umieszczeniu kodu w większym systemie ten dodatkowy wysiłek może uchronić Cię przed zmianami w systemie bazowym, takimi jak zmiany typu w klasie bazowej. Testowanie wszystkiego to najlepszy sposób na uzyskanie kompletnej regresji.
źródło
Pisanie testów jednostkowych dla metod pobierających i ustawiających nie zaszkodzi. W tej chwili mogą po prostu wykonywać operacje pobierania / ustawiania pól pod maską, ale w przyszłości możesz mieć logikę walidacji lub zależności między właściwościami, które należy przetestować. Łatwiej jest napisać to teraz, kiedy o tym myślisz, niż pamiętając o modernizacji, jeśli ten czas kiedykolwiek nadejdzie.
źródło
w ogóle, gdy metoda jest zdefiniowana tylko dla pewnych wartości, test dla wartości na i powyżej tej granicy, co jest dopuszczalne. Innymi słowy, upewnij się, że Twoja metoda robi to, co powinna, ale nic więcej . Jest to ważne, ponieważ kiedy ponosisz porażkę, chcesz zawodzić wcześnie.
W hierarchiach dziedziczenia upewnij się, że wykonałeś testy zgodności z LSP .
Testowanie domyślnych metod pobierających i ustawiających nie wydaje mi się zbyt przydatne, chyba że planujesz później przeprowadzić weryfikację.
źródło
cóż, jeśli myślisz, że może się zepsuć, napisz test. Zwykle nie testuję setera / gettera, ale powiedzmy, że tworzysz go dla User.Name, które łączą imię i nazwisko, napisałbym test, więc jeśli ktoś zmieni kolejność na nazwisko i imię, przynajmniej by wiedział zmienił coś, co było testowane.
źródło
Kanoniczna odpowiedź brzmi: „przetestuj wszystko, co może się zepsuć”. Jeśli masz pewność, że właściwości się nie zepsują, nie testuj ich.
A kiedy okaże się, że coś się zepsuło (znajdziesz błąd), oczywiście oznacza to, że musisz to przetestować. Napisz test, aby odtworzyć błąd, obejrzyj, jak się nie udaje, a następnie napraw błąd, a następnie zobacz przebieg testu.
źródło
Jak rozumiem testy jednostkowe w kontekście zwinnego programowania, Mike, tak, musisz przetestować metody pobierające i ustawiające (zakładając, że są one publicznie widoczne). Cała koncepcja testowania jednostkowego polega na testowaniu jednostki oprogramowania, która w tym przypadku jest klasą, jako czarnej skrzynki . Ponieważ metody pobierające i ustawiające są widoczne na zewnątrz, należy je przetestować wraz z uwierzytelnianiem i zapisywaniem.
źródło
Jeśli metody uwierzytelniania i zapisywania używają właściwości, testy pośrednio dotkną właściwości. Tak długo, jak właściwości zapewniają dostęp do danych, jawne testowanie nie powinno być konieczne (chyba że zamierzasz uzyskać 100% pokrycie).
źródło
Testowałbym twoje gettery i setery. W zależności od tego, kto pisze kod, niektórzy ludzie zmieniają znaczenie metod pobierających / ustawiających. Widziałem inicjalizację zmiennych i inną walidację jako część metod pobierających. Aby przetestować tego rodzaju rzeczy, chciałbyś, aby testy jednostkowe obejmowały ten kod jawnie.
źródło
Osobiście „przetestowałbym wszystko, co może się zepsuć”, a prosty getter (lub nawet lepsze właściwości auto) się nie zepsuje. Nigdy nie miałem niepowodzenia prostej instrukcji powrotu i dlatego nigdy nie miałem dla nich testu. Jeśli gettery mają w sobie obliczenia lub jakąś inną formę instrukcji, z pewnością dodałbym dla nich testy.
Osobiście używam Moq jako makiety struktury obiektów, a następnie sprawdzam, czy mój obiekt wywołuje otaczające obiekty tak, jak powinien.
źródło
Musisz pokryć wykonanie każdej metody klasy za pomocą UT i sprawdzić wartość zwracaną przez metodę. Obejmuje to metody pobierające i ustawiające, szczególnie w przypadku, gdy składowe (właściwości) są klasami złożonymi, które wymagają dużej alokacji pamięci podczas ich inicjalizacji. Wywołaj setera za pomocą na przykład bardzo dużego ciągu (lub czegoś z greckimi symbolami) i sprawdź, czy wynik jest poprawny (nie obcięty, kodowanie jest dobre itp.)
W przypadku prostych liczb całkowitych, które również mają zastosowanie - co się stanie, jeśli podasz long zamiast liczby całkowitej? To jest powód, dla którego piszesz UT :)
źródło
Nie testowałbym rzeczywistego ustawienia właściwości. Byłbym bardziej zaniepokojony tym, w jaki sposób te nieruchomości są zaludniane przez konsumentów i czym je zapełniają. Przy każdym testowaniu musisz rozważyć ryzyko z czasem / kosztem testowania.
źródło
Powinieneś testować „każdy nietrywialny blok kodu” używając testów jednostkowych, o ile to możliwe.
Jeśli twoje właściwości są trywialne i jest mało prawdopodobne, że ktoś wprowadzi do nich błąd, to powinno być bezpieczne, aby nie testować ich jednostkowo.
Twoje metody Authenticate () i Save () wyglądają na dobrych kandydatów do testów.
źródło
Najlepiej byłoby, gdybyś zrobił testy jednostkowe podczas pisania klasy. Oto, jak powinieneś to zrobić, korzystając z programowania sterowanego testami. Dodajesz testy podczas implementacji każdego punktu funkcji, upewniając się, że również przypadki brzegowe są objęte testem.
Pisanie testów później jest dużo bardziej bolesne, ale wykonalne.
Oto, co zrobiłbym na twoim stanowisku:
Powinno to dać ładny działający zestaw testów jednostkowych, które będą działać jako dobry bufor przeciwko regresjom.
Jedynym problemem związanym z tym podejściem jest konieczność zaprojektowania kodu aby był testowalny w ten sposób. Jeśli na początku popełnisz jakiekolwiek błędy w łączeniu, nie będziesz w stanie łatwo uzyskać wysokiego pokrycia.
Dlatego tak ważne jest, aby napisać testy przed napisaniem kodu. Zmusza cię do pisania kodu, który jest luźno powiązany.
źródło
Nie testuj działającego (standardowego) kodu. Więc jeśli twoje metody ustawiające i pobierające to po prostu „propertyvalue = wartość” i „return propertyvalue”, nie ma sensu go testować.
źródło
Nawet get / set może mieć dziwne konsekwencje, w zależności od tego, jak zostały zaimplementowane, dlatego należy je traktować jak metody.
Każdy z tych testów będzie musiał określić zestawy parametrów dla właściwości, definiując zarówno dopuszczalne, jak i niedopuszczalne właściwości, aby zapewnić, że wywołania zwracają / kończą się niepowodzeniem w oczekiwany sposób.
Musisz również zdawać sobie sprawę z pułapek bezpieczeństwa, na przykład wstrzyknięć SQL, i przetestować je.
Więc tak, musisz się martwić o testowanie właściwości.
źródło
Uważam, że głupie jest testowanie metod pobierających i ustawiających, gdy wykonują one tylko prostą operację. Osobiście nie piszę skomplikowanych testów jednostkowych, które obejmują dowolny wzorzec użycia. Próbuję napisać wystarczającą liczbę testów, aby upewnić się, że poradziłem sobie z normalnym zachowaniem podczas wykonywania i tyloma przypadkami błędów, jakie przychodzą mi do głowy. Napiszę więcej testów jednostkowych w odpowiedzi na zgłoszenia błędów. Używam testów jednostkowych, aby upewnić się, że kod spełnia wymagania i ułatwić przyszłe modyfikacje. Czuję się o wiele bardziej skłonny do zmiany kodu, gdy wiem, że jeśli coś złamię, to test się nie powiedzie.
źródło
Napisałbym test dla wszystkiego, dla czego piszesz kod, który można przetestować poza interfejsem GUI.
Zwykle każda logika, którą piszę, ma jakąkolwiek logikę biznesową, którą umieszczam w innej warstwie lub warstwie logiki biznesowej.
Wtedy łatwo jest napisać testy na wszystko, co robi coś.
Najpierw napisz test jednostkowy dla każdej metody publicznej w „Warstwie logiki biznesowej”.
Gdybym miał taką klasę:
public class AccountService { public void DebitAccount(int accountNumber, double amount) { } public void CreditAccount(int accountNumber, double amount) { } public void CloseAccount(int accountNumber) { } }
Pierwszą rzeczą, którą zrobiłbym przed napisaniem kodu, wiedząc, że mam te akcje do wykonania, byłoby rozpoczęcie pisania testów jednostkowych.
[TestFixture] public class AccountServiceTests { [Test] public void DebitAccountTest() { } [Test] public void CreditAccountTest() { } [Test] public void CloseAccountTest() { } }
Napisz testy, aby sprawdzić poprawność kodu, który napisałeś, aby coś zrobić. Jeśli powtarzasz zbiór rzeczy i zmieniasz coś w każdym z nich, napisz test, który robi to samo i potwierdź, że faktycznie się wydarzyło.
Istnieje wiele innych podejść, które możesz zastosować, a mianowicie Behavoir Driven Development (BDD), które są bardziej zaangażowane i nie są dobrym miejscem do rozpoczęcia umiejętności testowania jednostkowego.
Tak więc morał tej historii jest taki, że testuj wszystko, co powoduje cokolwiek, o co możesz się martwić, trzymaj testy jednostkowe testujące określone rzeczy, które są małe, wiele testów jest dobrych.
Zachowaj logikę biznesową poza warstwą interfejsu użytkownika, aby łatwo napisać dla nich testy, a będziesz dobry.
Polecam TestDriven.Net lub ReSharper, ponieważ oba łatwo integrują się z Visual Studio.
źródło
Poleciłbym napisanie wielu testów dla metod uwierzytelniania i zapisywania. Oprócz przypadku powodzenia (gdzie podane są wszystkie parametry, wszystko jest poprawnie napisane itp.) Dobrze jest mieć testy dla różnych przypadków awarii (nieprawidłowe lub brakujące parametry, niedostępne połączenia z bazą danych, jeśli dotyczy, itp.). Polecam Pragmatic Unit Testing w C # z NUnit jako odniesieniem.
Jak powiedzieli inni, testy jednostkowe dla metod pobierających i ustawiających są przesadą, chyba że w twoich metodach pobierających i ustawiających istnieje logika warunkowa.
źródło
Chociaż możliwe jest prawidłowe odgadnięcie, gdzie kod wymaga przetestowania, generalnie myślę, że potrzebujesz danych, aby wykonać kopię zapasową tego przypuszczenia. Moim zdaniem testy jednostkowe idą w parze z metrykami pokrycia kodu.
Kod z wieloma testami, ale niewielki zasięg nie został dobrze przetestowany. To powiedziawszy, kod ze 100% pokryciem, ale bez testowania granic i przypadków błędów, również nie jest świetny.
Potrzebujesz równowagi między wysokim pokryciem (minimum 90%) a zmiennymi danymi wejściowymi.
Pamiętaj, aby przetestować pod kątem „śmieci w”!
Ponadto test jednostkowy nie jest testem jednostkowym, chyba że sprawdza błąd. Testy jednostkowe, które nie mają potwierdzeń lub są oznaczone znanymi wyjątkami, po prostu sprawdzą, czy kod nie umiera po uruchomieniu!
Musisz zaprojektować swoje testy tak, aby zawsze zgłaszały awarie lub nieoczekiwane / niechciane dane!
źródło
To sprawia, że nasz kod jest lepszy ... kropka!
Jedną rzeczą, o której my, programiści zapominamy, gdy robimy programowanie sterowane testami, jest cel naszych działań. Jeśli test jednostkowy jest zapisywany po utworzeniu kodu produkcyjnego, wartość testu spada (ale nie jest całkowicie tracona).
W prawdziwym duchu testów jednostkowych testy te nie służą przede wszystkim do „testowania” większej ilości naszego kodu; lub aby uzyskać 90% -100% lepsze pokrycie kodu. Są to drugorzędne korzyści płynące z napisania najpierw testów. Dużą korzyścią jest to, że końce naszego kodu produkcyjnego są napisane znacznie lepiej ze względu na naturalny proces TDD.
Poniższe informacje mogą być pomocne w lepszym przedstawieniu tego pomysłu:
Wadliwa teoria testów jednostkowych
Celowe tworzenie oprogramowania
Jeśli uważamy, że napisanie większej liczby testów jednostkowych pomaga nam uzyskać produkt wyższej jakości, możemy cierpieć z powodu kultu Cargo związanego z rozwojem opartym na testach.
źródło