Rozwój sterowany testami z AI

https://aie24.pl/

Ponieważ generatywna AI opiera się na kontekście, sprawienie, aby AI generowała testy dla funkcji, które mają błędy, może być trudne. Co jednak, gdybyśmy odwrócili proces do góry nogami i poprosili AI o wygenerowanie działającego kodu na podstawie nieudanych testów? To jest idea stojąca za rozwojem sterowanym testami i może być najlepszym sposobem, aby asystent AI napisał dokładnie taki kod, jakiego potrzebujesz. Rozwój sterowany testami (TDD) to praktyka tworzenia oprogramowania, która koncentruje się na tworzeniu testów dla funkcjonalności, która jeszcze nie istnieje. W rozwoju sterowanym testami programista pisze test dla pojedynczej jednostki kodu, a następnie pisze kod, aby test przeszedł. Żaden fragment kodu nie jest pisany bez wcześniejszego napisania testu, więc TDD (wykonane poprawnie) skutkuje 100-procentowym pokryciem kodu i kodem wyższej jakości. Proces TDD obejmuje trzy kroki, zwane cyklem TDD, które są powtarzane tak często, jak to konieczne, aby zbudować pożądane oprogramowanie:

»»Napisz test. Napisz test, który dokładnie opisuje pojedynczy element funkcjonalności, a następnie uruchom test, aby potwierdzić, że się nie powiedzie (ponieważ funkcja jeszcze nie istnieje). Znany również jako etap czerwony.

»»Napisz kod, aby przejść test. Napisz minimalny kod niezbędny do przejścia testu. Znany również jako etap zielony.

»»Refaktoryzuj. Przebuduj zarówno kod, jak i test, aby je ulepszyć.

Po etapie refaktoryzacji cykl zaczyna się od nowego testu. Celem programisty podczas praktykowania TDD jest tworzenie testów i oprogramowania w małych i przetestowanych fragmentach kodu. Zamiast skupiać się na poprawnym pisaniu kodu, a następnie testowaniu, czy działa, TDD kładzie nacisk na pisanie dobrych testów, a następnie pisanie minimalnej ilości kodu, aby przejść testy, nawet jeśli kod, który piszesz, nie jest idealny. Po przejściu testu przez kod, ulepszasz kod na etapie refaktoryzacji. Ponieważ AI jest dobra w pisaniu małych ilości kodu, gdy otrzymuje dobre instrukcje, TDD wydaje się idealnym dopasowaniem do pracy z asystentem AI. Jest jednak pewien haczyk — musisz sam napisać testy. Jeśli masz AI piszącą zarówno testy, jak i kod, jest wysoce prawdopodobne, że oba będą błędne. Pisanie testów w TDD to sposób, w jaki projektujesz oprogramowanie, więc ważne jest, aby testy były poprawne. Technicznie rzecz biorąc, nie musisz pisać testów całkowicie bez pomocy AI. Korzystanie z funkcji uzupełniania Copilot podczas kodowania jest ogólnie bezpieczne, o ile weryfikujesz i zatwierdzasz każde automatyczne uzupełnianie. Aby znaleźć funkcję, która byłaby dobrym kandydatem do rozwinięcia za pomocą TDD, przyjrzałem się niedokończonym funkcjom w SRS gry w kółko i krzyżyk, które wygenerowałem za pomocą ChatGPT w rozdziale 5. Największa funkcja, której jeszcze nie stworzyłem, jest określona w nagłówku Historia i statystyki gry:

– Gra będzie śledzić statystyki gracza, takie jak:

– Całkowita liczba rozegranych gier.

– Liczba wygranych gier.

– Liczba przegranych gier.

Na początek napisałem test sprawdzający, czy zmienna totalGamesPlayed zwiększa się po rozegraniu gry. Oto, co wymyśliłem:

describe(‘Game stats’, () => {

let game;

beforeEach(() => {

game = new TicTacToeGame();

});

test(‘increments total games played after a game ends’,

() => {

expect(game.totalGamesPlayed).toBe(0);

game.isGameOver = true;

game.updateGameStats();

expect(game.totalGamesPlayed).toBe(1);

});

});

Po napisaniu testu uruchomiłem Jest, aby potwierdzić, że test się nie powiódł. I oczywiście tak się stało, jak pokazano na rysunku

Następnie otworzyłem pliki script.js, script.test.js i srs.md i wyświetliłem Copilot Chatowi następujący komunikat:

@workspace Napisz kod, aby przejść ten test:

Po wyświetleniu monitu wkleiłem swój test w oknie czatu. Zauważ, że użyłem polecenia @workspace, aby powiedzieć Copilotowi, aby uznał wszystkie pliki w moim projekcie za odniesienia do swojej odpowiedzi, co pokazano na rysunku

Wdrożyłem sugerowane rozwiązanie i ponownie uruchomiłem testy. Wszystko przeszło, więc byłem gotowy przejść do refaktoryzacji. Jednym ze sposobów ulepszenia testu byłoby symulowanie zakończenia gry, zamiast ręcznego ustawiania isGameOver na true. To ulepszenie sprawiłoby, że test byłby bardziej reprezentatywny dla rzeczywistego użycia klasy.

Zmieniłem test na następujący:

test(‘increments total games played after a game ends’, () => {

expect(game.totalGamesPlayed).toBe(0);

game.endGame()

expect(game.totalGamesPlayed).toBe(1);

});

Ponownie uruchomiłem test i nie powiódł się. Zapytałem Copilota, jak zmienić program, aby zaliczyć test, a on odpowiedział tak, jak pokazano na rysunku

Ta sugestia zadziałała i mój test zaliczył. Byłem całkiem zadowolony z testu i rozwiązania, więc przeszedłem do refaktoryzacji. Dokładnie wszystko sprawdziłem, a następnie napisałem kolejny test. Po zmodyfikowaniu testu i zaimplementowaniu kodu, aby go zaliczyć, sprawdź, czy nie ma zbędnego kodu. Jak dowiesz się w rozdziale 6, kod, który mógł mieć kiedyś jakiś cel, ale nie jest już używany przez program, jest znany jako martwy kod. Powinieneś usunąć martwy kod podczas etapu refaktoryzacji TDD.

W tym momencie metoda endGame() nigdy nie jest wywoływana podczas normalnego grania w grę, więc postanowiłem, że zakończenie gry będzie kolejnym elementem funkcjonalności do napisania. Aby zobaczyć, jak Copilot napisze test, wywołałem go następującym poleceniem:

@workspace Jak mogę napisać test jednostkowy, aby sprawdzić, czy metoda endGame jest uruchamiana, gdy gracz wygrywa?

Z nieznanego powodu Copilot odpowiedział, że może pomóc tylko w przypadku pytań związanych z programowaniem, jak pokazano na rysunku

Jestem pewien, że mógłbym doprecyzować swój monit, aby Copilot zrozumiał, o czym mówię, ale uznałem, że mój argument o nieproszeniu AI o generowanie testów podczas wykonywania TDD został udowodniony, więc napisałem następujący zestaw testów:

describe(‘Game end’, () => {

let game;

beforeEach(() => {

game = new TicTacToeGame();

});

test(‘sets isGameOver to true after a player wins’, () => {

expect(game.isGameOver).toBe(false);

game.board = [‘X’, ‘X’, ‘X’, ‘O’, ‘O’, ”, ”, ”, ”];

game.checkWin();

expect(game.isGameOver).toBe(true);

});

});

Kilkakrotnie próbowałem zmusić Copilot Chat do wygenerowania kodu, którego chciałem. Przedstawiłem monit @workspace, aby przeanalizował wszystkie pliki w moim projekcie. Dałem mu tylko script.js jako odniesienie, a następnie dałem mu tylko script.test.js. Za każdym razem uparcie odmawiał podania tego, co uważałem za akceptowalną odpowiedź. Zamiast dalej kłócić się z Copilot Chat, postanowiłem, że szybciej będzie po prostu napisać ten kod samemu. Prawidłowa odpowiedź to wywołanie funkcji endGame(), gdy jeden z graczy wygrywa. Oto poprawiona funkcja checkWin(), z kodem, który napisałem, aby przejść ten test, pokazanym pogrubieniem:

/**

* Check whether someone has won the game

* @returns {boolean}

*/

checkWin() {

const winCombos = [

[0, 1, 2],

[3, 4, 5],

[6, 7, 8],

[0, 3, 6],

[1, 4, 7],

[2, 5, 8],

[0, 4, 8],

[2, 4, 6],

];

const win = winCombos.some((combo) => {

return (

this.board[combo[0]] &&

this.board[combo[0]] === this.board[combo[1]] &&

this.board[combo[0]] === this.board[combo[2]]

);

});

win ? this.endGame() : null;

return win;

}

Wdrożyłem swoje rozwiązanie i test przeszedł. Prowadzi to do najważniejszej lekcji tego rozdziału: w TDD wspomaganym przez AI, jeśli znasz właściwy sposób (lub nawet łatwy sposób), aby zaliczyć test, nie proś o pomoc AI. Zaufaj sobie. Trzeba zrobić o wiele więcej, aby ukończyć funkcjonalność opisaną w sekcji Game History and Stats w SRS.

Analiza wyników testów

https://aie24.pl/

Fakt, że wszystkie testy wygenerowane przez Copilota przechodzą w tym momencie, nie oznacza, że ​​kod działa poprawnie. Jeśli w testach są błędy, mogą one przejść nawet jeśli testowany kod jest niepoprawny. W tej sekcji analizujesz testy i wyniki z uruchomienia testów. Jeśli napiszesz kod z błędami i poprosisz generatywny model AI o napisanie testu jednostkowego dla kodu z błędami, model może dać ci test, który weryfikuje zachowanie kodu takim, jaki jest — z błędami i wszystkim. Na przykład rozważ następującą funkcję:

sumNumbers(num1, num2) {

return `${num1} + ${num2}`;

}

Jak wskazuje nazwa funkcji, jej zamierzonym celem jest dodanie dwóch liczb. Została jednak napisana w taki sposób, że zwróci ciąg znaków. Wybrałem funkcję sumNumbers() i poprosiłem Copilota o napisanie dla niej testów. Copilot dostarczył następujące testy:

describe(‘sumNumbers’, () => {

test(‘returns correct string for positive numbers’, () => {

expect(game.sumNumbers(1, 2)).toBe(‘1 + 2’);

});

test(‘returns correct string for negative numbers’, () => {

expect(game.sumNumbers(-1, -2)).toBe(‘-1 + -2’);

});

test(‘returns correct string for zero’, () => {

expect(game.sumNumbers(0, 0)).toBe(‘0 + 0’);

});

test(‘returns correct string for mixed positive and negative

numbers’, () => {

expect(game.sumNumbers(-1, 2)).toBe(‘-1 + 2’);

expect(game.sumNumbers(1, -2)).toBe(‘1 + -2’);

});

});

Te testy poprawnie testują funkcjonalność funkcji sumNumbers() tak, jak jest napisana, i wszystkie przechodzą. Jednak funkcja w takiej formie, w jakiej została napisana, jest błędna, a ludzki programista, który znałby zamierzony cel sumNumbers(), nigdy nie napisałby tych testów. Funkcja sumNumbers() jest uproszczona i sztuczna, ale wskazuje na potencjalny błąd, gdy sztuczna inteligencja generuje testy: pisze testy, aby zweryfikować funkcję, którą masz, a nie, aby zweryfikować, czy funkcja generuje oczekiwane wyniki. Jedną ze strategii rozwiązania tego problemu może być prawidłowe udokumentowanie funkcji przed wygenerowaniem testów. Dodałem komentarz opisujący funkcję, tak jak poniżej:

/**

* Adds two numbers together.

* @returns {number}

*/

sumNumbers(num1, num2) {

return `${num1} + ${num2}`;

}

Jednak nawet z tym komentarzem, gdy uruchomiłem polecenie /tests, Copilot nadal generował testy dla funkcji tak, jak została napisana, a nie dla tego, co zamierzałem, aby funkcja robiła. W mojej następnej próbie specjalnie poprosiłem Copilot o wygenerowanie testu, który sprawdzałby, czy funkcja robi to, co określa opis funkcji:

Napisz test sprawdzający, czy funkcja sumNumbers wykonuje to, co powinna, zgodnie z komentarzem JSDoc.

Mimo tego konkretnego komentarza Copilot wygenerował testy w celu sprawdzenia, czy funkcja zwraca ciąg znaków, a nie liczbę, jak pokazano na rysunku

Postanowiłem dać temu jeszcze jedną szansę. Tym razem poprosiłem o dokładnie to, czego chciałem, tak:

Funkcja sumNumbers powinna przyjmować dwie liczby jako argumenty i zwracać sumę tych dwóch liczb. Napisz testy, aby sprawdzić, czy to właśnie robi.

Tym razem Copilot napisał testy, których chciałem, jak pokazano na rysunku

Skopiowałem testy do pliku o nazwie sumNumbers.test.js i uruchomiłem je. Zgodnie z oczekiwaniami wszystkie trzy testy wygenerowane przez Copilot zakończyły się niepowodzeniem, jak pokazano na rysunku

Zmodyfikowałem funkcję sumNumbers(), aby uzyskać prawidłowy wynik, a następnie ponownie uruchomiłem testy. Po naprawieniu funkcji wszystkie testy przeszły pomyślnie, jak pokazano na rysunku

Generative AI nie zawsze napisze testy, których chcesz. Aby zrozumieć dlaczego, ważne jest, aby zawsze pamiętać, że modele generatywne mogą tworzyć tylko takie przewidywania, które mają duże prawdopodobieństwo bycia poprawnymi. Łatwo jest oskarżyć model GenAI o to, że jest zły w swojej pracy, gdy wielokrotnie podaje tę samą błędną odpowiedź na pozornie proste pytanie. Jednak problem często polega na tym, że dostarcza on idealnie dobrych odpowiedzi na zadane pytanie i że poprawne zadanie pytania da oczekiwany wynik.

Odczytywanie raportu pokrycia

https://aie24.pl/

Struktury testowe, takie jak Jest, mogą przeglądać testy, które napisałeś, aby wygenerować raport pokrycia, który pomaga zrozumieć, jaka część kodu źródłowego została przetestowana. Raporty pokrycia generowane przez Jest dostarczają również informacji o częściach kodu, które nie są obecnie testowane, jak pokazano na rysunku

Jak dotąd Copilot świetnie radzi sobie z generowaniem testów, a raport pokrycia testów wskazuje, że prawie jedna trzecia funkcji jest teraz objęta testami. Jednak przetestowaliśmy tylko te funkcje, które są najłatwiejsze do przetestowania. Inne funkcje w programie mają zależności zewnętrzne (takie jak przeglądarka i serwer) i będą bardziej skomplikowane do przetestowania. Na przykład funkcja clearBoardDiplay(), która resetuje planszę gry do stanu domyślnego, współdziała z przeglądarką i wymaga testu, który poprawnie sprawdza stan planszy w przeglądarce. Aby sprawdzić, czy Copilot podoła zadaniu, wybrałem funkcję i uruchomiłem polecenie /tests. Copilot wygenerował test, który wyglądał podobnie do tego, co bym napisał. Utworzył kopię elementów planszy gry wypełnioną krzyżykami i dziesiątkami, a następnie uruchomił funkcję clearBoardDisplay() i sprawdził, czy plansza została przywrócona do stanu domyślnego. Kiedy skopiowałem zestaw testów do pliku script.test.js i uruchomiłem testy, nowy test przeszedł pomyślnie, jak pokazano na rysunku . Wszystkie testy napisane przez Copilota do tej pory przeszły, ale czy testy są ważne? W następnej sekcji dowiesz się, jak analizować testy napisane przez model AI.

Generowanie przypadków testowych

https://aie24.pl/

W Copilot Chat polecenie /tests generuje testy dla kodu wybranego w edytorze kodu. Aby użyć polecenia /tests, wykonaj następujące kroki:

  1. Upewnij się, że zarówno script.test.js, jak i script.js są otwarte w VS Code.
  2. W script.js wybierz funkcję checkWin().

Funkcja checkWin() sprawdza, czy któryś z graczy wygrał grę.

  1. Wpisz /tests w Copilot Chat.

Copilot automatycznie poprzedza polecenie /tests @workspace, a następnie próbuje wygenerować testy dla funkcji checkWin(), jak pokazano na rysunku

Polecenie @workspace to agent Copilot, który instruuje Copilot, aby podczas generowania odpowiedzi brał pod uwagę wszystkie pliki w bieżącym obszarze roboczym VS Code

Copilot zasugerował trzy testy dla funkcji checkWin():

»»Sprawdź, czy checkWin() zwraca false, gdy plansza jest pusta.

»»Sprawdź, czy checkWin() zwraca false, gdy plansza nie ma zwycięskiej kombinacji.

»»Sprawdź, czy checkWin() zwraca true, gdy plansza ma zwycięską kombinację.

Te testy zdają się obejmować każdy możliwy warunek funkcji, więc stwórzmy zestaw testów i dodajmy je do niego. Aby rozpocząć konfigurowanie zestawu testów dla pliku script.js w grze w kółko i krzyżyk, utworzyłem plik o nazwie script.test.js i dodałem do niego następującą instrukcję importu:

import { TicTacToeGame } from ‘./script’;

Skopiowałem testy wygenerowane przez Copilot i wkleiłem je do script.test.js po poleceniu import i uruchomiłem npm test. Wynik pokazano na rysunku

Copilot pomyślnie napisał trzy testy, a gra w kółko i krzyżyk przeszła wszystkie trzy! Funkcja checkWin() nie wchodzi w interakcję z przeglądarką, więc jest idealnym kandydatem do tworzenia prostych testów. Funkcja checkDraw() sprawdza, czy wszystkie pola są wypełnione bez wygranej żadnego z graczy. Jest również bardzo prosta i możesz użyć tego samego podejścia, aby wygenerować testy dla tej funkcji. Wykonaj następujące kroki:

  1. Upewnij się, że script.test.js jest nadal otwarty na sąsiedniej karcie, wybierz funkcję checkDraw() w script.js.
  2. W Copilot Chat wpisz /tests i naciśnij Enter.

Za pierwszym razem, gdy uruchomiłem /tests, wybrałem checkDraw() i jego komentarz. Copilot zwrócił testy dla innych funkcji w programie oprócz checkDraw(). Następnie wybrałem tylko funkcję checkDraw() (bez jej dokumentacji) i ponownie wpisałem /tests. Tym razem otrzymałem odpowiedź, której chciałem. Drugi pilot zasugerował następujące testy dla funkcji checkDraw():

»»Sprawdź, czy checkDraw() zwraca false, gdy plansza jest pusta.

»»Sprawdź, czy checkDraw() zwraca false, gdy plansza jest częściowo wypełniona.

»»Sprawdź, czy checkDraw() zwraca true, gdy plansza jest całkowicie wypełniona i nie ma zwycięzcy.

Ponownie, wydaje się to dobrym planem. Po dostarczeniu planu testowania checkDraw(), Copilot napisał testy dla każdego sugerowanego przypadku testowego, jak pokazano na rysunku

Skopiowałem testy, wkleiłem je do script.test.js i uruchomiłem testy ponownie. Wynik pokazano na rysunku

Uruchamianie Jest

https://aie24.pl/

Teraz, gdy framework testowy Jest jest zainstalowany i skonfigurowany, następnym krokiem jest jego uruchomienie. Aby uruchomić Jest, wpisz npm test w oknie terminala. Jest przeszukuje Twój projekt (wszystko w bieżącym pakiecie Node.js) w poszukiwaniu zestawów testów do uruchomienia. W tej chwili ten projekt nie ma żadnych testów, więc Jest odpowiada komunikatem „Nie znaleziono testów”, jak pokazano na rysunku 

Oprócz wskazania, że ​​w projekcie nie ma żadnych testów, raport wskazuje również sprawdzony folder, liczbę plików w projekcie i nazwy plików, w których szuka testów. Domyślnie Jest szuka testów w następujących plikach:

»»Pliki JavaScript lub TypeScript w folderze o nazwie __tests__ (to dwa podkreślenia, po których następuje słowo tests, a następnie dwa kolejne podkreślenia).

»»Pliki JavaScript lub TypeScript z .spec. w nazwie przed rozszerzeniem pliku, takie jak MyComponent.spec.js.

»»Pliki JavaScript lub TypeScript z .test. w nazwie przed rozszerzeniem pliku, takie jak MyComponent.test.js.

Instalowanie Jest

https://aie24.pl/

W tej sekcji instalujesz framework testowy Jest. Ale najpierw, otwórz folder tic-tac-toe-client-final w oknie terminala i uruchom npm install. Wykonałem już trudne części konfigurowania Jest w tym folderze, więc możesz pominąć pozostałe kroki w tej sekcji i przejść bezpośrednio do sekcji zatytułowanej „Uruchamianie Jest”. Aby zainstalować Jest, wykonaj następujące kroki:

  1. Otwórz nowe okno terminala i wprowadź poniższe polecenie, aby przejść do właściwego folderu:

cd tic-tac-toe-client

  1. Wprowadź następujące polecenie w terminalu, aby zainicjować projekt Node w katalogu klienta:

npm init

  1. Odpowiedz na pytania zadane przez skrypt npm init. (Możesz zaakceptować domyślną odpowiedź na każde pytanie.)

Twoje odpowiedzi są używane do konfigurowania pakietu Node.js. Pamiętaj, że możesz wrócić później i zmienić swoje odpowiedzi, edytując plik package.json.

  1. Zainstaluj Jest, wprowadzając następujące polecenie w oknie terminala:

npm install jest –save-dev

  1. Zainstaluj środowisko JSDom:

npm install jest-environment-jsdom –save-dev

JSDom to środowisko podobne do przeglądarki, w którym Jest uruchomi Twoje testy, aby symulować ich uruchomienie w rzeczywistej przeglądarce internetowej.

  1. Utwórz konfigurację bazową dla Jest:

npx jest –init

Skrypt init Jest zada Ci kilka pytań. Pytania, wraz z wybranymi przeze mnie ustawieniami, to:Skrypt init Jest zada Ci kilka pytań. Pytania, wraz z wybranymi przeze mnie ustawieniami, to:

Czy chcesz użyć Jest podczas uruchamiania skryptu „test” w „package.json”? tak

Czy chcesz użyć Typescript dla pliku konfiguracyjnego? nie

Wybierz środowisko testowe, które będzie używane do testowania jsdom (podobne do przeglądarki)

Czy chcesz, aby Jest dodawał raporty pokrycia? tak

Którego dostawcy należy użyć do instrumentacji kodu dla pokrycia? v8

Automatycznie czyścić pozorowane wywołania, wystąpienia, konteksty i wyniki przed każdym testem? tak

Gdy już odpowiesz na pytania, Jest utworzy w Twoim projekcie plik o nazwie jest.config.js.

Ponieważ Jest działa w Node, możliwe, że Twój projekt będzie zawierał składnię, która nie jest obsługiwana przez Node. Aby to uwzględnić, musisz zainstalować kilka dodatkowych pakietów.

  1. Wpisz poniższe polecenie w oknie terminala:

npm install babel-jest @babel/preset-env @babel/core

–save-dev

Babel to transpilator JavaScript, który konwertuje kod z jednej wersji języka na inną. W tym przypadku będziesz używać Babel do konwersji kodu zaprojektowanego do uruchomienia w przeglądarce na kod, który będzie działał w Node.

  1. Skonfiguruj wtyczkę babel-jest:
  2. Otwórz jest.config.js. Zobaczysz wiele zakomentowanych instrukcji.
  3. Znajdź zakomentowaną instrukcję, która zaczyna się od transform: i usuń komentarz. Instrukcja transform to miejsce, w którym możesz określić wzorce nazw plików, które mają pasować, a następnie zmienić te pliki przed testowaniem. W naszym przypadku będziemy transpilować pliki JavaScript za pomocą wtyczki babel-jest.
  4. Zmień instrukcję transform na następującą:

transform: {

‘\\.[jt]sx?$’: ‘babel-jest’,

}

  1. Skonfiguruj Babel, tworząc w swoim projekcie plik o nazwie babel.config.json i dodając do niego następującą zawartość:

{

“env”: {

“test”: {

“presets”: [

“@babel/preset-env”

]

}

}

}

Uff! Nie było tak źle, prawda? Przejdź do następnej sekcji, aby dowiedzieć się, jak uruchomić Jest i jak napisać swoje pierwsze testy.

Praca z frameworkiem testowym

https://aie24.pl/

Framework automatyzacji testowania to oprogramowanie, które udostępnia narzędzia do pisania testów i środowisko do uruchamiania testów. Dostępnych jest wiele frameworków testowych, a projekt oprogramowania może wymagać użycia kilku różnych frameworków do wykonywania różnych rodzajów testów. Programiści najczęściej zajmują się testowaniem jednostkowym, metodą testowania oprogramowania, w której poszczególne moduły aplikacji są testowane w celu ustalenia, czy nadają się do użytku. W testach jednostkowych programiści tworzą testy (znane również jako specyfikacje), które opisują i testują wyniki funkcji, porównując oczekiwane wyniki funkcji z rzeczywistymi wynikami funkcji. To porównanie pomiędzy oczekiwanymi wynikami a rzeczywistymi wynikami jest znane jako asercja. Pełne przetestowanie pojedynczej funkcji w programie zwykle wymaga wielu asercji, przy czym każda asercja testuje aspekt lub możliwy wynik funkcji. Zbiór testów dla pojedynczej funkcji lub modułu nazywa się zestawem testów. Najpopularniejszym frameworkiem testowym do pisania i uruchamiania testów jednostkowych dla kodu JavaScript jest Jest (https://jestjs.io). Jest działa w środowisku uruchomieniowym Node.js. Jeśli nie masz zainstalowanego Node.js, przejdź do https://nodejs.org/, aby go pobrać i zainstalować, zanim przejdziesz do następnej sekcji.

Generowanie scenariuszy testowych

https://aie24.pl/

Następnie dałem Copilotowi następujący monit:

@workspace Powiedz mi, jak mam przetestować ten program

Copilot odpowiedział listą proponowanych testów dla każdej z funkcji programu, jak pokazano na rysunku .

Ostatnia rada, jaką Copilot dał w odpowiedzi na moją podpowiedź, brzmiała:

Do pisania i uruchamiania tych testów można wykorzystać zintegrowaną obsługę testów jednostkowych w programie Visual Studio Code.

Nigdy nie widziałem ani nie używałem zintegrowanego wsparcia testów jednostkowych w VS Code, ale brzmi to dla mnie jak dobry plan. Czując optymizm co do możliwości Copilota, zadaję mu następujące pytanie:

W jaki sposób mogę użyć zintegrowanego wsparcia testów jednostkowych dla Visual Studio Code do pisania i uruchamiania tych testów?

W swojej odpowiedzi Copilot podał mi kilka niekompletnych instrukcji dotyczących instalacji środowiska testowego, ale nie wspomniał nic więcej o zintegrowanym wsparciu testów w VS Code. Po przeszukaniu dokumentacji VS Code odkryłem, że VS Code nie ma zintegrowanego wsparcia testów jednostkowych. Ta rada była po prostu improwizacją Copilota! W poniższych sekcjach pokażę Ci, jak skonfigurować wsparcie testów jednostkowych w Twoim projekcie, napisać pierwsze testy i jak najlepiej wykorzystać sztuczną inteligencję do testowania.

Identyfikowanie podstawowych funkcjonalności

https://aie24.pl/

Zanim będziesz mógł przetestować oprogramowanie, musisz zrozumieć, co ono robi. W przypadku złożonego oprogramowania lub oprogramowania, którego nie napisałeś, pomocne jest udokumentowanie podstawowych funkcjonalności, które zostaną przetestowane, zanim zaczniesz planować, jak je testować. Specyfikacja wymagań oprogramowania (SRS), jeśli jest dostępna, może dać dobry początek do zidentyfikowania, do czego oprogramowanie zostało pierwotnie zaprojektowane. Jednak jest prawdopodobne, że wymagania zmieniły się w trakcie procesu tworzenia oprogramowania. Asystent AI wyjaśniający funkcjonalność oprogramowania może również służyć jako przewodnik do dokumentowania funkcjonalności. W rozdziale 5 tworzę grę w kółko i krzyżyk za pomocą AI. W obecnej formie gra tylko częściowo spełnia wymagania określone w SRS. Aby zacząć zastanawiać się, jak przetestować grę, pierwszym krokiem jest zidentyfikowanie obszarów funkcjonalności w grze. Otworzyłem plik JavaScript dla aplikacji klienckiej i wyświetliłem Copilot Chat następujący komunikat:

@workspace Jakie są główne funkcjonalności tej gry w kółko i krzyżyk?

Drugi pilot odpowiedział, podając dokładną listę i opisy wszystkich funkcji gry w kółko i krzyżyk, jak pokazano na rysunku .

Zrozumienie roli AI w planowaniu testów

https://aie24.pl/

Możesz używać AI na kilka sposobów w trakcie procesu planowania testów. Niektóre z zadań, które AI może wykonywać, obejmują:

»»Symuluj zachowanie użytkownika, aby zidentyfikować wzorce porażek lub sukcesów.

»»Analizuj wymagania oprogramowania, aby wygenerować kroki testowe w celu ich walidacji.

»»Wyjaśnij kod i zidentyfikuj funkcjonalność, którą należy przetestować.

»»Napisz przypadki testowe.

Oto korzyści wynikające z używania AI do tworzenia planu testów:

»»Automatyczna analiza: System AI może szybko analizować ogromne ilości danych, w tym złożone bazy kodów i wyniki testów.

»»Delikatne wykrywanie wzorców: AI jest w stanie wykrywać wzorce i anomalie, które mogą zostać przeoczone przez ludzi.

»»Przewidywanie przyszłych problemów: Korzystając z danych historycznych, AI może przewidywać przyszłe awarie i umożliwiać proaktywne planowanie testów.

»»Ocena ryzyka: AI może identyfikować obszary kodu o wysokim ryzyku i pomagać w ustalaniu priorytetów działań testowych.

»»Symulacje scenariuszy: AI może symulować różne scenariusze testowe w celu zidentyfikowania najskuteczniejszych podejść.