Full stack проект на Go за неделю. День 3: Тестируем бэкенд

Разработка /
Разработка: Full stack проект на Go за неделю. День 3: Тестируем бэкенд

Это третья часть материала. Первая часть. Вторая часть.

Сегодня мы будет тестировать разработанный ранее бэкенд.

Цель тестирования

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

Вспомним, какие методы API должны работать в приложении. На текущий момент у нас реализованы три конечные точки и две из них поддерживают два HTTP-метода:

  • /currencies (GET, POST)
  • /convert (POST)
  • /webhook (POST, DELETE)

Итого, нам нужно сделать пять тестов, это не считая тестов загрузки приложения и т.п.

Методика тестирования

В Go есть встроенная утилита тестирования (go test), с её помощью писать и выполнять тесты очень удобно. Файлы, оканчивающиеся на _test.go будут автоматически включены в план тестирования, а функции тестирования имеют запись типа func(t *testing.T) и они будут выполнены в том же порядке, в каком написаны в файле. Имейте в виду, что файлы тестов не попадают в приложение при сборке.

План

Встроенная в Go подсистема тестирования требует небольшой инициализации. К счастью, в Go есть метод init(), всегда выполняющийся первым — даже при тестировании.

Вот пример инициализации:

var (
	server   *Server
	runError error
)

func init() {
	var err error
	server, err = New()
	if err != nil {
		panic(err)
	}

	go func() {
		runError = server.Run()
		if runError != nil {
			panic(runError)
		}
	}()
}

А теперь добавим несколько функций для проверки конечных точек API.

Тестирование инициализации

В нижеприведённом кусочке кода описана небольшая функция, проверяющая первичный запуск сервера и его непрерывную работу (в цикле, с помощью time.Sleep). При каждой итерации проверяется server.hasCurrencies для остановки цикла тестирования, когда сервер станет готов:

func TestServerCreation(t *testing.T) {
	if server == nil {
		t.Fatal("Server not initialized!")
	}

	if runError != nil {
		t.Fatal("Error starting the server!")
	}

	for loops := 0; !server.hasCurrencies && loops < 10; loops++ {
		t.Log("Sleep:", loops+1)
		time.Sleep(time.Duration(500*(loops+1)) * time.Millisecond)
	}

	if !server.hasCurrencies {
		t.Fatal("Currencies not loaded!")
	}
}

Эта функция располагается в файле a_test.go. Выбор названия файла объясняется тем, что тесты запускают файлы в алфавитном порядке, поэтому называем их, начиная с «a».

Дальнейшее тестирование

Все тесты проводятся таким же способом, используя функционал go test.
Загрузите их себе из репозитория и проверьте сами.

Проверим вывод после прохода тестов:

➜  currencyconverter git:(master) go test -v -cover ./...
?   	github.com/goingfullstack/currencyconverter	[no test files]
=== RUN   TestServerCreation
2017/02/15 20 : 02 : 05 Starting server on 127.0.0.1:4000
2017/02/15 20 : 02 : 05 Starting currency fetching...
2017/02/15 20 : 02 : 05 Starting new currency fetch...
2017/02/15 20 : 02 : 05 Currencies updated.
2017/02/15 20 : 02 : 05 Sleeping 1h0m0s
--- PASS: TestServerCreation (0.50s)
	a_test.go: 18 : Sleep: 1
=== RUN   TestCurrencyConversionNewServer
--- PASS: TestCurrencyConversionNewServer (0.00s)
=== RUN   TestCurrencyConversion
--- PASS: TestCurrencyConversion (0.00s)
=== RUN   TestUnknownCurrency
--- PASS: TestUnknownCurrency (0.00s)
=== RUN   TestConvertResponseCreation
--- PASS: TestConvertResponseCreation (0.00s)
=== RUN   TestConvertedResponseUnknownCurrency
--- PASS: TestConvertedResponseUnknownCurrency (0.00s)
=== RUN   TestCreateCurrencyResponse
--- PASS: TestCreateCurrencyResponse (0.00s)
=== RUN   TestCreateInvalidCurrencyResponse
--- PASS: TestCreateInvalidCurrencyResponse (0.00s)
=== RUN   TestCurrencyGet
2017/02/15 20 : 02 : 05 [GET] /currencies
--- PASS: TestCurrencyGet (0.00s)
=== RUN   TestCurrencyPostKnownCurrency
2017/02/15 20 : 02 : 05 [POST] /currencies
--- PASS: TestCurrencyPostKnownCurrency (0.00s)
=== RUN   TestCurrencyPostInvalidRequest
2017/02/15 20 : 02 : 05 [POST] /currencies
2017/02/15 20 : 02 : 05 EOF
--- PASS: TestCurrencyPostInvalidRequest (0.00s)
=== RUN   TestCurrencyPostUnknownCurrency
2017/02/15 20 : 02 : 05 [POST] /currencies
2017/02/15 20 : 02 : 05 Unknown currency: FOO
--- PASS: TestCurrencyPostUnknownCurrency (0.00s)
=== RUN   TestCurrencyPut
2017/02/15 20 : 02 : 05 [PUT] /currencies
--- PASS: TestCurrencyPut (0.00s)
=== RUN   TestConvert
2017/02/15 20 : 02 : 05 [POST] /convert
--- PASS: TestConvert (0.00s)
=== RUN   TestConvertInvalidMethod
2017/02/15 20 : 02 : 05 [PUT] /convert
--- PASS: TestConvertInvalidMethod (0.00s)
=== RUN   TestConvertInvalidCurrency
2017/02/15 20 : 02 : 05 [POST] /convert
2017/02/15 20 : 02 : 05 Unknown currency: INVALID
--- PASS: TestConvertInvalidCurrency (0.00s)
=== RUN   TestConvertInvalidRequestData
2017/02/15 20 : 02 : 05 [POST] /convert
2017/02/15 20 : 02 : 05 EOF
--- PASS: TestConvertInvalidRequestData (0.00s)
=== RUN   TestNotFoundRoute
2017/02/15 20 : 02 : 05 [GET] /notfound
--- PASS: TestNotFoundRoute (0.00s)
=== RUN   TestWebhookRegister
2017/02/15 20 : 02 : 05 [POST] /webhook
2017/02/15 20 : 02 : 05 Webhook return code: 200
--- PASS: TestWebhookRegister (0.00s)
=== RUN   TestWebhookCalling
2017/02/15 20 : 02 : 05 Webhook return code: 200
--- PASS: TestWebhookCalling (0.00s)
=== RUN   TestWebhookWrongSecret
2017/02/15 20 : 02 : 05 [POST] /webhook
2017/02/15 20 : 02 : 05 Webhook return code: 403
--- PASS: TestWebhookWrongSecret (0.00s)
=== RUN   TestWebhookWrongBase
2017/02/15 20 : 02 : 05 [POST] /webhook
--- PASS: TestWebhookWrongBase (0.00s)
=== RUN   TestWebhookGet
2017/02/15 20 : 02 : 05 [GET] /webhook
--- PASS: TestWebhookGet (0.00s)
PASS
coverage: 85.1% of statements
ok  	github.com/goingfullstack/currencyconverter/server	0.524s	coverage: 85.1% of statements

Как видно из последней строки, тест покрыл 85,1% нашего кода — можно сделать ещё лучше, но пока этого достаточно.

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

Продолжение
0 комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.