Ошибка теста контроллера Rspec с символом апострофа?

Прямо сейчас у меня есть модульные тесты, которые не работают с использованием названия компании «Faker».

похоже, что expect(response.body).to match(@thing.name) запутался.

При просмотре ошибки в названиях компаний-фейкеров иногда встречаются такие слова, как «Компания О'Брайан» или «Компания О'Хара» или что-то подобное.

Является ли faker закодированной строкой? так как я знаю, что не рекомендуется сопоставлять закодированные строки, и я действительно не хочу просто указывать конкретное название компании в Фабрике, которую я использую.

Спасибо


person msmith1114    schedule 23.01.2017    source источник
comment
Мне любопытно, почему вы решили, что моего ответа недостаточно. Я могу что-нибудь уточнить?   -  person Mickey Sheu    schedule 30.01.2017
comment
Проблема с включением заключается в том, что если оно содержится, я хочу, чтобы оно полностью совпадало с ним, а не только с тем, чтобы слово существовало в имени. Хотя я могу использовать его как запасной вариант, в котором я отмечу ваш ответ как правильный :). Я действительно просто пытаюсь искать другие возможности.   -  person msmith1114    schedule 30.01.2017


Ответы (4)


Faker не будет делать за вас никакого кодирования. Он просто даст вам строку типа O'Malley. Но в ответе должно быть HTML-экранирование (или какое-то другое, в зависимости от формата), например O'Malley. Вы всегда можете puts response.body убедиться в этом.

Сопоставитель RSpec matches действительно разработан для expected или actual быть регулярным выражением, но в вашем случае оба являются строками. Поскольку код вызывает оптимизацию values_match? который выполняет простой сравнения, вы фактически говорите expect(response.body).to eq(@thing.name).

Если вам нужно регулярное выражение, вы правы в том, что вам следует быть осторожным, используя неконтролируемые значения для его создания. К счастью, в Ruby для этого есть Regexp.escape, так что вам можно сказать Regexp.new("foo" + Regexp.escape(@thing.name) + "bar"). Но судя по вашему возражению против include, вы на самом деле хотите, чтобы ответ не содержал ничего, кроме имени, верно? В этом случае вам вообще не нужно регулярное выражение.

В любом случае проблема не в том, что вокруг имени, а в том, как это имя экранируется. Поэтому перед сравнением вы должны либо (1) декодировать ответ, либо (2) кодировать поддельную строку. Неважно какой. Оба довольно просты:

expect(CGI.unescapeHTML(response.body)).to eq @thing.name

or

expect(response.body).to eq CGI.escapeHTML(@thing.name)

Естественно, если ваш ответ - JSON, вы должны заменить все эти экранирующие элементы HTML на JSON и т. д.

person Paul A Jungwirth    schedule 30.01.2017
comment
Быстрый вопрос: что это за CGI в ваших ожидаемых функциях. Это то, что их кодирует? - person msmith1114; 31.01.2017
comment
CGI является частью стандартной библиотеки Ruby: ruby-doc .org/stdlib-2.3.0/libdoc/cgi/rdoc/CGI.html - person Paul A Jungwirth; 31.01.2017

Вы можете попробовать использовать #include вместо #match.

expect(response.body).to include(@thing.name)
person Mickey Sheu    schedule 23.01.2017

Предположим, вы имеете в виду Faker::Company из < жемчужина href="https://github.com/stympy/faker" rel="nofollow noreferrer">Faker

Правильный способ выполнить ожидание вашего примера — использовать Regexp, как в примере @rafael-costa. Это позволяет избежать таких вещей, как апострофы.

Проблема с использованием Faker заключается в том, что ваши тесты не являются детерминированными. Лучше всего предоставлять статические известные входные данные для теста и ожидать, что выходные данные будут соответствовать определенным ожиданиям на основе этих входных данных. Трудно привести соответствующий пример без дополнительной информации, но, возможно, что-то вроде этого:

company = Company.new(name: 'Acme Anvils')
get :show, params: {id: company.to_param}, session: {}
expect(response.body).to match(Regexp.new('Acme Anvils', Regexp::MULTILINE))

Также, как правило, вам не следует тестировать конкретный вывод тела в рамках спецификаций вашего контроллера. Для этого нужно тестировать разные цели. Обычно вы должны написать view тест для этого.

person Midwire    schedule 30.01.2017

Вы можете попробовать передать регулярное выражение вместо строки:

expect(response.body).to match(Regexp.new(@thing.name))

Кроме того, если проблема заключается только в том, что вы получаете имена такого типа от мошенников, вам следует взглянуть на этот QA , Это дает некоторые хорошие идеи.

person Rafael Costa    schedule 30.01.2017
comment
Я предполагаю, что проблема в том, что НЕ использую его, мне нужно будет определить много тестовых данных. Но в некотором смысле это хорошо, потому что, например, он показывает проблемы с нечетными значениями. - person msmith1114; 30.01.2017