Возникла у нас в компании проблема с превью документов, использовали мы для превью на портале всем известную тулзу от гугла. Но с ней были проблемы, у пользователя не всегда рендерился документ(видимо лимиты по количеству вызовов) и когда он рендерился, то бывало, что внешне превьюсильно отлиалосьот оригинала. Поэтому было решено разработать превью документов на нашем кор. портале с использованием уже имеющегося у нас Office Online.
28 июля в Абзаково проходил Ural Geek Camp 2018, в которой мы приняли участие, это была необычная и веселая конференция. И для меня она стала особенной, т.к. я в первый раз принимал участие в роли спикера на ИТ-конференции.
Это было волнительно и немного скомканно, но это было интересно.
По ссылке ниже можно найти мою презентацию с которой я рассказывал доклад.
Сегодня хочется немного рассказать о написании тестов в проектах написанных на Golang.
В плане тестирования в Go подход очень простой а точнее примитивный. Дело в том, что Go за тем как писать и организовывать тесты разработчик должен следить сам, т.е. вся ответственность на разработчике приложения 🙂
Это в свою очередь приводит к тому, что привычного инструментария для тестирования не так много, но зато он уже есть в коробке.
А вот что есть в этой самой коробке и как это можно приукрасить я и хочу рассказать.
Первый простой тест
Задача: Написать функцию, которая прибавляет к целому числу два и возвращает его в качестве результата.
В первую очередь мы пишем тест. Файл с тестом назовем numberator_test.go, это первое что нужно знать, все тесты в go должны быть в файлах с постфиксом _test.go.
Вот простейший пример теста:
package numberator
import "testing"
func TestNumberIncrement(t *testing.T) {
// если результат выполнения
// функции не равен сумме 5+2
// то добавляем ошибку
if NumberIncrement(5) != 5+2 {
t.Error("Error! NumberIncrement(5) != 5+2")
}
}
Думаю суть теста понятна и не требует дополнительных объяснений.
Как же теперь нам запустить наш тест, делается это очень просто командой go test:
go test ./
Улучшаем наш тест
Наш тест выполняется и успешно падает, вроде бы все хорошо, но хотелось бы сделать наш тест не только работающим и выполняющим свою функцию но и более приятным для нас разработчиков.
Поставить его очень просто: go get github.com/stretchr/testify
Перепишем наш тест с помощью этого пакета:
package numberator
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestNumberIncrement(t *testing.T) {
// задаем здесь наше правило
// результат NumberIncrement(5) должен быть равен 5+2
assert.Equal(t, NumberIncrement(5), 5+2, "NumberIncrement(5) != 5+2")
}
Теперь наш тест стал понятнее и сам говорит о своих ожиданиях, не так ли?
В этом же пакете есть много дополнительных методов для улучшения наших с вами тестов. Со всеми возможностями этого пакета можно ознакомиться на https://godoc.org/github.com/stretchr/testify.
Разработка через тестирование (англ. test-driven development, TDD) — техника разработки программного обеспечения, которая основывается на повторении очень коротких циклов разработки: сначала пишется тест, покрывающий желаемое изменение, затем пишется код, который позволит пройти тест, и под конец проводится рефакторинг нового кода к соответствующим стандартам. Кент Бек, считающийся изобретателем этой техники, утверждал в 2003 году, что разработка через тестирование поощряет простой дизайн и внушает уверенность (англ. inspires confidence).
Кстати, рекомендую прочитать книгу о TDD самого Кента Бега(http://www.ozon.ru/context/detail/id/1501671/). О том для чего и когда использовать TDD я в этой заметке писать не буду, т.к. я думаю, что это достаточно очевидный момент и как правило вопрос возникает как к этому подходу разработки перейти и как его успешно внедрять.
Workflow
Ниже на рисунке представлен процесс разработки программы в стиле TDD.
процесс разработки программы в стиле TDD
Начинается весь процесс всегда с написания тестов и далее двигаемся по стрелочке:
1. Написание теста, без написания логики программы, которую мы проверяем в тесте.
2. Запуск теста и проверка того, что тест красный, т.к. у нас нет реализации тестируемой части(если тесты зеленые – значит тесты ничего не проверяют и их нужно переписать)
3. Пишем код, который делает тесты зелеными(минимальный код, а точнее любой корректно работающий код, который сделает тесты зелеными)
4. Запускаем тесты и проверяем, что они зеленые
5. Рефакторинг, мы переписываем наш "говнокод" для озеленения тестов, так, чтобы он был работающим и хорошо пахнущим не только для тестов, но и для нас.
Проблема первого теста
Исходя из собственной практики на первых этапах самое сложное это начать писать первый тест, до реализации тестируемого кода и здесь я вижу два приема:
1. Написать сначала интерфейс, затем переходить к тесту. Это позволит начать переход к TDD и при этом не слишком "тупить" над тем, что и как тестировать, т.к. часть кода вы уже будете писать до теста и в голове уже будет небольшое понимание того, что тестировать. Ну а как привыкните – начнете писать тесты сразу.
2. Это писать сначала самый короткий, т.е. минимальный и общий тест. Собственно это и есть праведный путь TDD. Таким образом дизайн программы будет строиться по циклу через тесты, с каждой итерацией вы будете добавлять тесты и код.
Проблема плохого дизайна
Часто такое бывает, что есть желание перевести проект на TDD и жить хорошо, но оказывается так, что текущая ситуация с дизайном не позволяет перевести весь проект на TDD, на практике иногда ине всегда возможно в разумные сроки перенести весь проект на TDD. В связи сэтим разумно этого не делать, но естьвсе таки несколько вариантов для того, чтобы начать использовать TDD и в таком проекте:
1. Писать проект заново, особенно если в пользу этого уже есть какие-нибудь и другие предпосылки.
2. Выделять из проекта отдельные компоненты и тестировать их. Этот вариант подходит для проектов с не слишком НЕудачным дизайном.
3. Использовать TDD только для новых изменений кода и со временем весь проект сможет перейти на TDD. Этот вариант на мой взгляд самый универсальный.
Заключение
В общем и в целом считаю, что TDD это хороший способ улучшить стабильность и надежность своего кода и даже при написании небольших приложений это позволяет снизить количество ошибок в приложении многократно. Как минимум это стоит попробовать.