Jestem stosunkowo nowym programistą i jedną z rzeczy, które powinienem poprawić, jest moja zdolność do testowania własnego kodu. Za każdym razem, gdy opracowuję nową funkcjonalność, bardzo trudno jest podążać wszystkimi możliwymi ścieżkami, aby znaleźć błędy. Staram się podążać ścieżką, na której wszystko działa. Wiem, że jest to dobrze znany problem programistów, ale nie mamy testerów u mojego obecnego pracodawcy, a moi koledzy wydają się być w tym całkiem dobrzy.
W mojej organizacji nie prowadzimy testów opartych na testach ani testów jednostkowych. To by mi bardzo pomogło, ale nie jest prawdopodobne, że to się zmieni.
Jak myślicie, co mógłbym zrobić, aby to przezwyciężyć? Jakiego podejścia używasz podczas testowania własnego kodu?
Odpowiedzi:
Zadaniem kodera jest budowanie różnych rzeczy.
Zadaniem testera jest rozwiązywanie problemów.
Najtrudniejsze jest rozbicie rzeczy, które właśnie zbudowałeś. Osiągniesz sukces tylko przekraczając tę psychologiczną barierę.
źródło
Franciso, poczynię tutaj pewne założenia, oparte na tym, co powiedziałeś:
„Nie przeprowadzamy testów TDD ani testów jednostkowych. Bardzo by mi to pomogło, ale nie jest prawdopodobne, że to się zmieni”.
W związku z tym podejrzewam, że Twój zespół nie przywiązuje dużej wagi do testowania, a zarządzanie nie poświęci czasu, aby zespół mógł uporządkować istniejący kod i ograniczyć dług techniczny do minimum.
Po pierwsze, musisz przekonać swój zespół / kierownictwo o wartości testowania. Bądź dyplomatyczny. Jeśli kierownictwo prowadzi zespół do przodu, musisz pokazać mu pewne fakty, takie jak wskaźnik wad dla każdego wydania. Czas spędzony na naprawianiu defektów można lepiej poświęcić na inne rzeczy, takie jak ulepszenie aplikacji i dostosowanie jej do przyszłych wymagań.
Jeśli zespół i kierownictwo są ogólnie apatyczni w kwestii poprawiania kodu i czujesz się niezadowolony z tego, być może będziesz musiał poszukać innego miejsca do pracy, chyba że możesz ich przekonać, jak już powiedziałem. Problem ten napotykałem w różnym stopniu we wszystkich miejscach, w których pracowałem. Może to być wszystko, od braku odpowiedniego modelu domeny, po słabą komunikację w zespole.
Dbanie o kod i jakość opracowywanego produktu to dobra cecha, którą zawsze chcesz zachęcić innych ludzi.
źródło
Jeśli kodujesz w C, Objective-C lub C ++, możesz użyć CLang Static Analyzer, aby skrytykować swoje źródło bez faktycznego uruchamiania go.
Dostępnych jest kilka narzędzi do debugowania pamięci: ValGrind, Guard Malloc w systemie Mac OS X, Electric Fence w * NIX.
W niektórych środowiskach programistycznych dostępna jest opcja debugowania alokatora pamięci, który wykonuje takie czynności, jak wypełnianie nowo przydzielonych stron i nowo uwolnionych stron śmieciami, wykrywanie zwolnienia nieprzydzielonych wskaźników oraz zapisywanie niektórych danych przed i po każdym bloku sterty, przy czym debugger jest wywoływany, jeśli znany wzorzec tych danych kiedykolwiek się zmieni.
Jakiś facet na Slashdot powiedział, że czerpie wiele korzyści z jednorazowej zmiany linii źródła w debuggerze. „To wszystko” - powiedział. Nie zawsze stosuję się do jego rad, ale kiedy je mam, okazało się to bardzo pomocne. Nawet jeśli nie masz przypadku testowego, który stymuluje nietypową ścieżkę kodu, możesz zmienić zmienną w swoim debuggerze, aby wziąć takie ścieżki, powiedzmy przez przydzielenie pamięci, a następnie za pomocą debugera ustawić nowy wskaźnik na NULL zamiast adres pamięci, a następnie przechodzenie przez procedurę obsługi błędów alokacji.
Używaj asercji - makro assert () w C, C ++ i Objective-C. Jeśli twój język nie zapewnia funkcji potwierdzenia, napisz ją samodzielnie.
Użyj oświadczeń swobodnie, a następnie pozostaw je w kodzie. Wzywam assert () „Test, który ciągle testuje”. Używam ich najczęściej do sprawdzania warunków wstępnych w punkcie wejścia większości moich funkcji. To jedna z części „Programowania na podstawie umowy”, która jest wbudowana w język programowania Eiffla. Druga część to warunki dodatkowe, to znaczy użycie assert () w punktach zwrotnych funkcji, ale uważam, że nie mam z tego tak dużego przebiegu, jak warunki wstępne.
Możesz także użyć aser, aby sprawdzić niezmienniki klas. Chociaż żadna klasa nie jest bezwzględnie wymagana, aby mieć w ogóle niezmienniki, mają ją najbardziej rozsądnie zaprojektowane klasy. Niezmiennik klasy jest pewnym warunkiem, który jest zawsze prawdziwy, poza funkcjami składowymi, które mogą tymczasowo umieścić obiekt w niespójnym stanie. Takie funkcje zawsze muszą przywracać spójność, zanim powrócą.
Zatem każda funkcja członkowska może sprawdzać niezmiennik przy wejściu i wyjściu, a klasa może zdefiniować funkcję o nazwie CheckInvariant, którą dowolny inny kod mógłby wywołać w dowolnym momencie.
Użyj narzędzia pokrycia kodu, aby sprawdzić, które wiersze źródła są faktycznie testowane, a następnie zaprojektuj testy, które stymulują niezbadane wiersze. Na przykład można sprawdzić procedury obsługi niskiej ilości pamięci, uruchamiając aplikację w maszynie wirtualnej, która jest skonfigurowana z małą ilością pamięci fizycznej i bez pliku wymiany lub z bardzo małą.
(Z jakiegoś powodu nigdy nie byłem wtajemniczony, podczas gdy BeOS mógł działać bez pliku wymiany, był bardzo niestabilny w ten sposób. Dominic Giampaolo, który napisał system plików BFS, nalegał, abym nigdy nie uruchamiał BeOS bez wymiany. Nie robię tego zobacz, dlaczego to ma mieć znaczenie, ale musiał to być jakiś artefakt implementacyjny.)
Powinieneś również przetestować odpowiedź swojego kodu na błędy We / Wy. Spróbuj zapisać wszystkie pliki w udziale sieciowym, a następnie odłącz kabel sieciowy, gdy aplikacja jest obciążona dużym obciążeniem. Podobnie odłącz kabel - lub wyłącz sieć bezprzewodową - jeśli komunikujesz się przez sieć.
Jedną z rzeczy, które szczególnie mnie denerwują, są strony internetowe, które nie mają solidnego kodu JavaScript. Strony Facebooka ładują dziesiątki małych plików JavaScript, ale jeśli żaden z nich nie zostanie pobrany, cała strona się zepsuje. Musi istnieć jakiś sposób albo zapewnić pewną tolerancję na błędy, powiedzmy, ponawiając próbę pobrania pliku, albo zapewnić pewien rozsądny efekt rezerwowy, gdy niektóre skrypty nie zostaną pobrane.
Spróbuj zabić swoją aplikację za pomocą debugera lub komendy „kill -9” na * NIX, gdy jest to w trakcie pisania dużego, ważnego pliku. Jeśli twoja aplikacja jest dobrze zaprojektowana, cały plik zostanie zapisany lub w ogóle nie zostanie zapisany, a może jeśli zostanie napisany tylko częściowo, to co zostanie zapisane, nie zostanie uszkodzone, a zapisane dane będą w pełni użyteczne przez aplikacja po ponownym odczytaniu pliku.
bazy danych zawsze mają dyskowe wejścia / wyjścia odporne na awarie, ale prawie żadna inna aplikacja tego nie robi. Chociaż kronikowane systemy plików zapobiegają uszkodzeniu systemu plików w przypadku awarii zasilania lub awarii, w ogóle nie robią nic, aby zapobiec uszkodzeniu lub utracie danych użytkownika końcowego. Odpowiedzialność za to ponoszą użytkownicy aplikacji, ale prawie żadna inna baza danych nie zapewnia odporności na uszkodzenia.
źródło
Kiedy patrzę na testowanie mojego kodu, zwykle przechodzę przez szereg procesów myślowych:
Najłatwiejszym sposobem, aby to zrobić, jest opracowanie moich testów wraz z kodem. Jak tylko napisałem choćby fragment kodu, lubię napisać dla niego test. Próba wykonania wszystkich testów po zakodowaniu kilku tysięcy wierszy kodu o nietrywialnej cyklicznej złożoności kodu jest koszmarem. Dodanie jednego lub dwóch kolejnych testów po dodaniu kilku wierszy kodu jest naprawdę łatwe.
BTW, tylko dlatego, że firma, w której pracujesz i / lub twoi koledzy nie wykonują testów jednostkowych lub TDD, nie oznacza, że nie możesz ich wypróbować, chyba że są one wyraźnie zabronione. Być może użycie ich do stworzenia solidnego kodu będzie dobrym przykładem dla innych.
źródło
Oprócz rad podanych w innych odpowiedziach sugerowałbym użycie narzędzi do analizy statycznej (Wikipedia ma listę wielu narzędzi do analizy statycznej dla różnych języków ) w celu znalezienia potencjalnych wad przed rozpoczęciem testowania, a także monitorowania niektórych wskaźników, które dotyczą testowalność kodu, na przykład złożoność cykliczna , miary złożoności Halsteada oraz spójność i sprzężenie (można je zmierzyć za pomocą wachlarza i wachlarza).
Znalezienie trudnego do przetestowania kodu i ułatwienie testowania znacznie ułatwi pisanie przypadków testowych. Ponadto wczesne wykrywanie wad zwiększy wartość wszystkich praktyk zapewniania jakości (w tym testowania). Odtąd zapoznanie się z narzędziami do testowania jednostek i narzędziami do kpienia ułatwi ci wdrożenie testów.
źródło
Możesz przyjrzeć się możliwemu użyciu Tabeli Prawdy, aby pomóc ci zdefiniować wszystkie potencjalne ścieżki w twoim kodzie. Niemożliwe jest uwzględnienie wszystkich możliwości złożonych funkcji, ale po ustaleniu obsługi wszystkich znanych ścieżek można ustalić obsługę dla przypadku else.
Większość tej szczególnej umiejętności uczy się jednak na podstawie doświadczenia. Po dłuższym korzystaniu z określonych ram zaczniesz widzieć wzorce i cechy zachowania, które pozwolą ci spojrzeć na fragment kodu i zobaczyć, gdzie niewielka zmiana może spowodować poważny błąd. Jedynym sposobem na zwiększenie twoich umiejętności w tym zakresie jest praktyka.
źródło
Jeśli tak jak powiedziałeś, nie potrzebujesz testów jednostkowych, nie widzę lepszego podejścia niż próba ręcznego złamania własnego kodu.
Spróbuj przesunąć swój kod do granic możliwości . Na przykład spróbuj przekazać zmienne do funkcji przekraczającej granice graniczne. Czy masz funkcję, która ma filtrować dane wejściowe użytkownika? Spróbuj wprowadzić różne kombinacje znaków.
Rozważ punkt widzenia użytkownika . Staraj się być jednym z użytkowników, którzy będą korzystać z Twojej aplikacji lub biblioteki funkcji.
źródło
Twoi koledzy muszą być naprawdę wyjątkowi, aby nie śledzić TDD lub testu jednostkowego i nigdy nie generować błędów, więc na pewnym poziomie wątpię, aby sami nie przeprowadzali żadnych testów jednostkowych.
Zgaduję, że twoi koledzy robią więcej testów niż są dopuszczani, ale ponieważ fakt ten nie jest znany zarządowi, organizacja cierpi w wyniku tego, ponieważ zarząd ma wrażenie, że prawdziwe testy nie są przeprowadzane, a liczba błędów jest niska testowanie jest nieważne i nie będzie na niego zaplanowany czas.
Porozmawiaj z kolegami i spróbuj dowiedzieć się, jakie testy jednostkowe przeprowadzają, i naśladuj to. W późniejszym czasie możesz prototypować lepsze sposoby testowania jednostkowego i atrybutów TDD i powoli wprowadzać te koncepcje do zespołu, aby łatwiej je zastosować.
źródło
Powinieneś być w stanie uzyskać zasięg tego, co piszesz, nawet jeśli Twoja organizacja nie ma pełnego zasięgu. Podobnie jak wiele innych rzeczy w programowaniu, doświadczenie powtarzania tego jest jednym z najlepszych sposobów, aby być w tym wydajnym.
źródło
Oprócz wszystkich innych komentarzy, skoro mówisz, że twoi koledzy są dobrzy w pisaniu testów, które nie są szczęśliwe, poproś ich, aby sparowali z tobą kilka testów.
Najlepszym sposobem na naukę jest zobaczenie, jak to się robi i wykorzystanie tego, czego się nauczysz.
źródło
Testowanie czarnej skrzynki! Powinieneś tworzyć swoje klasy / metody z myślą o testowaniu. Twoje testy powinny opierać się na specyfikacji oprogramowania i powinny być jasno określone na diagramie sekwencji (poprzez przypadki użycia).
Teraz, ponieważ możesz nie chcieć tworzyć testów opartych na testach ...
Umieść sprawdzanie poprawności danych wejściowych na wszystkich przychodzących danych; nie ufaj nikomu. Struktura .net ma wiele wyjątków opartych na niepoprawnych argumentach, zerowych referencjach i niepoprawnych stanach. Powinieneś już pomyśleć o użyciu sprawdzania poprawności danych wejściowych w warstwie interfejsu użytkownika, więc jest to ta sama sztuczka w oprogramowaniu pośrednim.
Ale naprawdę powinieneś robić jakieś automatyczne testy; te rzeczy ratują życie.
źródło
Z mojego doświadczenia
Jednostka testowa, jeśli nie jest całkowicie automatyczna, jest bezużyteczna. To bardziej jak Pointy Haired Boss, który można kupić. Dlaczego ?, ponieważ jednostka testowa obiecała zaoszczędzić czas (i pieniądze) automatyzując proces testowy. Ale niektóre narzędzia jednostek testowych robią coś przeciwnego, zmuszają programistów do dziwnej pracy, a inne zmuszają do testowania zbyt długiego. W większości przypadków nie pozwoli to zaoszczędzić godziny pracy, ale zwiększy czas przeprowadzki od kontroli jakości do dewelopera.
UML jest kolejnym niszczycielem czasu. pojedyncza tablica + długopis mogłyby zrobić to samo, taniej i szybko.
BTW, Jak być dobrym w kodowaniu (i unikać błędów)?
a) atomowość. Jedna funkcja, która wykonuje jedno proste (lub kilka pojedynczych zadań). Ponieważ jest łatwy do zrozumienia, łatwo go śledzić i łatwo go rozwiązać.
b) Homologia. Jeśli na przykład wywołujesz bazę danych przy użyciu procedury składowania, wykonaj resztę kodu.
c) Identyfikuj, ograniczaj i izoluj „kod kreacji”. Większość kodu jest w zasadzie kopiuj i wklej. Kod kreatywny jest odwrotny, jest to nowy kod, który działa jak prototyp, może zawieść. Ten kod jest podatny na błędy logiczne, dlatego ważne jest, aby go zmniejszyć, odizolować i zidentyfikować.
d) Kod „cienkiego lodu” to kod, o którym wiesz, że jest „niepoprawny” (lub potencjalnie niebezpieczny), ale nadal potrzebuje, na przykład niebezpiecznego kodu do procesu wielozadaniowego. Unikaj, jeśli możesz.
e) Unikaj kodu czarnej skrzynki, w tym kodu, który nie jest tworzony przez ciebie (na przykład framework) i wyrażenia regularnego. Tego rodzaju kodu łatwo przeoczyć błąd. Na przykład, pracowałem w projekcie przy użyciu Jboss i nie znalazłem ani jednego, ale 10 błędu w Jboss (przy użyciu najnowszej stabilnej wersji), to była PITA, aby je znaleźć. Unikaj szczególnie hibernacji, ukrywa implementację, stąd błędy.
f) dodaj komentarze do swojego kodu.
g) dane wejściowe użytkownika jako źródło błędów. zidentyfikuj to. Na przykład SQL Injection jest spowodowany przez dane wejściowe użytkownika.
h) Zidentyfikuj zły element zespołu i rozdziel przydzielone zadanie. Niektórzy programiści mają skłonność do przekręcania kodu.
i) Unikaj niepotrzebnego kodu. Jeśli na przykład klasa potrzebuje interfejsu, użyj go, w przeciwnym razie unikaj dodawania nieistotnego kodu.
a) ib) są kluczowe. Na przykład miałem problem z systemem, kiedy kliknąłem przycisk (zapisz), nie zapisał formularza. Potem zrobiłem listę kontrolną:
I sidenote
źródło
Tester i programista napotykają problem z różnych punktów widzenia, ale obie role powinny w pełni przetestować funkcjonalność i znaleźć błędy. W centrum uwagi znajdują się różnice między rolami. Klasyczny tester widzi aplikację tylko z zewnątrz (tj. Czarna skrzynka). Są ekspertami w zakresie wymagań funkcjonalnych aplikacji. Oczekuje się, że programista będzie ekspertem zarówno w zakresie wymagań funkcjonalnych, jak i kodu (ale zwykle koncentruje się bardziej na kodzie).
(Zależy od organizacji, czy od programistów wyraźnie oczekuje się, że będą ekspertami w zakresie wymagań. Niezależnie od tego, oczekiwanie jest ukryte - jeśli zaprojektujesz coś złego, to ty - a nie osoba wymagająca - otrzymasz winę).
Ta podwójna rola eksperta obciąża umysł programisty i, z wyjątkiem najbardziej doświadczonych, może obniżać biegłość w wymaganiach. Uważam, że muszę mentalnie zmienić bieg, aby rozważyć użytkowników aplikacji. Oto, co pomaga mi:
źródło
Myślę, że chcesz pracować na dwóch frontach. Jeden z nich ma charakter polityczny, zmuszając twoją organizację do przyjęcia testów na pewnym poziomie (z nadzieją, że z czasem przyjmą więcej). Porozmawiaj z inżynierami ds. Kontroli jakości poza miejscem pracy. Znajdź listy książek o kontroli jakości . Grzebać w odpowiednich artykułach na Wikipedii . Zapoznaj się z zasadami i praktykami kontroli jakości. Nauczenie się tych rzeczy przygotuje cię do zrobienia najbardziej przekonującego przypadku, jaki możesz w swojej organizacji. Istnieją dobre działy zapewniania jakości, które wnoszą znaczącą wartość do ich organizacji.
Jako indywidualny programista stosuj strategie do wykorzystania we własnej pracy. Skorzystaj z TDD , współtworząc kod i testy. Utrzymuj testy jasne i dobrze utrzymane. Na pytanie, dlaczego to robisz, możesz powiedzieć, że zapobiegasz regresjom, a to lepiej organizuje proces myślowy (oba będą prawdziwe). Jest sztuką pisania testowalnego kodu , naucz się go. Bądź dobrym przykładem dla innych programistów.
Częściowo głoszę tu sobie, ponieważ robię o wiele mniej tego rodzaju rzeczy, niż powinienem.
źródło