Подробное модульное тестирование Master Go: полное руководство от основ до продвинутых
Подробное модульное тестирование Master Go: полное руководство от основ до продвинутых

Предисловие

В разработке программного обеспечения модульное тестирование — это аспект, который нельзя игнорировать. Это не только помогает разработчикам обнаруживать и решать потенциальные проблемы на ранних этапах кодирования, но также обеспечивает надежность, удобство сопровождения и общее качество кода, что очень важно для повышения эффективности разработки и снижения затрат на последующее обслуживание.

Тестовые примеры, которые вы написали ранее, особенно важны, когда вы позже оптимизируете функцию или метод. Если тест пройдет успешно, вы почувствуете облегчение от того, что оптимизированный код не нарушит существующую функциональность; если тест не пройден, это тоже хорошо, потому что вы вовремя обнаружили потенциальную проблему и избежали риска онлайн-сбоя.

существовать Go на языке,go test команда и testing Пакет предоставляет простой и мощный механизм тестирования, позволяющий Gopher Умение легко писать и выполнять тест-кейсы. В этой статье будет подробно описано, как использовать Go на языке testing Обсуждается пакет для написания эффективных модульных тестов go test Общие параметры команд и их функций, а также повышение качества кода с помощью практических методов подтестов и табличного тестирования. В статье также будет представлено TestMain Сценарии использования функции, Библиотека инструментов внешнего тестированиянравиться testify Приложения, а также часто используемые методы утверждения.

Вы готовы? Возьмите чашку любимого кофе или чая и узнайте, прочитав эту статью.

Базовая структура теста

  • Go Файлы языковых тестов обычно помещаются в тот же пакет, что и тестируемый исходный файл, а имя файла заканчивается на _test.go окончание。например,reverse.go Тестовый файл для файла должен называться reverse_test.go。так go test Команда будет правильно распознана и тест выполнен.
  • Каждая тестовая функция должна иметь имя Test начинается, за которым следует имя функции, начинающееся с заглавной буквы. Сигнатура тестовой функции: func (t *testing.T)t *testing.T Параметр, используемый для управления статусом теста и Отчет сбоя теста.
Язык кода:bash
копировать
├── stringx/
│   ├── reverse.go
│   └── reverse_test.go

Простой случай

существовать reverse.go внутри:

Язык кода:go
копировать
package stringx

func Reverse(s string) string {
	r := []rune(s)
	for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
		r[i], r[j] = r[j], r[i]
	}
	return string(r)
}

существовать reverse_test.go внутри:

Язык кода:go
копировать
package stringx

import (
	"testing"
)

func TestReverse(t *testing.T) {
	got := Reverse("Чен Минён")
	if got != «Ён Мин Чен» {
		t.Errorf("expected Юн Мин Чен, but got %s", got)
	}
}

когда Reverse Если возвращаемый результат неожиданный, используйте t.Errorf Метод сообщает о неудачном тесте и печатает соответствующую информацию о параметрах.

существовать stringx Выполнить в каталоге go test Заказ:

Язык кода:bash
копировать
$ go test
PASS
ok      test_example/stringx    0.166s

Протестируйте часто используемые параметры и их описания.

  • -v
    • Функция: отображение подробных результатов теста,Включает статус выполнения каждого тестового примера (название тестовой функции и статус прохождения/неудачи).
    • Пример:go test -v
Язык кода:bash
копировать
$ go test -v       
=== RUN   TestReverse
--- PASS: TestReverse (0.00s)
PASS
ok      test_example/stringx    0.284s
  • -cover
    • Функция: запускать тесты и отображать краткую статистику покрытия кода.
    • Пример:go test -cover
Язык кода:bash
копировать
$ go test -cover
PASS
coverage: 100.0% of statements
ok      test_example/stringx    0.174s
  • -run <regex>
    • Функция: Просто беги соответствует указанной функции проверки регулярного выражения.
    • Пример:go test -run ^TestFunction$ Просто беги TestFunction
  • -bench <regex>
    • эффект:Просто беги тест на соответствие регулярным выражениям (названия функций обычно начинаются с Benchmark начало).
    • Пример:go test -bench . Запустите все тесты.
  • -benchmem
    • Эффект: существуют при запуске тестов производительности.,Отчет Статистика распределения памяти.
    • Пример:go test -bench . -benchmem
  • -coverprofile=<filename>
    • Функция: создать подробный отчет о покрытии кода и сохранить его в указанный файл.
    • Пример:go test -coverprofile=coverage.out
  • -covermode=<mode>
    • Функция: указать режим покрытия.,Есть три режима:
      • set: Подсчитайте, какие операторы выполняются (по умолчанию).
      • count: Подсчитайте, сколько раз выполняется каждый оператор.
      • atomic: Подсчитайте количество выполнений операторов и обеспечьте многопоточную безопасность.
    • Пример:go test -covermode=count
  • -timeout=<duration>
    • Функция: установите тайм-аут выполнения теста, чтобы предотвратить его зависание на длительное время. Тайм-аут по умолчанию: 10 минута.
    • Пример:go test -timeout=30s
  • -short
    • Функция: сообщить тестовой программе, чтобы она пропускала более длительные тесты. Часто используется для сокращения времени тестирования.
    • Пример:go test -short
  • -parallel=<n>
    • Функция: Установить максимальное количество тестов параллельного выполнения. Goroutine количество.
    • Пример:go test -parallel=4
  • -race
    • Функция: включение обнаружения конкуренции данных, подходит для тестирования параллельных программ.
    • Пример:go test -race
  • -count=<n>
    • Функция: укажите количество повторных запусков теста, обычно используемое для обнаружения спорадических ошибок.
    • Пример:go test -count=3
  • -json
    • Функция: Вывод результата теста в виде JSON формат, подходящий для использования с CI Системная интеграция или анализ журналов.
    • Пример:go test -json
  • -failfast
    • Функция: существует Немедленно прекращает выполнение оставшихся тестов, если тест не пройден.
    • Пример:go test -failfast

Часто используемые комбинации:

  • Анализ покрытия кода и создание отчетов HTML
Язык кода:bash
копировать
go test -coverprofile=coverage.out && go tool cover -html=coverage.out
  • Запустите все тесты и выведите подробную информацию
Язык кода:bash
копировать
go test -v ./...

Эти параметры можно гибко комбинировать в соответствии с требованиями тестирования, что помогает улучшить покрытие тестированием, анализ производительности и возможности отладки.

Дополнительные параметры доступны, запустив go help test команда для просмотра.

Табличное тестирование для подтестов

лист Тест-драйв(Table-driven tests)да Go на языке Общие тестовые шаблоны,Он работает путем организации нескольких тестовых случаев в один (обычно срез).,Используйте цикл для последовательного выполнения каждого тестового примера.,Тем самым улучшая читаемость и ремонтопригодность кода.

Язык кода:go
копировать
package stringx

import (
	"testing"
)

func TestReverse(t *testing.T) {
	testCases := []struct {
		name     string
		input    string
		expected string
	}{
		{"empty string", "", ""},                     // Проверка пустой строки
		{"reverse Chinese characters", "Чен Минён", «Ён Мин Чен»}, // Проверьте китайские иероглифы
		{"reverse English word", "Hello", "olleH"},   // Проверьте английские слова
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			got := Reverse(tc.input)
			if got != tc.expected {
				t.Errorf("expected %s, but got %s", tc.expected, got)
			}
		})
	}
}

Объяснение кода:

  • листtestCases Срез, содержащий несколько структур, каждая структура представляет собой тестовый пример.
  • проверка контура:проходить for _, tc := range testCases Прокрутите каждый тестовый пример.
  • субтест:проходить t.Run(tc.name, ...) Метод создает субтест для каждого тестового примера.,При выполнении подобных тестов существуют,Имя каждого субтестирезультата можно увидеть в информации, выдаваемой консолью существования.,Удобен для отладки и устранения неполадок.

Преимущества табличного тестирования

  • Уменьшите дублирование кода: Избегайте написания отдельного теста для каждого тестового примера. Базовую логику тестирования всех тестовых примеров можно использовать повторно, тем самым уменьшая избыточность кода.
  • Улучшите удобство сопровождения тестового кода: Если вам нужно добавить новые тестовые примеры,Просто добавьте новые строки данных в существующий лист (срез).,Нет необходимости изменять базовую логику тестирования.
  • Улучшите читаемость кода: Разделение тестовых примеров и основной тестовой логики делает тестовый код более кратким и простым для понимания.

Функция TestMain

TestMain В существующем тестовом модуле есть специальная функция, которая используется для выполнения глобальной инициализации и очистки до или после существующего теста. Это точка входа для всего тестового пакета. существовать бежать go test После команды сначала проверяется, определен ли тестовый файл пакета. TestMain Функция, если она присутствует, будет вызвана для выполнения теста. если не TestMain функция, все будут вызываться по умолчанию TextXxx функция.

TestMain Сигнатура функции следующая:

Язык кода:go
копировать
TestMain(m *testing.M)

TestMain Функции обычно сочетаются с setup и teardown Функция используется вместе,Первый используется для выполнения некоторой подготовительной работы перед выполнением теста (например, подключения к базе данных).,Конфигурация инициализации и т. д.),Последний используется для выполнения некоторой очистки после выполнения теста (например, закрытия ссылки на базу данных).,удалить временные файлы и т. д.).

Вот пример кода:

Язык кода:go
копировать
package stringx

import (
	"fmt"
	"os"
	"testing"
)

func TestReverse(t *testing.T) {
	testCases := []struct {
		name     string
		input    string
		expected string
	}{
		{"empty string", "", ""},                     // Проверка пустой строки
		{"reverse Chinese characters", "Чен Минён", «Ён Мин Чен»}, // Проверьте китайские иероглифы
		{"reverse English word", "Hello", "olleH"},   // Проверьте английские слова
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			got := Reverse(tc.input)
			if got != tc.expected {
				t.Errorf("expected %s, but got %s", tc.expected, got)
			}
		})
	}
}

func setup() {
	fmt.Println("Before running tests")
}

func teardown() {
	fmt.Println("After running tests")
}

func TestMain(m *testing.M) {
	setup()
	code := m.Run()
	teardown()
	os.Exit(code)
}

ключ Объяснение кода:

  • m.Run():проходить Этот метод выполняет все тестыфункция.он возвращает целое число,Код состояния, указывающий на тест,Обычно 0 Указывает на успех, а не 0 Указывает на неудавшийся тест.
  • os.Exit(code) : Вернитесь к результатам теста, чтобы убедиться в правильности статуса выхода.

Библиотека инструментов внешнего тестирования

существуют В предыдущем примере кода мы использовали != оператор для сравнения результат и ожидаемое значение Они не равны?,Это возможно для базовых типов данных. Однако,когда Нам нужно сравнивать как кусочки、map При ожидании сложных структур данных используйте их напрямую != больше не применимо, и для выполнения сравнения необходимо написать дополнительную логику. Чтобы решить эту проблему, мы можем использовать сторонние библиотеки, такие как testify,чтобы упростить эти операции сравнения.

библиотека инструментов для дачи показаний

testify дасуществовать Go Широко используемая сторонняя библиотека тестирования на языке, предоставляющая несколько удобных методов утверждения и поддержку набора тестов. mock функция, значительно упрощающая написание тестового кода. по сравнению с Go Входит в комплект testing Библиотека,testify Предоставляет более богатые функции для оценки утверждений, особенно когда существование более удобно при работе со сложными структурами данных.

Мы можем установить его с помощью следующей команды testify Модуль:

Язык кода:bash
копировать
go get github.com/stretchr/testify

Далее мы можем преобразовать часть кода, показанного ранее:

Язык кода:go
копировать
if got != tc.expected {
    t.Errorf("expected %s, but got %s", tc.expected, got)
}

Переписано как:

Язык кода:go
копировать
assert.Equalf(t, tc.expected, got, "expected %s, but got %s", tc.expected, got)

Если утверждение «когда» не выполнено, будет напечатана следующая информация.

свидетельствовать о часто используемых методах утверждения

testify/assert Предоставляет множество функций утверждения, упрощающих выполнение сложных операций сравнения. Ниже приведены некоторые часто используемые функции утверждения:

  • assert.Equal Утверждайте, что два значения равны, применимо к базовым типам, структурам и т. д.
Язык кода:go
копировать
assert.Equal(t, «Ён Мин Чен», Reverse("Чен Минён"))  // Reverse("Чен Минён" Равно ли это «Ён Мин Чен»
  • assert.NotNil Утверждать, что объект не nil
Язык кода:go
копировать
var obj = &struct{}{}
assert.NotNil(t, obj)
  • assert.True Условие утверждения true
Язык кода:go
копировать
var b bool
assert.True(t, b)
  • assert.False Условие утверждения false
Язык кода:go
копировать
var b bool
assert.False(t, b)
  • assert.ElementsMatch Используется для сравнения того, содержат ли два среза одни и те же элементы, независимо от порядка элементов.
Язык кода:go
копировать
expected := []int{1, 2, 3, 4}
actual := []int{4, 3, 2, 1}
assert.ElementsMatch(t, expected, actual)  
  • assert.Len набор утверждений(как нарезанный、map и т. д.) равно указанному значению.
Язык кода:go
копировать
assert.Len(t, []int{1, 2, 3}, 3)

Дополнительную информацию о функциях см. testify/assert

Кроме assert Сумка,testify В библиотеке также есть еще один require пакет, это связано с assert Функции пакетов аналогичны и используются для утверждений. Основное различие между ними заключается в том, как бороться с неудачными тестами:

  • когда утверждение терпит неудачу,assert Пакет зарегистрирует сбой, но тест продолжит выполнение последующего кода.
Язык кода:go
копировать
assert.Equal(t, "Чен Минён", Reverse("Чен Минён")) // Регистрируйте сбой при сбое, но продолжайте выполнение кода, стоящего за ним.
assert.Equal(t, «Ён Мин Чен», Reverse("Чен Минён")) // Это утверждение все равно будет выполнено
  • когда утверждение терпит неудачу,require Пакет немедленно прекратит выполнение предварительного теста и выдаст сообщение об ошибке. Тест не продолжает выполнять последующий код.
Язык кода:go
копировать
require.Equal(t, "Чен Минён", Reverse("Чен Минён")) // Немедленно прекратить выполнение последующего кода в случае сбоя.
require.Equal(t, «Ён Мин Чен», Reverse("Чен Минён")) // Если предыдущее утверждение не выполнено, это не будет выполнено.

Мы можем выбрать подходящий пакет в соответствии с конкретным сценарием тестирования, например, когда некоторые ключевые шаги должны гарантировать, что тест будет завершен, если он не пройден. require,И за не такключ Можно использовать шаги assert,Чтобы тест мог продолжать выполняться и получать больше результатов.

краткое содержание

Я считаю, что благодаря этой статье вы научились существовать. Go Язык для эффективного написания Модульное тестирование。от Базовая структура тест к листу тестирования драйверов с использованием внешних библиотек testify для более гибких операций утверждения и для go test Владение командами и их часто используемыми параметрами.

Модульное тестирование — не только ключевое звено в улучшении качества кода,Это также важная практика для обеспечения долгосрочной стабильности проекта. Будь то личный проект или большая командная разработка,Каждый должен обратить внимание на важность тестирования на протяжении всего процесса разработки.


Здравствуйте, я Чэнь Мингён, разработчик, который любит технологии и готов ими делиться, а также энтузиаст открытого исходного кода.

Путь к успеху не переполнен. Вы заинтересованы в поиске партнера?

Следуйте за мной, добавляйте меня в друзья, учитесь и совершенствуйтесь вместе!

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose