TDD заметки: Тестирование в проектах на Golang

Введение

Сегодня хочется немного рассказать о написании тестов в проектах написанных на 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 ./

Улучшаем наш тест

Наш тест выполняется и успешно падает, вроде бы все хорошо, но хотелось бы сделать наш тест не только работающим и выполняющим свою функцию но и более приятным для нас разработчиков.

Для этого есть очень хороший пакет – https://github.com/stretchr/testify, который нам с этим и поможет.

Поставить его очень просто: 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.

Заключение

Тесты это хорошо, а понятные тесты это еще лучше!

 

Настройка Travis CI для Golang проекта с использованием Godep

В этом посте хочу поделиться тем как я настраивал Travis CI для своего небольшого проекта на Golang.

Что такое Travis CI?

Travis CI — распределённый веб-сервис для сборки и тестирования программного обеспечения, использующий GitHub в качестве хостинга исходного кода.

У этого сервиса есть неплохой раздел по поводу настройки проекта – https://docs.travis-ci.com/user/languages/go/#Dependency-Management , но как это часто бывает не все так гладко, как хотелось бы.

Проблема возникла с менеджером пакетов godep и импортом пакетов, у меня возникали такие ошибки:

// первый вариант
The command "eval go get -t -v ./... " failed. Retrying, 2 of 3.
// второй вариант
cannot find package "my_go_project/my_package" in any of:
 
Решение оказалось очень простым – заменить относительные пути импорта локальных пакетов на абсолютные, т.е. вместо import "my_go_project/my_package" написать import "github.com/username/my_go_project/my_package".
 
 
В итоге получился такой .travis.yml:
 

Одна строка, которая сэкономит 99% RAM

В Golang как и во многих других языках работает сборщик мусора.

Но все же ресурсы высвобождать необходимо, особенно если вы работаете с http запросами и пакетом https://golang.org/pkg/net/http/.

В противном случае может случится так, что приложение в один прекрасный момент упадет и не факт, что об этом Вы узнаете первым. Из этого следует:

  1. нужно внимательно читать документацию;
  2. нужно всегда проверять приложение на прожорливость и работу с ресурсами;
  3. использовать инструментыдля мониторинга.

Само высвобожение ресурса тела запроса выглядит так:

 

Golang: пакеты

По поводу пакетов в голанге есть множество статей и ресурсов, например – https://thenewstack.io/understanding-golang-packages/. Но лично у меня в самом начале изучения этого языка прграммирования возникли две проблемы:

  1. Как использовать пакеты внутри совего приложения для разделения кода(что-то вроде namespace в других языках);
  2. Ошибка цикличного импорта пакетов.

Первый вопрос снимается легко, допустим у нас в проекте с названием project7(директория /go/src/project7) есть модели и контроллеры в соответствующих директориях(models и controllers), тогда мы можем их использовать в нашем главном файле main.go вот так:


То есть, по сути мы просто используем их как локальный неймспейс, все очень просто.

Проблема циклических импортов возникает, когда вы ипортируете пакет, который импортирует пакет из которого вы производите импорт.

Т.е. получается, что вы попадаете в бесконечный цикл импорта, так как оба пакета импортируют друг друга.

Избежать этой проблемы легко – используйте интерфейсы.