Каковы лучшие практики тестирования модулей в rspec? У меня есть несколько модулей, которые включены в несколько моделей, и сейчас у меня просто есть дублирующие тесты для каждой модели (с небольшими отличиями). Есть ли способ высушить это?
ruby
unit-testing
rspec
Андрюс
источник
источник
let(:dummy_class) { Class.new { include ModuleToBeTested } }
let(:class_instance) { (Class.new { include Super::Duper::Module }).new }
таким образом я получаю переменную экземпляра, которая чаще всего используется для тестирования любым способом.include
не работает для меня, ноextend
делаетlet(:dummy_class) { Class.new { extend ModuleToBeTested } }
subject(:instance) { Class.new.include(described_class).new }
Что сказал Майк Вот тривиальный пример:
код модуля ...
фрагмент спец ...
источник
include Say
указали внутри объявления DummyClass вместо вызоваextend
?extend
в экземпляр класса, то есть после того,new
как был вызван. Если бы вы делали это до того,new
как вас вызвали, значит, вы правы, вы бы использовалиinclude
DummyClass
константу? Почему не просто@dummy_class = Class.new
? Теперь вы загрязняете свою тестовую среду ненужным определением класса. Этот класс DummyClass определен для каждой из ваших спецификаций, и в следующей спецификации вы решите использовать тот же подход и заново открыть определение DummyClass, которое может уже содержать что-то (хотя в этом тривиальном примере это определение является абсолютно пустым в реальной жизни Примеры использования, вероятно, что-то будет добавлено в какой-то момент, и тогда этот подход станет опасным.)Для модулей, которые могут быть протестированы изолированно или с помощью насмешек над классом, мне нравится что-то вроде:
модуль:
спецификация:
Может показаться неправильным захватывать вложенные группы примеров, но мне нравится краткость. Есть предположения?
источник
let
лучше использовать метод, описанный @metakungfu.Я нашел лучшее решение на домашней странице rspec. По-видимому, он поддерживает общие группы примеров. С https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/example-groups/shared-examples !
источник
Сверх того, не могли бы вы создать в своем тестовом скрипте фиктивный класс и включить в него модуль? Затем проверьте, что фиктивный класс ведет себя так, как вы ожидаете.
РЕДАКТИРОВАТЬ: Если, как указано в комментариях, модуль ожидает, что некоторые поведения будут присутствовать в классе, в который он смешан, то я бы попытался реализовать макеты этих поведений. Достаточно, чтобы модуль с радостью выполнял свои обязанности.
Тем не менее, я буду немного нервничать по поводу своего дизайна, когда модуль ожидает многого от своего хоста (мы говорим «хост»?) Класса - если я еще не наследую от базового класса или не могу внедрить новая функциональность в дереве наследования, то я думаю, что я буду пытаться минимизировать любые такие ожидания, которые может иметь модуль. Меня беспокоит то, что мой дизайн начнет развиваться в некоторых областях с неприятной негибкостью.
источник
Я думаю, что принятый ответ является правильным, однако я хотел бы добавить пример использования rpsecs
shared_examples_for
иit_behaves_like
методов. Я упоминаю несколько трюков в фрагменте кода, но для получения дополнительной информации см. Этот relishapp-rspec-guide .При этом вы можете протестировать свой модуль в любом из классов, которые его включают. Таким образом, вы действительно тестируете то, что используете в своем приложении.
Давайте посмотрим на пример:
Теперь давайте создадим спецификацию для нашего модуля:
movable_spec.rb
источник
Что о:
источник
Я хотел бы предложить, чтобы для более крупных и часто используемых модулей был выбран «Shared Example Groups», как предложено здесь @Andrius . Для простых вещей, для которых вы не хотите испытывать трудности с наличием нескольких файлов и т. Д., Вот как обеспечить максимальный контроль над видимостью ваших пустышек (протестировано с помощью rspec 2.14.6, просто скопируйте и вставьте код в spec-файл и запустите его):
источник
subject { dummy_class.new }
работает. Случай сsubject { dummy_class }
не работает для меня.моя недавняя работа, используя как можно меньше жесткой проводки
я желаю
работал, но это не так (как в Ruby MRI 2.2.3 и RSpec :: Core 3.3.0)
Очевидно, описанный_класс не виден в этой области.
источник
Чтобы проверить свой модуль, используйте:
Чтобы высушить некоторые вещи, которые вы используете в нескольких спецификациях, вы можете использовать общий контекст:
Ресурсы:
источник
Вы также можете использовать тип помощника
Вот документация: https://www.relishapp.com/rspec/rspec-rails/v/3-3/docs/helper-specs/helper-spec
источник
вам нужно просто включить ваш модуль в ваш файл спецификаций
mudule Test module MyModule def test 'test' end end end
в вашем файле спецификацийRSpec.describe Test::MyModule do include Test::MyModule #you can call directly the method *test* it 'returns test' do expect(test).to eql('test') end end
источник
Одно возможное решение для тестирования метода модуля, который не зависит от класса, который будет включать их
И спец для него
И если вы хотите DRY их протестировать, то shared_examples - хороший подход.
источник
subject(:module_to_test_instance) { Class.new.include(described_class) }
. В противном случае я не вижу ничего плохого в вашем ответе.Это повторяющийся шаблон, так как вам нужно протестировать более одного модуля. По этой причине более чем желательно создать помощника для этого.
Я нашел этот пост, который объясняет, как это сделать, но я справляюсь здесь, так как сайт может быть закрыт в какой-то момент.
Это сделано для того, чтобы экземпляры объекта не реализовывали метод экземпляра: любую ошибку, которую вы получаете при попытке использовать
allow
методыdummy
классе.Код:
В
spec/support/helpers/dummy_class_helpers.rb
В
spec/spec_helper.rb
В ваших спецификациях:
источник