Jednostka 6 / 11

Generowanie i testowalność testów jednostkowych: solidne testowanie za pomocą sztucznej inteligencji

Zyski:

  • Możliwość uniemożliwienia sztucznej inteligencji akceptowania błędnego zachowania jako „poprawnego” poprzez obliczenie wartości oczekiwanej w testach jednostkowych niezależnie od reguły akceptacji
  • Możliwość drukowania szybkich, niezależnych i powtarzalnych testów poprzez zastosowanie zasad AAA i FIRST oraz wyśmiewanie zależności zewnętrznych
  • Umiejętność testowania testów z mutacją (łamanie kodu) i rozpoznawania trudnego do przetestowania kodu jako zapachu projektu

Największą i najszybszą warstwą piramidy testowania są testy jednostkowe — testy weryfikujące funkcję lub mały fragment kodu w oderwaniu od wszystkiego innego. Tysiące testów jednostkowych uruchamia się w ciągu kilku sekund i wychwytuje błąd, gdy kod jest wciąż na ekranie programisty. Sztuczna inteligencja (AI) jest prawdopodobnie najbardziej biegła w tworzeniu testów jednostkowych: dajesz jej funkcję, a sztuczna inteligencja tworzy dziesiątki testów. Ale to właśnie wygoda rodzi największą pułapkę: sztuczna inteligencja z łatwością tworzy testy, które „świecą na zielono, ale niczego nie weryfikują” lub akceptują obecne (być może błędne) zachowanie kodu jako „poprawne”. W tej części dowiesz się, jak pisać prawdziwie ochronne testy jednostkowe z wykorzystaniem sztucznej inteligencji oraz powiązania pomiędzy testowalnym kodem a sztuczną inteligencją.

Cechy dobrego testu jednostkowego: PIERWSZE

Dobre testy jednostkowe są zgodne z PIERWSZYMI zasadami: szybkie, niezależne (testy nie powinny być od siebie zależne), powtarzalne (powtarzalne — ten sam wynik w każdym środowisku), samosprawdzające się (wyraźnie pozytywny/negatywny), terminowe (na czas). Przypomnij sobie o tych zasadach, gdy AI będzie tworzyć testy; szczególnie poproś, aby test nie zależał od świata zewnętrznego (rzeczywista baza danych, sieć, zegar), aby był „niezależny” i „powtarzalny”.

Wzór AAA i wyrazista asertywność

Solidny test jednostkowy jest zgodny ze strukturą AAA: Arrange (przygotowaj – skonfiguruj dane wejściowe i zależności), Act (wykonaj – wywołaj testowaną funkcję), Assert (zatwierdź – porównaj wynik z oczekiwaną wartością). Krytycznym jest stwierdzenie. Najczęstszym błędem popełnianym przez sztuczną inteligencję jest wyprowadzanie potwierdzenia z danych wyjściowych testowanego kodu — logika „wszystko, co zwróci kod, jest prawdą”. To sprawia, że ​​test nie ma sensu. Prawidłowym sposobem jest samodzielne wyznaczenie wartości oczekiwanej (z kryteriów akceptacji wyliczyć ją ręcznie).

Uwaga: jeśli powiesz AI „napisz test dla tej funkcji”, AI może uruchomić tę funkcję i zapisać jej wynik jako „oczekiwany”. Ten test przechodzi pomyślnie, nawet jeśli funkcja jest fałszywa. Zamiast tego powiedz „obliczasz oczekiwane wyniki zgodnie z tymi regułami, nie odwołujesz się do bieżącego wyjścia funkcji”.

Próby, kody pośredniczące i zależności

Testowanie jednostkowe wymaga izolacji. Jeśli Twoja funkcja zależy od bazy danych lub interfejsu API, podczas testowania są one zastępowane obiektami próbnymi (mock/stub — kontrolowany, fikcyjny substytut prawdziwej zależności). Dzięki temu test jest szybki, niezależny i powtarzalny. Sztuczna inteligencja może stworzyć próbną instalację; Ale uważaj na nadmierne kpiny: jeśli będziesz kpił ze wszystkiego, test zweryfikuje jedynie „co zwróci kpina”, a nie faktyczną logikę. Równowaga: emuluj świat zewnętrzny, wykonaj testowaną prawdziwą logikę.

Testowalność i sztuczna inteligencja

Istnieje interesująca informacja zwrotna: kod trudny do przetestowania jest często źle zaprojektowany. Jeśli sztuczna inteligencja ma problemy z zapisaniem testów do funkcji (zbyt wiele zależności, ukryty stan globalny, skutki uboczne), jest to zapach projektu. Zapytanie sztucznej inteligencji „w jaki sposób zrefaktoryzowałbyś ten kod, aby był testowalny” prowadzi zarówno do lepszego testowania, jak i lepszego kodu.

Testy parametryczne i różnorodność danych

Pisanie za każdym razem osobnego testu w celu sprawdzenia tej samej reguły przy różnych danych wejściowych jest zarówno żmudne, jak i trudne w utrzymaniu. Testowanie parametryczne — struktura, która wielokrotnie uruchamia tę samą logikę testów na liście danych wejściowych i oczekiwanych wyników — eliminuje to powtarzanie: pojedynczy korpus testowy jest zasilany dziesiątkami par wejściowych. Sztuczna inteligencja jest bardzo skuteczna w tworzeniu tabel wyników oczekiwanych na podstawie danych wejściowych, jeśli podasz jej zasady akceptacji; W szczególności systematycznie zestawia wartości graniczne i klasy równoważności.

Ale i tutaj jest pułapka: sztuczna inteligencja ma tendencję do wyprowadzania oczekiwanych wyników w wygenerowanej tabeli z testowanego kodu. Ten błąd jest jeszcze bardziej niebezpieczny w testowaniu sparametryzowanym, ponieważ pojedyncza niepoprawna logika unieważnia dziesiątki linii. Dlatego zawsze należy obliczać kolumnę oczekiwanego wyniku niezależnie, zgodnie z regułą akceptacji i ręcznie weryfikować co najmniej kilka wierszy. Poproś także o kolumnę opisu „co reprezentuje każdy wiersz”; więc gdy wiersz się zepsuje, natychmiast zobaczysz, który stan jest uszkodzony.

Wskazówka: celowo dodaj „wiersz pułapki” do sparametryzowanej tabeli testowej — to znaczy świadomie błędnie wpisz wynik. Jeśli po uruchomieniu testu ta linia nie zmieni koloru na czerwony, oznacza to, że test w rzeczywistości nie sprawdza tej sytuacji. Jest to szybka próbna kontrola przepustki.

Słaba zachęta/silna zachęta

Słabe: „Napisz test jednostkowy dla tej funkcji”.
Mocne: Napisz testy jednostkowe [język/framework] dla funkcji „taxCalculate(kwota, stawka). Reguła akceptacji: wynik = kwota * stawka, zaokrąglona do 2 miejsc po przecinku; ujemna kwota lub stawka powoduje błąd; zwraca 0, jeśli stawka wynosi 0. Użyj struktury AAA. Ręcznie oblicz oczekiwane wartości zgodnie z TYMI regułami; nie odwołuj się do bieżącego wyniku funkcji. Uwzględnij przypadki ograniczone i ujemne (0, ujemne, bardzo duże, zaokrąglone do miejsc po przecinku). Niech nazwa każdy test opisuje regułę, którą sprawdza. Zewnętrzna zależność „Nie”.

Potężny monit; Podaje regułę akceptacji, niezależną wartość oczekiwaną, strukturę i przypadki brzegowe. Tym samym test staje się strażnikiem reguły, a nie zwierciadłem kodu.

Tabela jakości testów jednostkowych

objaw

Zły test (fałszywe zaufanie)

dobry test

twierdzić

Brak lub „nie null”

Oczekiwana konkretna wartość

Oczekiwane źródło wartości

Wyjście funkcji

Reguła akceptacji / kalkulacja ręczna

uzależnienie

Rzeczywisty DB/sieć/godz

Izolowany za pomocą makiety/odgałęzienia

obudowa krawędziowa

Tylko szczęśliwa droga

granica, ujemna, błąd

Kiedy złamiesz kod

pozostaje zielony

zmienia kolor na czerwony

Imię

test1, metoda testowa

opisuje regułę, którą potwierdza

Cztery szablony do kopiowania

1) Testowanie jednostkowe oparte na regułach:

Twoja rola: starszy inżynier ds. testów oprogramowania.Napisz test jednostkowy dla następującej funkcji, używając [języka/frameworka]: [podpis].Zasady akceptacji: [reguły].- Użyj struktury AAA.- Ręcznie oblicz oczekiwane wartości zgodnie z TYMI regułami; NIE odwołuj się do wyjścia prądowego funkcji. - Obejmij granicę, ujemną, błędną i szczęśliwą ścieżkę oddzielnymi testami. - Niech każda nazwa testu opisuje regułę, którą sprawdza. - Mock zależności zewnętrzne; Spraw, aby rzeczywista logika działała.

2) Kontrola odporności na mutację:

Sprawdź te testy jednostkowe. Wymień 5 drobnych poprawek, które mógłbym wprowadzić w testowanym kodzie (a - zamiast +, a >= zamiast >, przesunięcie granicy) i powiedz mi w przypadku każdego z nich, KTÓRE z tych testów zmienią kolor na czerwony? Jeżeli żaden nie zostanie zwrócony, test jest niewystarczający. Kod + testy: [wklej]

3) Przegląd testowalności:

Dlaczego trudno jest napisać test jednostkowy dla tej funkcji? Ukryte uzależnienie, status globalny, skutki uboczne, czy jest wiele obowiązków? Zaproponuj minimalną refaktoryzację, aby można było ją przetestować; nie zmieniaj zachowania. Kod: [wklej]

4) Niekompletne ukończenie scenariusza:

Podano następującą funkcję i dostępne testy. Wypisz, które zachowanie/przypadek Edge NIGDY nie zostało przetestowane (luka w zakresie) i dodaj test dla każdego z nich. Funkcja+testy: [wklej]

trzy mini etui

Przypadek 1 — Test odzwierciedlający kod. Deweloper zlecił sztucznej inteligencji napisanie testu funkcji zaokrąglania; 10 testów było zielonych. W rzeczywistości funkcja zaokrąglała w złym kierunku, ale sztuczna inteligencja pobrała oczekiwane wartości z wyniku funkcji, więc testy uznały błąd za „prawdę”. Kiedy oczekiwane wartości zostały obliczone ręcznie za pomocą szablonu „opartego na regułach”, 4 testy zmieniły kolor na czerwony i ujawniono prawdziwy błąd.

Przypadek 2 — Wartość kontroli mutacji. Jeden zespół oparł się na 45 testach jednostkowych. Wypróbowano 20 drobnych poprawek w kodzie za pomocą „kontroli odporności mutacji”; testy wyłapały tylko 11 z nich. Pozostałe 9 zakłóceń minęło spokojnie. Zespół wzmocnił słabe testy; Te ulepszone testy w następnej wersji wykryły rzeczywisty błąd obliczeniowy.

Przypadek 3 — Nietestowalność to zapach projektu. Sztuczna inteligencja nie mogła pisać testów dla funkcji porządkującej, stale potrzebowała prawdziwej bazy danych. Szablon „przeglądu testowalności” pokazał, że funkcja wbudowanego dostępu do bazy danych. Po usunięciu zastrzyku zależności można było pisać testy, a kod stał się czystszy.

Typowe błędy

  • Wyprowadzanie oczekiwanej wartości z kodu. AI akceptuje wynik funkcji jako „poprawny”; test potwierdzający błędny kod.
  • Testuj bez potwierdzenia lub z trywialnym potwierdzeniem. „Nie wyrzucił błędu, zdał” logikę; To niczego nie potwierdza.
  • Ekstremalna kpina. Wyśmiewanie wszystkiego i testowanie tylko tego, co zwraca kpina; prawdziwa logika nie jest testowana.
  • Tylko szczęśliwa droga. Omijanie stanów granicznych, ujemnych i błędów.
  • Nie testowanie poprzez łamanie kodu. Ufanie zielonemu bez sprawdzania mutacji.
  • Ignorowanie nietestowalności. Nierozpoznawanie i naprawianie złego projektu zamiast forsowania trudnych testów.

Podsumowując

Testy jednostkowe to najszybsza i największa warstwa piramidy testowej; Łapie błąd w najtańszym momencie. Sztuczna inteligencja jest bardzo zdolna do tworzenia testów jednostkowych, ale jej największą pułapką jest pisanie testów, które zakładają nieprawidłowe zachowanie jako „poprawne”, wyprowadzając oczekiwaną wartość z samego kodu. Rozwiązanie: podaj reguły akceptacji, ręcznie oblicz oczekiwane wartości, egzekwuj zasady AAA i FIRST, kpij ze świata zewnętrznego i uruchom rzeczywistą logikę oraz przetestuj każdy test poprzez mutację (łamanie kodu). Kod trudny do przetestowania jest znakiem projektowym wymagającym naprawy.

Zadanie aplikacji

Wybierz funkcję zawierającą regułę biznesową z własnego projektu. Napisz reguły akceptacji i zleć AI zapisanie testów z szablonem „testowanie jednostkowe oparte na regułach”; Należy ręcznie obliczyć oczekiwane wartości. Następnie zastosuj „sprawdzenie odporności mutacji”: wykonaj co najmniej 5 małych przerw w kodzie i zmierz, ile testów zmienia kolor na czerwony. Dodaj nowy test na niewykryte korupcje. Zgłoś liczbę wykrytych zakłóceń (np. wynik mutacji).

lista kontrolna

  • [ ] Podałem zasady akceptacji i ręcznie obliczyłem oczekiwane wartości.
  • [ ] Upewniłem się, że testy nie wyprowadziły oczekiwanej wartości z kodu.
  • [ ] Przeprowadziłem niezależne testy zgodnie z wytycznymi AAA i FIRST.
  • [ ] Wyśmiałem zależności zewnętrzne i uruchomiłem rzeczywistą logikę.
  • [ ] Omówiłem przypadki graniczne, ujemne i błędy.
  • [ ] Łamiąc kod (mutację) udowodniłem, że testy rzeczywiście chronią.