Test e integrazione
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 104 di 107.
Sfida
FacileCompletiamo il ciclo del nostro sistema di gestione della biblioteca scrivendo test che verificano che tutto funzioni correttamente! Creerai un file di test che convalida le funzionalità principali della tua biblioteca: assicurarti che i libri possano essere presi in prestito e restituiti correttamente e che le condizioni di errore siano gestite nel modo giusto.
Organizzerai il codice in cinque file:
book.go: la tua structBookcon i campiID,Title,Author,ISBNeAvailable. Includi il costruttoreNewBook, che inizializza i libri come disponibili.user.go: la tua structUsercon i campiID,Name,EmaileBorrowedBooks. Includi il costruttoreNewUser.library.go: la tua structLibrarycon map per libri e utenti, insieme ai metodiNewLibrary,AddBook,AddUser,BorroweReturn. Il metodoBorrowdovrebbe restituire errori per utente non valido, libro non valido o libro non disponibile. Il metodoReturndovrebbe restituire errori per utente non valido, libro non valido o libro non preso in prestito.library_test.go: qui scriverai le tue funzioni di test! Crea test che verifichino:TestBorrowSuccess: verifica che prendere in prestito un libro disponibile vada a buon fine (non venga restituito alcun errore), che il libro diventi non disponibile e che l'ID del libro venga aggiunto alla lista dei libri presi in prestito dall'utenteTestBorrowUnavailable: verifica che prendere in prestito un libro già preso in prestito restituisca un erroreTestBorrowInvalidUser: verifica che tentare di prendere in prestito un libro con l'ID di un utente inesistente restituisca un erroreTestReturnSuccess: verifica che restituire un libro preso in prestito vada a buon fine, che il libro torni disponibile e che il suo ID venga rimosso dalla lista dei libri presi in prestito dall'utente
Ogni test dovrebbe configurare la propria biblioteca con i libri e gli utenti necessari, eseguire l'operazione e controllare i risultati usando
t.Errorot.Errorfquando le asserzioni non vengono soddisfatte.main.go: esegui i test manualmente e riporta i risultati. Leggi il nome del test da eseguire (borrow_success,borrow_unavailable,borrow_invalid_useroreturn_success). In base al nome del test, configura lo scenario appropriato e stampaPASSse tutte le asserzioni vengono soddisfatte, oppureFAIL: [reason]se un'asserzione non viene soddisfatta.
Verrà fornito il seguente input:
- Un nome di test:
borrow_success,borrow_unavailable,borrow_invalid_useroreturn_success
Per ogni test, usa i seguenti dati di test standard:
- Libro: ID
B001, titoloGo Programming, autoreJohn Doe, ISBN123-456 - Utente: ID
U001, nomeAlice, emailalice@test.com
Per esempio, dato:
borrow_successIl tuo output dovrebbe essere:
PASSE dato:
borrow_unavailableIl tuo output dovrebbe essere:
PASSE dato:
borrow_invalid_userIl tuo output dovrebbe essere:
PASSE dato:
return_successIl tuo output dovrebbe essere:
PASSPer borrow_success: crea la biblioteca, aggiungi un libro e un utente, fai prendere in prestito il libro, verifica che non ci siano errori, verifica che il libro non sia disponibile e verifica che l'utente abbia il libro nella propria lista dei libri presi in prestito.
Per borrow_unavailable: crea la biblioteca, aggiungi un libro e un utente, imposta Available del libro su false, prova a farlo prendere in prestito e verifica che venga restituito un errore.
Per borrow_invalid_user: crea la biblioteca, aggiungi solo il libro (nessun utente), prova a farlo prendere in prestito con l'ID utente U001 e verifica che venga restituito un errore.
Per return_success: crea la biblioteca, aggiungi un libro e un utente, fai prendere in prestito il libro e poi restituiscilo; verifica che non ci siano errori, che il libro sia di nuovo disponibile e che la lista dei libri presi in prestito dall'utente sia vuota.
Scrivere test assicura che il sistema della biblioteca si comporti correttamente e ti dà la sicurezza necessaria per apportare modifiche senza compromettere le funzionalità esistenti!
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
testName, _ := reader.ReadString('\n')
testName = strings.TrimSpace(testName)
// Dati di test standard
// Libro: ID "B001", titolo "Go Programming", autore "John Doe", ISBN "123-456"
// Utente: ID "U001", nome "Alice", email "alice@test.com"
switch testName {
case "borrow_success":
// TODO: Verificare che il prestito di un libro disponibile riesca
// 1. Creare la biblioteca, aggiungere il libro e l'utente
// 2. Prendere in prestito il libro
// 3. Verificare: nessun errore, libro non disponibile, libro presente nell'elenco dell'utente
// Stampare "PASS" se tutte le verifiche riescono, oppure "FAIL: [reason]" se una fallisce
fmt.Println("FAIL: not implemented")
case "borrow_unavailable":
// TODO: Verificare che il prestito di un libro non disponibile restituisca un errore
// 1. Creare la biblioteca, aggiungere il libro e l'utente
// 2. Impostare Available del libro su false
// 3. Tentare di prendere il libro in prestito
// 4. Verificare che venga restituito un errore
fmt.Println("FAIL: not implemented")
case "borrow_invalid_user":
// TODO: Verifica che il prestito con un utente non valido restituisca un errore
// 1. Crea la biblioteca, aggiungi solo il libro (nessun utente)
// 2. Prova a prendere in prestito il libro con l'ID utente "U001"
// 3. Verifica che venga restituito un errore
fmt.Println("FAIL: not implemented")
case "return_success":
// TODO: Verifica che la restituzione di un libro preso in prestito riesca
// 1. Creare la biblioteca, aggiungere il libro e l'utente
// 2. Prendi prima in prestito il libro
// 3. Restituisci il libro
// 4. Verifica: nessun errore, libro disponibile, elenco dell'utente vuoto
fmt.Println("FAIL: not implemented")
default:
fmt.Println("FAIL: unknown test")
}
}
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker pool12Concetti avanzati di OOP
Pattern delle opzioni funzionaliPattern Builder in GoConcatenamento dei metodiAlias di tipo e definizioni a confrontoNozioni di base sulla reflectionPanoramica sulla generazione del codice15Progetto: Gestione della biblioteca
Panoramica e struttura del progettoStruct per libri e utentiEsercitati da solo: Compilatore Go online