2008-09-29 1 views
61

Я расширяю понимание Ruby, кодируя эквивалент xUnit Кента Бек в Ruby. Python (который пишет Kent) имеет метод assert() на языке, который используется широко. Рубин не делает. Я думаю, что это должно быть легко добавить, но является ли ядром подходящее место?Это идиоматический Ruby для добавления метода assert() в класс ядра Ruby?

BTW, Я знаю о существовании различных рамок блока в Ruby - это упражнение, чтобы изучить идиомы Ruby, а не «что-то сделать».

+3

Мне нравятся проблемы, которые делают и то, и другое: научите вас и сделайте что-нибудь. :) – 2008-09-29 14:35:02

ответ

77

Нет, это не лучшая практика. Лучшая аналогия утверждать() в Ruby, просто поднимая

raise "This is wrong" unless expr 

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

+22

Вы также можете использовать `fail if [expr]`, если хотите, что вызывает ошибку выполнения. – 2010-02-25 03:38:20

14

В чем причина добавления метода assert к модулю ядра? Почему бы просто не использовать другой модуль под названием Assertions или что-то в этом роде?

Как это:

module Assertions 
    def assert(param) 
    # do something with param 
    end 

    # define more assertions here 
end 

Если вам действительно нужны ваши утверждения должны быть доступны везде сделать что-то вроде этого:

class Object 
    include Assertions 
end 

Отказ от ответственности: я не проверял код, но в принципе Я бы сделал это так.

+1

Разве это не обезьяна? Вы изменяете класс `Object`. – tsikov 2016-02-10 18:12:26

+0

Да, это классическая панировка обезьян. Это способ сделать это, если вам действительно нужно сделать метод `assert` доступным во всем мире. Тем не менее, я бы не советовал кому-либо использовать обезьянную патчу, как это, в проектах, отличных от игрушек. – 2017-01-23 09:52:41

4

Мое понимание заключается в том, что вы пишете собственный тестовый пакет, чтобы стать более знакомым с Ruby. Поэтому, хотя Test :: Unit может быть полезен в качестве руководства, вероятно, это не то, что вы ищете (потому что это уже сделало работу).

Тем не менее, утверждение python (по крайней мере, для меня), более похоже на C's assert(3). Он специально не предназначен для модульных тестов, а скорее для того, чтобы ловить случаи, когда «этого никогда не должно быть».

Как встроенные модульные тесты Ruby имеют тенденцию рассматривать проблему, тогда каждый отдельный класс тестового случая является подклассом TestCase и включает в себя инструкцию «assert», которая проверяет правильность переданного ей и записывает его для отчетности.

6

Это не особенно идиоматических исключения, но я думаю, что это хорошая идея. Особенно, если сделать так:

def assert(msg=nil) 
    if DEBUG 
     raise msg || "Assertion failed!" unless yield 
    end 
end 

Таким образом, нет никакого влияния, если вы решили не работать с DEBUG (или каким-либо другим удобным переключателем, я использовал Kernel.do_assert в прошлом) наборе.

25

Я думаю, что это абсолютно правильно использовать утверждения в Ruby. Но вы упоминали две разные вещи:

  • Основы xUnit используют assert методы проверки ваших ожиданий тестов. Они предназначены для использования в вашем тестовом коде, а не в вашем коде приложения.
  • Некоторые языки, такие как C, Java или Python, включают в себя конструкцию assert, предназначенную для использования внутри кода ваших программ, для проверки допущений, которые вы делаете о своей целостности. Эти проверки встроены внутри самого кода. Это не утилита для тестирования, а время разработки.

Я недавно писал solid_assert: a little Ruby library implementing a Ruby assertion utility а также a post in my blog explaining its motivation .. Это позволит вам записывать выражения в виде:

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 получить оценку в виде пустых заявлений. Это позволит избежать проблем с производительностью при производстве. Но обратите внимание, что The Pragmatic Programmers рекомендуют не деактивировать их. Вы должны отключать их только в том случае, если они действительно влияют на производительность.

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

Вы можете быть уверены, что использование утверждений - это хорошо, потому что две обязательные для чтения классические книги, такие как The Pragmatic Programmer From Journeyman to Master и Code Complete, посвящают им все разделы и рекомендуют использовать их. Существует также хорошая статья под названием Programming with assertions, которая очень хорошо иллюстрирует, что такое напористое программирование и когда его использовать (оно основано на Java, но концепции применимы к любому языку).

Смежные вопросы