Ответ 1
Нет, это не лучшая практика. Лучшая аналогия assert() в Ruby просто поднимает
raise "This is wrong" unless expr
и вы можете реализовать свои собственные исключения, если хотите предоставить более конкретную обработку исключений
Я расширяю свое понимание Ruby, кодируя эквивалент Kent Beck xUnit в Ruby. Python (который пишет Kent) имеет метод assert() на языке, который используется широко. Рубин не делает. Я думаю, что это должно быть легко добавить, но является ли ядром подходящее место для его размещения?
Кстати, я знаю о существовании различных структур Unit в Ruby - это упражнение, чтобы изучить идиомы Ruby, а не "что-то сделать".
Нет, это не лучшая практика. Лучшая аналогия assert() в Ruby просто поднимает
raise "This is wrong" unless expr
и вы можете реализовать свои собственные исключения, если хотите предоставить более конкретную обработку исключений
Я думаю, что вполне реально использовать утверждения в Ruby. Но вы упоминаете две разные вещи:
assert
для проверки ожиданий ваших тестов. Они предназначены для использования в вашем тестовом коде, а не в вашем коде приложения.assert
, предназначенную для использования внутри кода ваших программ, для проверки допущений, которые вы делаете о своей целостности. Эти проверки встроены внутри самого кода. Они не являются утилитой для тестирования, а имеют время разработки.Недавно я написал solid_assert: небольшая библиотека Ruby, реализующая утилиту утверждения Ruby, а также сообщение в моем блоге, объясняющее его мотивация. Позволяет писать выражения в форме:
assert some_string != "some value"
assert clients.empty?, "Isn't the clients list empty?"
invariant "Lists with different sizes?" do
one_variable = calculate_some_value
other_variable = calculate_some_other_value
one_variable > other_variable
end
И они могут быть деактивированы, поэтому assert
и invariant
получают оценку как пустые операторы. Это позволит избежать проблем с производительностью при производстве. Но обратите внимание, что Pragmatic Programmers рекомендуют не деактивировать их. Вы должны дезактивировать их, только если они действительно влияют на производительность.
Относительно ответа, говорящего, что идиоматический метод Ruby использует нормальный оператор raise
, я думаю, что ему не хватает выразительности. Одним из золотых правил настойчивого программирования не является использование утверждений для нормальной обработки исключений. Это две совершенно разные вещи. Если вы используете один и тот же синтаксис для двух из них, я думаю, что код будет более неясным. И, конечно же, вы теряете способность дезактивировать их.
Вы можете убедиться, что использование утверждений - это хорошо, потому что две обязательные для чтения классические книги, такие как Прагматический программист от Journeyman to Master и Code Complete посвятить им целые разделы и рекомендовать их использование. Существует также хорошая статья под названием Программирование с утверждениями, которые очень хорошо иллюстрируют, что такое напористое программирование и когда его использовать (оно основано на Java, но концепции применимы к любым язык).
В чем причина добавления метода assert к модулю ядра? Почему бы просто не использовать другой модуль под названием Assertions
или что-то еще?
Вот так:
module Assertions
def assert(param)
# do something with param
end
# define more assertions here
end
Если вам действительно нужны ваши утверждения, чтобы они были доступны везде, выполните следующие действия:
class Object
include Assertions
end
Отказ от ответственности: я не тестировал код, но в принципе я сделал бы это так.
Это не особенно идиоматично, но я думаю, что это хорошая идея. Особенно, если это делается следующим образом:
def assert(msg=nil)
if DEBUG
raise msg || "Assertion failed!" unless yield
end
end
Таким образом, нет никакого эффекта, если вы решите не запускаться с DEBUG (или другим удобным переключателем, который я использовал Kernel.do_assert в прошлом).
Мое понимание заключается в том, что вы пишете свой собственный набор тестов, чтобы стать более знакомым с Ruby. Поэтому, хотя Test:: Unit может быть полезен в качестве руководства, возможно, это не то, что вы ищете (потому что оно уже выполнило задание).
Тем не менее, утверждение python (по крайней мере, для меня), более похоже на C assert (3). Это не специально предназначено для модульных тестов, а скорее для того, чтобы ловить случаи, когда "этого никогда не должно быть".
Как встроенные модульные тесты Ruby имеют тенденцию рассматривать проблему, тогда каждый отдельный класс тестового случая является подклассом TestCase и включает в себя инструкцию assert, которая проверяет достоверность того, что было передано ей, и записывает ее для отчетности.