Testowanie i integracja
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 104 z 107.
Wyzwanie
ŁatwyDomknijmy działanie naszego systemu zarządzania biblioteką, pisząc testy weryfikujące, czy wszystko działa poprawnie! Utworzysz plik testowy, który sprawdzi podstawowe funkcje biblioteki: upewni się, że książki można prawidłowo wypożyczać i zwracać oraz że błędy są odpowiednio obsługiwane.
Rozmieścisz kod w pięciu plikach:
book.go: StrukturaBookz polamiID,Title,Author,ISBNiAvailable. Dodaj konstruktorNewBook, który inicjuje książki jako dostępne.user.go: StrukturaUserz polamiID,Name,EmailiBorrowedBooks. Dodaj konstruktorNewUser.library.go: StrukturaLibraryz mapami książek i użytkowników oraz metodamiNewLibrary,AddBook,AddUser,BorrowiReturn. MetodaBorrowpowinna zwracać błędy w przypadku nieprawidłowego użytkownika, nieprawidłowej książki lub niedostępnej książki. MetodaReturnpowinna zwracać błędy w przypadku nieprawidłowego użytkownika, nieprawidłowej książki lub książki, która nie została wypożyczona.library_test.go: Tutaj napiszesz swoje funkcje testowe! Utwórz testy, które sprawdzą:TestBorrowSuccess: Sprawdź, czy wypożyczenie dostępnej książki powiedzie się (nie zostanie zwrócony błąd), książka stanie się niedostępna, a jej ID zostanie dodane do listy wypożyczonych książek użytkownikaTestBorrowUnavailable: Sprawdź, czy próba wypożyczenia już wypożyczonej książki zwróci błądTestBorrowInvalidUser: Sprawdź, czy próba wypożyczenia książki przez nieistniejącego użytkownika zwróci błądTestReturnSuccess: Sprawdź, czy zwrócenie wypożyczonej książki powiedzie się, książka ponownie stanie się dostępna, a jej ID zostanie usunięte z listy wypożyczonych książek użytkownika
Każdy test powinien skonfigurować własną bibliotekę z niezbędnymi książkami i użytkownikami, wykonać operację i sprawdzić wyniki za pomocą
t.Errorlubt.Errorf, gdy asercje nie przejdą.main.go: Uruchom testy ręcznie i wyświetl ich wyniki. Odczytaj nazwę testu do wykonania (borrow_success,borrow_unavailable,borrow_invalid_userlubreturn_success). Na podstawie nazwy testu skonfiguruj odpowiedni scenariusz i wyświetlPASS, jeśli wszystkie asercje przejdą, lubFAIL: [reason], jeśli któraś asercja nie przejdzie.
Otrzymasz następujące dane wejściowe:
- Nazwę testu:
borrow_success,borrow_unavailable,borrow_invalid_userlubreturn_success
W każdym teście użyj tych standardowych danych testowych:
- Książka: ID
B001, tytułGo Programming, autorJohn Doe, ISBN123-456 - Użytkownik: ID
U001, imięAlice, adres e-mailalice@test.com
Na przykład, dla danych wejściowych:
borrow_successWynik powinien wyglądać tak:
PASSA dla danych wejściowych:
borrow_unavailableWynik powinien wyglądać tak:
PASSA dla danych wejściowych:
borrow_invalid_userWynik powinien wyglądać tak:
PASSA dla danych wejściowych:
return_successWynik powinien wyglądać tak:
PASSDla borrow_success: Utwórz bibliotekę, dodaj książkę i użytkownika, wypożycz książkę, sprawdź, czy nie wystąpił błąd, sprawdź, czy książka jest niedostępna, i sprawdź, czy książka znajduje się na liście wypożyczonych książek użytkownika.
Dla borrow_unavailable: Utwórz bibliotekę, dodaj książkę i użytkownika, ustaw wartość Available książki na false, spróbuj ją wypożyczyć i sprawdź, czy został zwrócony błąd.
Dla borrow_invalid_user: Utwórz bibliotekę, dodaj tylko książkę (bez użytkownika), spróbuj ją wypożyczyć, używając ID użytkownika U001, i sprawdź, czy został zwrócony błąd.
Dla return_success: Utwórz bibliotekę, dodaj książkę i użytkownika, najpierw wypożycz książkę, a następnie ją zwróć. Sprawdź, czy nie wystąpił błąd, książka znów jest dostępna, a lista wypożyczonych książek użytkownika jest pusta.
Pisanie testów pozwala upewnić się, że system biblioteczny działa poprawnie, i daje pewność, że możesz wprowadzać zmiany bez psucia istniejących funkcji!
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
testName, _ := reader.ReadString('\n')
testName = strings.TrimSpace(testName)
// Standardowe dane testowe
// Książka: ID "B001", tytuł "Go Programming", autor "John Doe", ISBN "123-456"
// Użytkownik: ID "U001", imię "Alice", adres e-mail "alice@test.com"
switch testName {
case "borrow_success":
// TODO: Sprawdź, czy wypożyczenie dostępnej książki się powodzi
// 1. Utwórz bibliotekę, dodaj książkę i użytkownika
// 2. Wypożycz książkę
// 3. Sprawdź: brak błędu, książka niedostępna, użytkownik ma książkę na liście
// Wypisz "PASS", jeśli wszystkie testy przejdą, lub "FAIL: [reason]", jeśli którykolwiek się nie powiedzie
fmt.Println("FAIL: not implemented")
case "borrow_unavailable":
// TODO: Sprawdź, czy próba wypożyczenia niedostępnej książki zwraca błąd
// 1. Utwórz bibliotekę, dodaj książkę i użytkownika
// 2. Ustaw Available książki na false
// 3. Spróbuj wypożyczyć książkę
// 4. Sprawdź, czy zwrócono błąd
fmt.Println("FAIL: not implemented")
case "borrow_invalid_user":
// TODO: Sprawdź, czy próba wypożyczenia książki przez nieprawidłowego użytkownika zwraca błąd
// 1. Utwórz bibliotekę i dodaj tylko książkę (bez użytkownika)
// 2. Spróbuj wypożyczyć książkę, używając ID użytkownika "U001"
// 3. Sprawdź, czy zwrócono błąd
fmt.Println("FAIL: not implemented")
case "return_success":
// TODO: Sprawdź, czy zwrot wypożyczonej książki się powiedzie
// 1. Utwórz bibliotekę, dodaj książkę i użytkownika
// 2. Najpierw wypożycz książkę
// 3. Zwróć książkę
// 4. Sprawdź: brak błędu, książka jest dostępna, lista użytkownika jest pusta
fmt.Println("FAIL: not implemented")
default:
fmt.Println("FAIL: unknown test")
}
}
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP w Go
Pliki zewnętrzneObszar roboczy i moduły GoPakiety i importyNazwy eksportowane i nieeksportowaneWprowadzenie do OOP w GoStruktury jako klasyDefiniowanie metod dla strukturOdbiorniki wskaźnikowe i wartościoweInicjalizacja strukturFunkcje konstruktoraPodsumowanie – prosty kalkulator4Interfejsy
Wprowadzenie do interfejsówImplementacja niejawnaInterfejs jako kontraktPusty interfejs (any)Asercja typuPrzełącznik typówKompozycja interfejsówInterfejsy Stringer i ErrorPowtórka — kalkulator figur7Hermetyzacja
Pola eksportowane i nieeksportowaneHermetyzacja na poziomie pakietuMetody pobierające i ustawiająceUkrywanie informacji w GoPowtórka – dane studentów10Typy generyczne (Go 1.18+)
Wprowadzenie do typów generycznychParametry typówOgraniczenia typówStruktury generyczneObejście ograniczeń metod generycznychPodsumowanie — generyczna kolekcja2Typy i struktury w praktyce
Typy proste i złożoneDefiniowanie własnych typówTagi pól strukturStruktury anonimoweStruktury zagnieżdżoneWartości zerowe i domyślnePodsumowanie – książka kontaktów5Kompozycja zamiast dziedziczenia
Dlaczego Go nie ma dziedziczeniaPodstawy osadzania strukturPromowanie metodOsadzanie wielu strukturOsadzanie a agregacjaPrzesłanianie osadzonych metodPodsumowanie — hierarchia pracowników8Obsługa błędów i programowanie obiektowe
Interfejs błęduWłasne typy błędówOpakowywanie błędów (fmt.Errorf)Błędy wartowniczeerrors.Is() i errors.As()Panic, Defer i RecoverPodsumowanie — parser plików3Wskaźniki i pamięć
Podstawy wskaźników w GoWskaźniki do strukturPrzekazywanie przez wartość a przez referencjęFunkcja new()Odśmiecanie pamięci w GoPowtórka — kreator listy wiązanej6Polimorfizm w Go
Polimorfizm za pomocą interfejsówDuck typing w GoZasady spełniania interfejsówKolekcje polimorficzneWstrzykiwanie zależnościPowtórka — procesor płatności9Współbieżność i OOP
Podstawy goroutinesKanały i komunikacjaKanały buforowane i niebuforowaneInstrukcja selectsync.Mutex i sync.RWMutexsync.WaitGroupProjektowanie struktur bezpiecznych wątkowoPowtórka – pula workerów12Zaawansowane zagadnienia programowania obiektowego
Wzorzec opcji funkcyjnychWzorzec Builder w GoŁańcuchowe wywoływanie metodAliasy typów a definicje typówPodstawy refleksjiPrzegląd generowania kodu15Projekt: Zarządzanie biblioteką
Przegląd i struktura projektuStruktury książek i użytkownikówPoćwicz samodzielnie: Kompilator Go online