litbaza книги онлайнРазная литератураCrystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI - Джордж Дитрих

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 58 59 60 61 62 63 64 65 66 ... 75
Перейти на страницу:
командной строки» при создании проекта создавалась папка spec/. В этой папке находились все тесты, относящиеся к приложению, но что такое тесты и зачем их писать? Короче говоря, тесты — это автоматизированный способ убедиться, что ваш код по-прежнему работает должным образом. Они могут быть чрезвычайно полезны по мере роста вашего приложения, поскольку время и усилия, необходимые для ручного тестирования всего на предмет каждого изменения, становятся просто невозможными. В этой главе мы рассмотрим следующие темы:

• Зачем тестировать?

• Модульное тестирование.

• Интеграционное тестирование.

К концу этой главы вы должны понять преимущества тестирования и то, как писать общие модульные тесты и интеграционные тесты в контексте Athena Framework.

Технические требования

Для этой главы вам потребуется следующее:

• Рабочая установка Crystal.

Инструкции по настройке Crystal можно найти в Главе 1 «Введение в Crystal».

Все примеры кода, использованные в этой главе, можно найти в папке Chapter 14 на GitHub по следующей ссылке: https://github.com/PacktPublishing/Crystal-Programming/tree/main/Chapter14

Зачем тестировать?

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

Этот процесс подходит, когда имеется всего несколько методов/потоков. Однако по мере роста приложения становится невозможным тестировать каждый метод или поток самостоятельно после каждого изменения. Конечно, вы можете вернуться к тестированию только тех вещей, которые напрямую связаны с тем, что вы изменили, но это может привести к пропущенным ошибкам в другой логике, которая это использует. Тестирование — это процесс написания дополнительного кода, который автоматически выполняет утверждения, чтобы гарантировать, что код выполняется должным образом.

Тестирование также может быть хорошим способом убедиться, что изменение не приведет к непреднамеренному нарушению общедоступного интерфейса прикладного программирования (API) вашего приложения, поскольку тесты будут тестировать общедоступный API и, как следствие, частный API.

Некоторые люди (или компании) могут колебаться, стоит ли тратить дополнительное время и деньги на что-то, что по существу не приносит никакой пользы клиенту/пользователю приложения. Однако то небольшое количество времени, которое потребуется для написания некоторых тестов, может в конечном итоге сэкономить бесчисленное количество часов, предотвращая попадание ошибок в рабочую среду.

Существуют различные виды тестирования, каждый из которых преследует свою цель. Некоторые из них включают следующее:

• Модульное тестирование (Unit testing): изолированное тестирование конкретной функции/метода.

• Интеграционное тестирование (Integration testing): тестирование интеграции различных типов вместе, имитация внешних коммуникаций (база данных, внешние API и т. д.).

• Функциональное тестирование (Functional testing): аналогично интеграционному тестированию, но с меньшим количеством насмешек и более конкретными утверждениями, например, конкретное значение, возвращаемое из базы данных, а не просто подтверждение того, что запрос был выполнен.

• Сквозное тестирование (E2E) (End-to-end (E2E) testing): аналогично функциональному тестированию, но обычно включает пользовательский интерфейс (UI) и минимальное количество макетов.

• Тестирование безопасности (Security testing): проверка отсутствия известных недостатков безопасности в коде. Каждый из этих типов тестирования имеет свои плюсы, минусы и цели. Однако мы собираемся в первую очередь сосредоточиться на модульной и интеграционной/функциональной стороне вещей, начиная с модульного тестирования.

Модульное тестирование

Модульное тестирование означает, что вы хотите протестировать определенный метод, будь то на верхнем уровне или как часть объекта, изолированно. Изолированное тестирование является важной частью этого типа тестирования. Это гарантирует, что вы тестируете только ту логику, которую хотите, а не логику ее зависимостей.

Crystal поставляется в комплекте с модулем Spec, который предоставляет инструменты, необходимые для тестирования вашего кода. Например, предположим, что у вас есть следующий метод, который возвращает сумму двух значений как часть add.cr:

def add(value1, value2)

    valuel + value2

end

Соответствующие тесты для этого могут выглядеть так:

require "spec"

require "./add"

describe "#add" do

  it "adds with positive values" do

    add(1, 2).should eq 3

  end

  it "adds with negative values" do

    add(-1, -2).should eq -3

  end

  it "adds with mixed signed values" do

    add(-1, 2).should eq 1

  end

end

Сначала нам нужен модуль Spec, а затем мы используем метод #describe для создания группы связанных тестов — в данном случае всех тех, которые связаны с методом #add. Затем мы используем метод #it для определения конкретных тестовых случаев, в которых мы утверждаем, что он возвращает правильное значение. У нас есть некоторые из них, определенные для примера. В идеале у вас должен быть тестовый пример для каждого потока, через который может пройти код, и обязательно добавлять новые по мере исправления ошибок.

Если вы тестировали этот метод как часть сегмента, вам нужно было бы создать файл в папке spec/ с именем, оканчивающимся на _spec, например spec/add_spec.cr. Обычно тесты следуют тому же организационному стилю, что и исходный код, например, используют те же подпапки и т.п. После этого вы сможете запустить спецификацию Crystal, которая запустит все спецификации, определенные в папке. В противном случае вы также можете запустить этот файл, как и любую другую программу Crystal, если это разовый тест. Также предлагается использовать опцию --order=random для crystal spec. Это запустит все тестовые примеры в случайном порядке, что может помочь выявить случаи, когда одна спецификация требует запуска предыдущей, а это не то, что вам нужно.

Файл spec/spec_helper.cr, созданный командой crystal init, используется в качестве точки входа в тесты проекта. Этот файл обычно требует спецификации, исходного кода проекта, а также любых других файлов, специфичных для спецификации, таких как фикстуры или макеты. Здесь также могут быть определены глобальные помощники тестирования. Каждый тест должен требовать, чтобы этот файл имел доступ к модулю Spec и другим помощникам.

В предыдущем примере мы использовали только утверждение eq, то есть два значения равны. Однако модуль Spec предоставляет множество других утверждений, как показано в следующем примере:

require "spec"

it do

  true.should be_true

  nil.should be_nil

  10.should be >= 5

  "foo bar baz".should contain "bar"

  10.should_not eq 5

  expect_raises Exception, "Err" do

    raise Exception.new "Err"

  end

end

Полный список см. на https://crystal-lang.org/api/Spec/Expectations.html. Этот пример также демонстрирует, что внешний блок #describe не требуется. Однако обычно рекомендуется включить

1 ... 58 59 60 61 62 63 64 65 66 ... 75
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?