Подтвердить что ты не робот

Когда использовать фигурные скобки и круглые скобки в ожидании метода Rspec?

У меня был тест, который сделал это:

expect(@parser.parse('adsadasdas')).to raise_error(Errno::ENOENT)

и это не сработало. Я изменил на:

expect { @parser.parse('adsadasdas') }.to raise_error(Errno::ENOENT)

И это сработало.

Когда мы используем фигурные скобки и когда мы будем использовать круглые скобки с ожиданием?

4b9b3361

Ответ 1

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

Ваш вопрос был фактически рассмотрен другим другим fooobar.com/questions/227930/....

Один плакат, Питер Альфвин, дает хороший момент, когда он говорит:

Что касается правил, вы передаете блок или Proc, если вы пытаетесь проверить поведение (например, повышение ошибок, изменение некоторого значения). В противном случае вы передать "обычный" аргумент, и в этом случае значение этого аргумент - это то, что тестируется.

Причина, по которой вы сталкиваетесь с феноменом, который вы видите, связана с повышением ошибок. Когда вы передаете @parser.parse('adsadasdas') в качестве аргумента (используйте круглые скобки) в expect, вы по существу говорите ruby:

  • Сначала оцените @parser.parse('adsadasdas').
  • Возьмите результат и передайте его expect.
  • expect должен увидеть, соответствует ли этот результат моему ожиданию (т.е. будет Errno:ENOENT).

Но происходит следующее: когда ruby ​​оценивает @parser.parse('adsadasdas'), ошибка возникает тогда и там. Ruby даже не получает возможность передать результат на expect. (Для всех нас заботит, вы могли бы передать @parser.parse('adsadasdas') в качестве аргумента любой функции... например multiply() или capitalize()). Ошибка возникает, а expect никогда не получает возможности выполнить свою работу.

Но когда вы передаете @parser.parse('adsadasdas') как proc (блок кода) в expect с помощью фигурных скобок, то, что вы говорите, это:

  • expect, приготовьтесь к некоторой работе.
  • expect, я хотел бы, чтобы вы отслеживали, что происходит, когда мы оцениваем @parser.parse('adsadasdas').
  • Итак, expect, был ли только что оценен кодовый блок, подняв ошибку Errno:ENOENT? Я ожидал, что это будет.

Когда вы передаете блок кода в expect, вы сообщаете expect, что вы хотите, чтобы он проанализировал полученное поведение, изменения, сделанные вашим исполнением кода, а затем, чтобы вы знали, встречается ли оно к ожиданиям, которые вы ему предоставляете.

Когда вы передаете аргумент expect, вы сообщаете ruby, чтобы оценить, что этот аргумент достигнет некоторого значения до того, как expect даже включится, и затем вы передаете это значение в expect, чтобы увидеть, встречается ли оно до некоторого ожидания.

Ответ 2

TL; DR: используйте expect(exp), чтобы указать что-то о значении exp, и используйте expect { exp }, чтобы указать побочный эффект, который возникает при выполнении exp.


Позвольте распаковать это немного. Большинство контроллеров RSpec являются сопоставимыми значениями. Они соответствуют (или нет) против любого объекта ruby. Напротив, несколько контроллеров RSpec могут быть сопоставлены только с блоком, потому что они должны наблюдать за блоком, пока он работает, чтобы работать правильно. Эти сопоставления касаются побочных эффектов, которые происходят (или нет) во время выполнения блока. Соединитель не смог бы определить, произошел ли именованный побочный эффект, если ему не передан блок для выполнения. Давайте рассмотрим встроенные блок-матрицы (по RSpec 3.1) один за другим:

raise_error

Считайте, что можно вернуть исключение из метода, и это отличается от того, что возникает исключение. Принятие исключения является побочным эффектом и может наблюдаться только солярщиком посредством выполнения блока с соответствующим предложением rescue. Таким образом, этот соединитель должен получить блок для правильной работы.

throw_symbol

Символы броска аналогичны ошибкам при поднятии - это вызывает скачок стека и является побочным эффектом, который можно наблюдать только путем запуска блока внутри соответствующего блока catch.

change

Мутация в состояние является побочным эффектом. Соединитель может только указать, было ли какое-то изменение в каком-либо состоянии, проверив состояние перед рукой, запустив блок, а затем проверив состояние после.

output

I/O - побочный эффект. Чтобы работать с output, он должен заменить соответствующий поток ($stdout или $stderr) новым StringIO, execute the block, restore the stream to its original value, and then check the contents of the StringIO`.

yield_control/yield_with_args/yield_with_no_args/yield_with_successive_args

Эти матчи немного разные. Утоление не является побочным эффектом (это действительно просто синтаксический сахар для вызова другой функции, предоставляемой вызывающим), но уступка не может наблюдаться, если посмотреть на возвращаемое значение выражения. Для того, чтобы рабочие классы соответствия работали, они предоставляют объект probe, который вы передаете методу в тесте как блок, используя синтаксис &probe:

expect { |probe| [1, 2, 3].each(&probe) }.to yield_with_successive_args(1, 2, 3)

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

Обратите внимание, что в RSpec 3 мы добавили некоторую логику, чтобы предоставить пользователям четкие ошибки, когда они используют неправильную форму expect с данным соглашением, Однако в конкретном случае expect(do_something).to raise_error мы ничего не можем сделать, чтобы дать вам четкое объяснение там - если do_something вызывает ошибку (как вы ожидаете...), тогда ошибка возникает до рубина оценивает аргумент to (совпадение raise_error), поэтому RSpec не имеет возможности проверить с помощью соединителя, чтобы увидеть, поддерживает ли значение или блокирует ожидания.

Ответ 3

В тесте, написанном с помощью круглых скобок, код выполняется нормально, включая все нормальные обработки ошибок. Синтаксис curly-brace определяет объект блока, на который вы можете поместить ожидание. Он инкапсулирует код, который вы ожидаете сломать, и позволяет rspec улавливать ошибку и обеспечивать ее собственную обработку (в данном случае успешный тест).

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

Ответ 4

:

  • используйте фигурные скобки (блок): если вы хотите протестировать behavior
  • используйте скобки, если вы хотите протестировать returned value

стоит прочитать: As for rules, you pass a block or a Proc if you're trying to test behavior (e.g. raising errors, changing some value). Otherwise, you pass a "conventional" argument, in which case the value of that argument is what is tested. - из этого ответа