Тестирование и интеграция
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 104 из 107.
Задание
ЛегкоДавайте завершим создание нашей системы управления библиотекой, написав тесты, которые проверят корректность её работы! Вы создадите файл тестов, проверяющий основную функциональность библиотеки: правильность выдачи и возврата книг, а также корректную обработку ошибок.
Вы распределите код по пяти файлам:
book.go: ваша структураBookс полямиID,Title,Author,ISBNиAvailable. Добавьте конструкторNewBook, который инициализирует книги как доступные.user.go: ваша структураUserс полямиID,Name,EmailиBorrowedBooks. Добавьте конструкторNewUser.library.go: ваша структураLibraryс отображениями для книг и пользователей, а также методамиNewLibrary,AddBook,AddUser,BorrowиReturn. МетодBorrowдолжен возвращать ошибки для недействительного пользователя, недействительной книги или недоступной книги. МетодReturnдолжен возвращать ошибки для недействительного пользователя, недействительной книги или книги, которая не была взята.library_test.go: здесь вы напишете функции тестов! Создайте тесты, которые проверяют:TestBorrowSuccess: проверьте, что выдача доступной книги проходит успешно (ошибка не возвращается), книга становится недоступной, а ID книги добавляется в список взятых пользователем книгTestBorrowUnavailable: проверьте, что попытка взять уже выданную книгу возвращает ошибкуTestBorrowInvalidUser: проверьте, что попытка взять книгу с несуществующим ID пользователя возвращает ошибкуTestReturnSuccess: проверьте, что возврат взятой книги проходит успешно, книга снова становится доступной, а ID книги удаляется из списка взятых пользователем книг
Каждый тест должен создавать собственную библиотеку с необходимыми книгами и пользователями, выполнять операцию и проверять результаты с помощью
t.Errorилиt.Errorf, если проверки не пройдены.main.go: запускайте тесты вручную и выводите результаты. Считайте имя теста для выполнения (borrow_success,borrow_unavailable,borrow_invalid_userилиreturn_success). В зависимости от имени теста настройте соответствующий сценарий и выведитеPASS, если все проверки пройдены, илиFAIL: [reason], если какая-либо проверка не пройдена.
Будет предоставлен следующий ввод:
- Имя теста:
borrow_success,borrow_unavailable,borrow_invalid_userилиreturn_success
Для каждого теста используйте следующие стандартные тестовые данные:
- Книга: ID
B001, названиеGo Programming, авторJohn Doe, ISBN123-456 - Пользователь: ID
U001, имяAlice, электронная почтаalice@test.com
Например, если задано:
borrow_successВаш вывод должен быть таким:
PASSА если задано:
borrow_unavailableВаш вывод должен быть таким:
PASSА если задано:
borrow_invalid_userВаш вывод должен быть таким:
PASSА если задано:
return_successВаш вывод должен быть таким:
PASSДля borrow_success: создайте библиотеку, добавьте книгу и пользователя, возьмите книгу, проверьте отсутствие ошибки, проверьте, что книга недоступна, и проверьте, что у пользователя есть книга в списке взятых книг.
Для borrow_unavailable: создайте библиотеку, добавьте книгу и пользователя, установите для Available книги значение false, попробуйте взять книгу и проверьте, что возвращена ошибка.
Для borrow_invalid_user: создайте библиотеку, добавьте только книгу (без пользователя), попробуйте взять книгу с ID пользователя U001 и проверьте, что возвращена ошибка.
Для return_success: создайте библиотеку, добавьте книгу и пользователя, сначала возьмите книгу, затем верните её, проверьте отсутствие ошибки, проверьте, что книга снова доступна, и проверьте, что список взятых пользователем книг пуст.
Написание тестов гарантирует корректную работу вашей библиотечной системы и позволит вам уверенно вносить изменения, не нарушая существующую функциональность!
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
testName, _ := reader.ReadString('\n')
testName = strings.TrimSpace(testName)
// Стандартные тестовые фикстуры
// Книга: ID "B001", Title "Go Programming", Author "John Doe", ISBN "123-456"
// Пользователь: ID "U001", Name "Alice", Email "alice@test.com"
switch testName {
case "borrow_success":
// TODO: Протестировать, что взятие доступной книги проходит успешно
// 1. Создать библиотеку, добавить книгу и пользователя
// 2. Взять книгу
// 3. Проверить: нет ошибки, книга недоступна, у пользователя есть книга в списке
// Вывести "PASS", если все пройдено, или "FAIL: [reason]", если что-то не удалось
fmt.Println("FAIL: not implemented")
case "borrow_unavailable":
// TODO: Протестировать, что взятие недоступной книги возвращает ошибку
// 1. Создать библиотеку, добавить книгу и пользователя
// 2. Установить Available книги в false
// 3. Попытаться взять книгу
// 4. Проверить, что возвращается ошибка
fmt.Println("FAIL: not implemented")
case "borrow_invalid_user":
// TODO: Проверить, что заимствование с недействительным пользователем возвращает ошибку
// 1. Создать библиотеку, добавить только книгу (без пользователя)
// 2. Попытаться взять книгу с ID пользователя "U001"
// 3. Проверить, что возвращается ошибка
fmt.Println("FAIL: not implemented")
case "return_success":
// TODO: Проверить, что возврат взятой книги проходит успешно
// 1. Создать библиотеку, добавить книгу и пользователя
// 2. Сначала взять книгу
// 3. Вернуть книгу
// 4. Проверить: нет ошибки, книга доступна, список пользователя пуст
fmt.Println("FAIL: not implemented")
default:
fmt.Println("FAIL: unknown test")
}
}
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП в Go
Внешние файлыРабочее пространство и модули GoПакеты и импортыЭкспортируемые и неэкспортируемые именаВведение в ООП в GoСтруктуры как классыОпределение методов структурПолучатели-указатели и получатели-значенияИнициализация структурФункции-конструкторыИтоги — Простой калькулятор4Интерфейсы
Введение в интерфейсыНеявная реализацияИнтерфейс как контрактПустой интерфейс (any)Утверждение типаПереключатель типовКомпозиция интерфейсовИнтерфейсы Stringer и ErrorПовторение: Калькулятор фигур7Инкапсуляция
Экспортируемые и неэкспортируемые поляИнкапсуляция на уровне пакетовГеттеры и сеттерыСокрытие информации в GoИтоги — Записи о студентах10Обобщения (Generics) (Go 1.18+)
Введение в GenericsПараметры типовОграничения типовОбобщенные структурыОбходной путь для обобщенных методовИтоги — Обобщенная коллекция13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy2Глубокое погружение в типы и структуры
Базовые и составные типыОпределение пользовательских типовТеги структурАнонимные структурыВложенные структурыНулевые значения и значения по умолчаниюПовторение — Контактная книга5Композиция вместо наследования
Почему в Go нет наследованияОсновы встраивания структурПродвижение методовВстраивание нескольких структурВстраивание против агрегацииЗатенение встроенных методовИтоги — Иерархия сотрудников8Обработка ошибок и ООП
Интерфейс errorПользовательские типы ошибокОбертывание ошибок (fmt.Errorf)Sentinel-ошибкиerrors.Is() и errors.As()Panic, Defer и RecoverИтоги — Парсер файлов11Стандартная библиотека и ООП
io.Reader и io.Writersort.InterfaceИнтерфейс fmt.Stringerencoding/json со структурамиИнтерфейс http.HandlerПовторение: модели REST API14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикMiddleware как Декоратор3Указатели и память
Основы указателей в GoУказатели на структурыПередача по значению и по ссылкеФункция new()Сборка мусора в GoПовторение: Конструктор связного списка6Полиморфизм в Go
Полиморфизм через интерфейсыУтиная типизация в GoПравила реализации интерфейсовПолиморфные коллекцииВнедрение зависимостейИтоги — Обработчик платежей9Конкурентность и ООП
Основы горутинКаналы и взаимодействиеБуферизованные и небуферизованные каналыОператор selectsync.Mutex и sync.RWMutexsync.WaitGroupПроектирование потокобезопасных структурПовторение — Worker Pool12Продвинутые концепции ООП
Паттерн функциональных опцийПаттерн Builder в GoЦепочки вызовов методовПсевдонимы и определения типовОсновы рефлексииОбзор генерации кода15Проект: Управление библиотекой
Обзор и структура проектаСтруктуры Book и UserПотренируйтесь самостоятельно: Онлайн-компилятор Go