Testes e integração
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 104 de 107.
Desafio
FácilVamos completar o ciclo do nosso Sistema de Gerenciamento de Biblioteca escrevendo testes que verifiquem se tudo funciona corretamente! Você criará um arquivo de teste que valida a funcionalidade principal da sua biblioteca: garantindo que os livros possam ser emprestados e devolvidos corretamente e que as condições de erro sejam tratadas adequadamente.
Você organizará seu código em cinco arquivos:
book.go: sua structBookcom os camposID,Title,Author,ISBNeAvailable. Inclua o construtorNewBook, que inicializa os livros como disponíveis.user.go: sua structUsercom os camposID,Name,EmaileBorrowedBooks. Inclua o construtorNewUser.library.go: sua structLibrarycom mapas para livros e usuários, juntamente com os métodosNewLibrary,AddBook,AddUser,BorroweReturn. O métodoBorrowdeve retornar erros para usuário inválido, livro inválido ou livro indisponível. O métodoReturndeve retornar erros para usuário inválido, livro inválido ou livro não emprestado.library_test.go: é aqui que você escreverá suas funções de teste! Crie testes que verifiquem:TestBorrowSuccess: verifique se o empréstimo de um livro disponível é bem-sucedido (nenhum erro é retornado), se o livro fica indisponível e se o ID do livro é adicionado à lista de livros emprestados do usuárioTestBorrowUnavailable: verifique se o empréstimo de um livro que já foi emprestado retorna um erroTestBorrowInvalidUser: verifique se o empréstimo com um ID de usuário inexistente retorna um erroTestReturnSuccess: verifique se a devolução de um livro emprestado é bem-sucedida, se o livro fica disponível novamente e se o ID do livro é removido da lista de livros emprestados do usuário
Cada teste deve configurar sua própria biblioteca com os livros e usuários necessários, realizar a operação e verificar os resultados usando
t.Errorout.Errorfquando as asserções falharem.main.go: execute seus testes manualmente e informe os resultados. Leia o nome do teste a ser executado (borrow_success,borrow_unavailable,borrow_invalid_useroureturn_success). Com base no nome do teste, configure o cenário apropriado e exibaPASSse todas as asserções passarem ouFAIL: [reason]se alguma asserção falhar.
A seguinte entrada será fornecida:
- Um nome de teste:
borrow_success,borrow_unavailable,borrow_invalid_useroureturn_success
Para cada teste, use estes dados de teste padrão:
- Livro: ID
B001, títuloGo Programming, autorJohn Doe, ISBN123-456 - Usuário: ID
U001, nomeAlice, e-mailalice@test.com
Por exemplo, dada a entrada:
borrow_successSua saída deve ser:
PASSE dada a entrada:
borrow_unavailableSua saída deve ser:
PASSE dada a entrada:
borrow_invalid_userSua saída deve ser:
PASSE dada a entrada:
return_successSua saída deve ser:
PASSPara borrow_success: crie a biblioteca, adicione o livro e o usuário, empreste o livro, verifique se não há erro, verifique se o livro está indisponível e verifique se o usuário tem o livro em sua lista de livros emprestados.
Para borrow_unavailable: crie a biblioteca, adicione o livro e o usuário, defina Available do livro como false, tente emprestá-lo e verifique se um erro é retornado.
Para borrow_invalid_user: crie a biblioteca, adicione apenas o livro (sem usuário), tente realizar o empréstimo com o ID de usuário U001 e verifique se um erro é retornado.
Para return_success: crie a biblioteca, adicione o livro e o usuário, empreste o livro primeiro e depois devolva-o, verifique se não há erro, verifique se o livro está disponível novamente e verifique se a lista de livros emprestados do usuário está vazia.
Escrever testes garante que seu sistema de biblioteca se comporte corretamente e dá a você confiança para fazer alterações sem quebrar funcionalidades existentes!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
testName, _ := reader.ReadString('\n')
testName = strings.TrimSpace(testName)
// Fixtures de teste padrão
// Livro: ID "B001", Title "Go Programming", Author "John Doe", ISBN "123-456"
// Usuário: ID "U001", Name "Alice", Email "alice@test.com"
switch testName {
case "borrow_success":
// TODO: Testar que o empréstimo de um livro disponível é bem-sucedido
// 1. Crie a biblioteca, adicione o livro e o usuário
// 2. Empreste o livro
// 3. Verifique: sem erro, livro indisponível, usuário tem o livro na lista
// Imprima "PASS" se todos passarem, ou "FAIL: [reason]" se algum falhar
fmt.Println("FAIL: not implemented")
case "borrow_unavailable":
// TODO: Testar que o empréstimo de um livro indisponível retorna erro
// 1. Crie a biblioteca, adicione o livro e o usuário
// 2. Defina Available do livro como false
// 3. Tente emprestar
// 4. Verifique que um erro é retornado
fmt.Println("FAIL: not implemented")
case "borrow_invalid_user":
// TODO: Teste que emprestar com usuário inválido retorna erro
// 1. Crie a biblioteca, adicione apenas o livro (sem usuário)
// 2. Tente emprestar com o ID de usuário "U001"
// 3. Verifique se um erro é retornado
fmt.Println("FAIL: not implemented")
case "return_success":
// TODO: Teste que devolver um livro emprestado tem sucesso
// 1. Crie a biblioteca, adicione o livro e o usuário
// 2. Empreste o livro primeiro
// 3. Devolva o livro
// 4. Verifique: sem erro, livro disponível, lista do usuário vazia
fmt.Println("FAIL: not implemented")
default:
fmt.Println("FAIL: unknown test")
}
}
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosWorkspace e Módulos do GoPacotes e ImportsNomes Exportados vs. Não ExportadosIntrodução à OOP em GoStructs como ClassesDefinindo Métodos em StructsReceptores de Ponteiro vs. de ValorInicialização de StructsFunções ConstrutorasRecapitulação — Calculadora Simples4Interfaces
Introdução às InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Asserção de TipoSwitch de TipoComposição de InterfacesInterfaces Stringer e ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs. Não ExportadosEncapsulamento no Nível de PacoteMétodos Getters e SettersOcultação de Informações em GoRecapitulação - Registros de Alunos10Genéricos (Go 1.18+)
Introdução aos genéricosParâmetros de tipoRestrições de tipoStructs genéricasAlternativa para métodos genéricosRecapitulação - Coleção genérica13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão Abstract FactoryPadrão ObserverPadrão Strategy2Tipos e Structs em Profundidade
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosTags de StructStructs AnônimasStructs AninhadasValores Zero e PadrõesRecapitulação - Livro de Contatos5Composição em vez de herança
Por que Go não tem herançaNoções básicas de incorporação de structsPromoção de métodosIncorporação de várias structsIncorporação vs agregaçãoOcultação de métodos incorporadosRecapitulação - Hierarquia de funcionários8Tratamento de Erros e OOP
A interface errorTipos de Erro PersonalizadosEncapsulamento de Erros (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - Analisador de Arquivos3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs. ReferênciaA Função new()Coleta de Lixo em GoRecapitulação - Construtor de Lista Ligada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfacesColeções PolimórficasInjeção de DependênciasRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e comunicaçãoCanais com e sem bufferInstrução selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de structs thread-safeRevisão - Worker Pool12Conceitos Avançados de OOP
Padrão de Opções FuncionaisPadrão Builder em GoEncadeamento de MétodosAliases de Tipos vs. DefiniçõesNoções Básicas de ReflectionVisão Geral da Geração de Código15Projeto: Gerenciamento de Biblioteca
Visão geral e estrutura do projetoStructs de livros e usuáriosPratique por conta própria: Compilador de Go online