Читаем Terraform: инфраструктура на уровне кода полностью

• Простые значения в качестве ввода. Класс Handlers не зависит от HTTPServer, HTTPRequest или HTTPResponse. Весь его ввод состоит из простых параметров, таких как строка с URL-адресом.

• Простые значения в качестве вывода. Вместо того чтобы менять поля объекта HTTPResponse (создавая тем самым побочный эффект), методы класса Handlers возвращают HTTP-ответ в виде простого значения (массива с кодом состояния, типом содержимого и телом).

Код, который принимает на вход и возвращает простые значения, обычно легче понять, обновить и протестировать. Сначала изменим класс WebServer так, чтобы он отвечал на запросы с помощью Handlers.

class WebServer < WEBrick::HTTPServlet::AbstractServlet

  def do_GET(request, response)

    handlers = Handlers.new

    status_code, content_type, body = handlers.handle(request.path)

    response.status = status_code

    response['Content-Type'] = content_type

    response.body = body

  end

end

Этот код вызывает метод handle из класса Handlers и возвращает полученные из него код статуса, тип содержимого и тело в качестве HTTP-ответа. Как видите, код, использующий класс Handlers, выглядит аккуратным и простым. Кроме того, это облегчает тестирование. Вот как выглядит модульный тест для точки входа /:

class TestWebServer < Test::Unit::TestCase

  def initialize(test_method_name)

    super(test_method_name)

    @handlers = Handlers.new

  end

  def test_unit_hello

    status_code, content_type, body = @handlers.handle("/")

    assert_equal(200, status_code)

    assert_equal('text/plain', content_type)

    assert_equal('Hello, World', body)

  end

end

Код теста вызывает тот же метод handle из класса Handlers и использует несколько вызовов assert для проверки ответа, который возвращается из точки входа /. Вот как запустить этот тест:

$ ruby web-server-test.rb

Loaded suite web-server-test

Finished in 0.000287 seconds.

-------------------------------------------

1 tests, 3 assertions, 0 failures, 0 errors

100% passed

-------------------------------------------

Похоже, тест пройден. Теперь добавим модульные тесты для точек входа /api и 404:

def test_unit_api

  status_code, content_type, body = @handlers.handle("/api")

  assert_equal(201, status_code)

  assert_equal('application/json', content_type)

  assert_equal('{"foo":"bar"}', body)

end

def test_unit_404

  status_code, content_type, body = @handlers.handle("/invalid-path")

  assert_equal(404, status_code)

  assert_equal('text/plain', content_type)

  assert_equal('Not Found', body)

end

Запустите тесты еще раз:

$ ruby web-server-test.rb

Loaded suite web-server-test

Finished in 0.000572 seconds.

-------------------------------------------

3 tests, 9 assertions, 0 failures, 0 errors

100% passed

-------------------------------------------

Всего за 0,000 527 2 секунды вы можете проверить, работает ли код вашего веб-сервера так, как вы того ожидали. В этом сила модульных тестов: быстрые результаты, которые помогают укрепить уверенность в своем коде. Если допущена какая-либо ошибка (например, случайно поменялся ответ точки входа /api), вы узнаете об этом почти мгновенно:

$ ruby web-server-test.rb

Loaded suite web-server-test

============================================================================

Failure: test_unit_api(TestWebServer)

web-server-test.rb:25:in `test_unit_api'

     22:     status_code, content_type, body = Handlers.new.handle("/api")

     23:     assert_equal(201, status_code)

     24:     assert_equal('application/json', content_type)

  => 25:     assert_equal('{"foo":"bar"}', body)

     26:   end

     27:

     28:   def test_unit_404

<"{\"foo\":\"bar\"}"> expected but was

<"{\"foo\":\"whoops\"}">

diff:

? {"foo":"bar   "}

?         whoops

============================================================================

Finished in 0.007904 seconds.

-------------------------------------------

3 tests, 9 assertions, 1 failures, 0 errors

66.6667% passed

-------------------------------------------

Основы модульных тестов

Какой эквивалент такого рода модульных тестов для кода Terraform? Для начала нужно определиться с тем, что в мире Terraform считается модулем. Ближайший аналог отдельной функции или класса — обобщенный модуль (определение термина дано в подразделе «Компонуемые модули» на с. 226), такой как alb из главы 6. Как бы вы его протестировали?

В Ruby для написания модульных тестов необходимо провести такой рефакторинг, чтобы код можно было выполнять без сложных зависимостей вроде HTTPServer, HTTPRequest или HTTPResponse. Если подумать о том, чем занимается код Terraform (обращение к API AWS для создания балансировщиков нагрузки, прослушивателей, целевых групп и т. д.), то в 99 % случаев он взаимодействует со сложными зависимостями! Не существует практичного способа свести число внешних зависимостей к нулю, но, даже если бы вы могли это сделать, у вас бы практически не осталось кода для тестирования56.

Это подводит нас к ключевому выводу о тестировании № 3: вы не можете проводить чистое тестирование кода Terraform.

Перейти на страницу:

Все книги серии Бестселлеры O'Reilly

Искусство управления IT-проектами
Искусство управления IT-проектами

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

Скотт Беркун

Деловая литература
iOS. Приемы программирования
iOS. Приемы программирования

Книга, которую вы держите в руках, представляет собой новый, полностью переписанный сборник приемов программирования по работе с iOS. Он поможет вам справиться с наболевшими проблемами, с которыми приходится сталкиваться при разработке приложений для iPhone, iPad и iPod Touch. Вы быстро освоите всю информацию, необходимую для начала работы с iOS 7 SDK, в частности познакомитесь с решениями для добавления в ваши приложения реалистичной физики или движений — в этом вам помогут API UIKit Dynamics.Вы изучите новые многочисленные способы хранения и защиты данных, отправки и получения уведомлений, улучшения и анимации графики, управления файлами и каталогами, а также рассмотрите многие другие темы. При описании каждого приема программирования приводятся образцы кода, которые вы можете смело использовать.

Вандад Нахавандипур

Программирование, программы, базы данных / Программирование / Книги по IT

Похожие книги