abstract class Animal
end
class Cat < Animal
end
class Dog < Animal
end
class Food(T)
end
Food(Cat).new
Food(Dog).new
Food(Int32).new
В этом примере имеется общий тип еды, который должен принимать только подкласс Animal. Однако по умолчанию вполне нормально иметь возможность создавать экземпляр Food, используя тип, отличный от Animal, например Int32. Мы можем использовать специальную ошибку времени компиляции в конструкторе Food, чтобы гарантировать, что T является дочерним элементом Animal. В конечном итоге это будет выглядеть так:
class Food(T)
def self.new
{% raise "Non animal '#{t}' cannot be fed." unless T <=
Animal %}
end
end
В этом новом коде попытка выполнить Food(Int32).new вызовет ошибку во время компиляции.
Возможность определять собственные ошибки времени компиляции может существенно сократить время, необходимое для отладки проблемы. В противном случае неопределенные ошибки могут быть дополнены дополнительным контекстом/ссылками и в целом станут более удобными для пользователя.
Резюме
Ура! Мы подошли к концу части книги, посвященной метапрограммированию, рассмотрели много нового и продемонстрировали, насколько мощными могут быть макросы Crystal. Я надеюсь, что вы сможете применить свое более глубокое понимание макросов и этих шаблонов для решения сложных задач, с которыми вы можете столкнуться в рамках ваших будущих проектов.
В следующей части мы рассмотрим различные инструменты поддержки Crystal, например, как тестировать, документировать и развертывать ваш код, а также как автоматизировать этот процесс!
Часть 5: Вспомогательные инструменты
Crystal поставляется в комплекте с различными вспомогательными функциями и инструментами, которые помогут создать все необходимое для создания надежных и удобных в использовании приложений после того, как само приложение будет написано. Это включает в себя платформу тестирования, которая гарантирует, что приложение продолжает функционировать должным образом, и систему документации, которая облегчает другим пользователям изучение того, как пользоваться приложением, и поддерживается природой самого языка, что упрощает его развертывание. Давайте начнем!
Эта часть содержит следующие главы:
• Глава 14, тестирование
• Глава 15, Документирование кода
• Глава 16, Развертывание кода
• Глава 17, Автоматизация
• Приложение А, Настройка инструментария
• Приложение В, Будущее Crystal
14. Тестирование
Если вы помните, в Главе 4 «Изучение Crystal посредством написания интерфейса командной строки» при создании проекта создавалась папка spec/. В этой папке находились все тесты, относящиеся к приложению, но что такое тесты и зачем их писать? Короче говоря, тесты — это автоматизированный способ убедиться, что ваш код по-прежнему работает должным образом. Они могут быть чрезвычайно полезны по мере роста вашего приложения, поскольку время и усилия, необходимые для ручного тестирования всего на предмет каждого изменения, становятся просто невозможными. В этой главе мы рассмотрим следующие темы:
• Зачем тестировать?
• Модульное тестирование.
• Интеграционное тестирование.
К концу этой главы вы должны понять преимущества тестирования и то, как писать общие модульные тесты и интеграционные тесты в контексте Athena Framework.
Технические требования
Для этой главы вам потребуется следующее:
• Рабочая установка Crystal.
Инструкции по настройке Crystal можно найти в Главе 1 «Введение в Crystal».
Все примеры кода, использованные в этой главе, можно найти в папке Chapter 14 на GitHub по следующей ссылке: https://github.com/PacktPublishing/Crystal-Programming/tree/main/Chapter14
Зачем тестировать?
В обоих двух более крупных проектах, над которыми мы работали до сих пор, и во всех других примерах, мы запускали их вручную после внесения изменений, чтобы гарантировать, что они дают ожидаемый результат, например, возвращают правильный ответ, производят желаемое преобразование и т. д. или просто вывести правильное значение на терминал.