Go: Система тестирования на основе BDD: введение и практика Ginkgo
Go: Система тестирования на основе BDD: введение и практика Ginkgo

Введение

В статье «Как эффективно тестировать код Go» мы говорили о модульном тестировании и предлагали решения для интерфейсных и фиктивных зависимостей, позволяющие решить две основные проблемы: развязку и зависимость. В то же время в этой статье также обсуждаются некоторые практические инструменты тестирования в области Go, читатели могут ее прочитать. В центре внимания модульного тестирования находится логическая единица кода, обычно объект или конкретная функция. Мы можем написать достаточное количество модульных тестов, чтобы гарантировать качество кода. Когда функции изменяются или код подвергается рефакторингу, достаточное количество случаев модульного тестирования может дать нам достаточную уверенность. Над модульными тестами находятся спецификации разработки. В гибкой разработке программного обеспечения часто встречаются два человека: разработка через тестирование (TDD) и разработка через поведение (BDD). Это не только практики и методы, но и методологии проектирования.

1. TDD

Основная идея TDD — продвигать всю разработку посредством тестирования. Принцип состоит в том, чтобы писать сценарии модульного тестирования до разработки функционального кода. Содержит следующие пять шагов:

  • Разработчики сначала пишут несколько вариантов использования,
  • Запустите этот тест,Но этот тест явно провалится,Потому что бизнес-логика в тестовом варианте использования еще не реализована.
  • Детали кода реализации
  • Если разработчик успешно реализует код, все тесты будут пройдены.
  • Своевременно проводите рефакторинг бизнес-кода,Если новый код работает неправильно,Соответствующий тестовый файл также не будет работать.

Когда необходимо разработать новые функции, описанные выше шаги повторяются. Процесс выглядит так, как показано ниже.

Есть интересный репозиторий на Github: Learn-go-with-tests, предназначенный для изучения TDD с помощью Go.

2. BDD

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

3. Ginkgo

Ginkgo — это среда тестирования BDD на языке Go, призванная помочь разработчикам писать выразительные и комплексные тесты. Ginkgo интегрируется с собственными библиотеками Go, что означает, что вы можете запускать набор тестов Ginkgo через . В то же время он также совместим с набором утверждений и макетов, а также с богатым набором тестов для проверки. Но Ginkgo рекомендует использовать его с библиотекой gomega.

10 часто используемых модулей Ginkgo: It, Context, Describe, BeforeEach, AfterEach, JustBeforeEach, BeforeSuite, AfterSuite, By, Fail

  • Базовая единица примера Itdatest,То есть код, который он содержит, считается вариантом использования.
  • Функция ContextиDescribe заключается в категоризации одного или нескольких экземпляров.
  • BeforeEachда Выполняйте этот код перед выполнением каждого экземпляра теста.
  • AfterEachда Выполняйте этот код после выполнения каждого экземпляра теста.
  • JustBeforeEachда выполняется после выполнения BeforeEach и до выполнения тестового примера.
  • BeforeSuiteда выполняется до выполнения тестового набора, то есть до выполнения тестовых примеров в папке.
  • AfterSuiteда выполняется после выполнения тестового набора, то есть после выполнения тестовых примеров в папке.
  • Byда Распечатать информацию,Содержимое может быть только строкой,Будет распечатано только в том случае, если тестовый пример не пройден.,Обычно используется для отладки и поиска проблем.
  • Неудачный далоготип Этот тестовый пример завершается неудачей и печатает содержащуюся в нем информацию.
  • Существует также Specify, который имеет точно такую ​​же функцию, что и It, и это его аббревиатура.

1. Практика гинкго

1. Установите Гинкго
Язык кода:javascript
копировать
go get github.com/onsi/ginkgo/ginkgo 
go get github.com/onsi/gomega/...
2. Используйте

Создайте тестовую папку, например, example, войдите в папку, выполните команду ginkgo bootstrap, чтобы сгенерировать файл шаблона, имя файла — example_suite_test.go, в нем есть функция ввода для выполнения примера создания гинкго, пример не требуется. написано, по умолчанию используется имя текущей папки, сгенерируйте тест. Пример файла шаблона example_test.go добавляет суффикс _test, чтобы отличить его от существующего кода в текущей папке. Код example_test.go по умолчанию импортирует текущую папку.

Язык кода:javascript
копировать
var _ = Describe(“Book”, func() { 
	var ( 
		book Book 
		err error 	
		json string 
	)
	BeforeEach(func() { 
		json = `{ 
			"title":"Les Miserables", 
			"author":"Victor Hugo", 
			"pages":1488 
		}` 
	})
	
	JustBeforeEach(func() { 
		book, err = NewBookFromJSON(json) 
	})
	
	AfterEach(func() { 
		By("End One Test") 
	})
	
	Describe("loading from JSON", func() { 
		Context("when the JSON parses succesfully", func() { 
			It("should populate the fields correctly", func() { 
				Expect(book.Title).To(Equal("Les Miserables")) 
				Expect(book.Author).To(Equal("Victor Hugo")) 
				Expect(book.Pages).To(Equal(1488)) 
			}) 
			It("should not error", func() { 
				Expect(err).NotTo(HaveOccurred()) 
			}) 
		}) 
		Context("when the JSON fails to parse", func() { 
			BeforeEach(func() { 
				json = `{ 
					"title":"Les Miserables", 
					"author":"Victor Hugo", 
					"pages":1488oops 
				}` 
			}) 
			It("should return the zero-value for the book", func() { 
				Expect(book).To(BeZero()) 
			}) 
			It("should error", func() { 
				if err != nil { 
					Fail("This Case Failed") 
				} 
			})
		}) 
	})
	Describe("Extracting the author's last name", func() { 
		It("should correctly identify and return the last name", func(){
			Expect(book.AuthorLastName()).To(Equal("Hugo")) 
		}) 
	}) 
})

Как видите, сначала определяются глобальные переменные book, err и json. Пять тестовых примеров разделены на две основные категории, различающиеся двумя описаниями. Первая категория разделена на две небольшие категории, различающиеся контекстом. Каждый It содержит тестовый пример. Состоит из двух BeforeEach, каждый из которых работает только в пределах текущего домена. Последовательность выполнения — это последовательное выполнение одного и того же уровня и выполнение разных уровней от внешнего слоя к внутреннему. AfterEach правило меняется на противоположное. AfterEach обычно используется для очистки данных после завершения выполнения тестового примера, а также может использоваться для оценки результатов. Старайтесь не присваивать значения переменным в var, поскольку каждый раз при выполнении тестового примера значение глобальная переменная может быть изменена, что вызовет проблемы для последующих тестовых примеров Influence, ее правильнее записать в BeforeEach.

Язык кода:javascript
копировать
func TestBooks(t *testing.T) { 
	RegisterFailHandler(Fail) 
	RunSpecs(t, "Books Suite") 
}

var _ = BeforeSuite(func() { 
	dbRunner = db.NewRunner() 
	err := dbRunner.Start() 
	Expect(err).NotTo(HaveOccurred())

	dbClient = db.NewClient() 
	err = dbClient.Connect(dbRunner.Address()) 
	Expect(err).NotTo(HaveOccurred()) 
})

var _ = AfterSuite(func() { 
	dbClient.Cleanup() 
	dbRunner.Stop() 
})

BeforeSuite и AfterSuite записаны в файле _suite_test.go и будут выполняться до и после выполнения всех тестовых случаев. Если BeforeSuite не запускается, этот набор тестов не будет выполнен.

Совет: При использовании C для прерывания выполнения AfterSuite все равно будет выполняться, и вам придется использовать C для прерывания еще раз.

2. Расширенное использование

1. Логотип

Их три: Ф,

Язык кода:javascript
копировать
FDescribe(“outer describe”, func() { 
	It(“A”, func() { … }) 
	It(“B”, func() { … }) 
}) 

Совет: Если фокус существует как во внутреннем, так и во внешнем слоях, внешний слой недействителен, то есть следующий код выполнит только тестовый пример B.

Язык кода:javascript
копировать
FDescribe(“outer describe”, func() { 
	It(“A”, func() { … }) 
	FIt(“B”, func() { … }) 
})

Значение P — «Ожидание», то есть не выполняется. Использование такое же, как F. Внешний уровень правила вступает в силу. X имеет то же значение, что и P. Другой способ пропустить тестовые примеры — добавить его.

Язык кода:javascript
копировать
Skip It(“should do something, if it can”, func() { 
	if !someCondition { 
		Skip(“special condition wasn’t met”) 
	}
}) 
2. Параллелизм

ginkgo -p использует количество параллелизма по умолчанию, ginkgo -nodes=N Установите количество параллелизма самостоятельно. Число параллелизма по умолчанию — это значение параметра runtime.NumCPU(), которое представляет собой количество логических процессоров. Если оно больше 4, используйте runtime.NumCPU()-1. во время одновременного выполнения суммируются и объединяются. Он обрабатывается, а затем печатается, поэтому он выглядит более стандартизированным. Содержимое каждого тестового примера также печатается вместе, но не в реальном времени. Если вам нужно печатать в реальном времени, добавьте. параметр -stream. Недостаток заключается в том, что каждый журнал тестовых случаев печатается перекрестно.

3. goroutine
Язык кода:javascript
копировать
It(“should post to the channel, eventually”, func(done Done) { 
	c := make(chan string, 0)
	go DoSomething(c) 
	Expect(<-c).To(ContainSubstring("Done!")) 
	close(done) 
}, 0.2)
Гинкго обнаруживает параметр типа «Готово»,Тайм-аут будет установлен автоматически,Всего на 0,2 позади да,Единица измерения в секунду
4. Использование таблицы описания

Иногда многие тестовые примеры одинаковы, за исключением части данных. Было бы затруднительно писать много подобных, поэтому появляется формат таблицы.

Язык кода:javascript
копировать
package table_test 
import ( 
	. “github.com/onsi/ginkgo/extensions/table” 
	. "github.com/onsi/ginkgo" 
	. "github.com/onsi/gomega" 
) 

var _ = Describe(“Math”, func() { 
	DescribeTable(“the > inequality”, 
		func(x int, y int, expected bool) { 
			Expect(x > y).To(Equal(expected)) 
		}, 
		Entry(“x > y”, 1, 0, true), 
		Entry(“x == y”, 0, 0, false), 
		Entry(“x < y”, 0, 1, false), 
	) 
})

Эквивалентно

Язык кода:javascript
копировать
package table_test import ( 
	. “github.com/onsi/ginkgo” 
	. “github.com/onsi/gomega” 
) 
var _ = Describe(“Math”, func() { 
	Describe(“the > inequality”, 
		It(“x > y”, func() { 
			Expect(1 > 0).To(Equal(true)) 
		})
		It("x == y", func() { 
			Expect(0 > 0).To(Equal(false)) 
		}) 
		It("x < y", func() { 
			Expect(0 > 1).To(Equal(false)) 
		}) 
	) 
})
4. Создайте отчет о тестировании JUnit.

Обычно генерирует отчет о тестировании Junit XML

Язык кода:javascript
копировать
func TestFoo(t *testing.T) { 
	RegisterFailHandler(Fail) 
	junitReporter := reporters.NewJUnitReporter("junit.xml")
	RunSpecsWithDefaultAndCustomReporters(t, "Foo Suite", []Reporter{junitReporter}) 
}
6. Производительность тестового примера

Использование модуля «Измерение»

Язык кода:javascript
копировать
Measure(“it should do something hard efficiently”, func(b Benchmarker) { 
	runtime := b.Time(“runtime”, func() { 
		output := SomethingHard() 
		Expect(output).To(Equal(17)) 
	})
	Ω(runtime.Seconds()).Should(BeNumerically("<", 0.2), "SomethingHard() shouldn't take too long.") 
	b.RecordValue("disk usage (in MB)", HowMuchDiskSpaceDidYouUse()) 
}, 10)

Этот тестовый пример будет запущен 10 раз, и данные о производительности выполнения будут распечатаны.

Язык кода:javascript
копировать
• [MEASUREMENT] 
Suite 
it should do something hard efficiently 

Ran 10 samples: 
runtime: 
	Fastest Time: 0.01s 
	Slowest Time: 0.08s 
	Average Time: 0.05s ± 0.02s 

disk usage (in MB): 
	Smallest: 3.0 
	Largest: 5.2 
	Average: 3.9 ± 0.4

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

DD и BDD — это методологии, часто упоминаемые в гибкой разработке. По сравнению с TDD, BDD стимулирует разработку программного обеспечения путем написания поведения и спецификаций. Такое поведение и спецификации отражаются в более «подробном» описании кода. Есть еще один способ выразить суть BDD: BDD помогает разработчикам разрабатывать программное обеспечение, а TDD помогает разработчикам тестировать программное обеспечение. Ginkgo — отличная платформа BDD на языке Go. Она эффективно помогает разработчикам организовывать и организовывать тестовые сценарии с помощью синтаксиса DSL (Describe/Context/It). В этой статье показан только очень простой вариант использования гинкго, и ее следует использовать в качестве отправной точки. При использовании Ginkgo читателям необходимо понимать жизненный цикл его выполнения, уделяя особое внимание последовательности выполнения и семантической логике этих модулей. Ginkgo имеет множество функций, не описанных в этой статье, таких как асинхронное тестирование, эталонное тестирование, непрерывная интеграция и другая мощная поддержка. Его склад расположен по адресу https://github.com/onsi/ginkgo. Он также предоставляет английскую и китайскую версии документации по использованию. Читатели могут использовать его, чтобы узнать больше о Ginkgo. Наконец, платформа Ginkgo также используется в проекте K8s для написания сквозных (E2E) тестовых примеров, чему стоит поучиться.

Ссылка: https://view.inews.qq.com/a/20220711A0270R00.

boy illustration
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода