Як перевірити стурбованість у рейках


104

Зважаючи на те, що я маю Personableзанепокоєння в моєму додатку Rails 4, який має full_nameметод, як би я міг пройти тестування цього за допомогою RSpec?

проблеми / personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

Які рамки тестування ви використовуєте? Також пам’ятайте, що Персональний - це просто звичайний модуль Ruby. Випробуйте його так, як ви б протестували будь-який інший міксин.
Лі Джарвіс

Не ActiveSupport::Concernвивезено з рейок? Я думав, що це пішло трохи тому.
Рассел

@LeeJarvis Я використовую Rspec разом з FactoryGirl
Kyle Decot


4
@Russell Я згоден. Тим не менш, я б не допомагав комусь із їхніми питаннями лише тому, що вони дотримувалися Rails-y способу робити щось, що я з цим не погоджувався. Так чи інакше, це не вникнути теми цього питання :-)
Лі Джарвіс

Відповіді:


176

Знайдений вами метод, безумовно, допоможе перевірити функціональність, але здається досить крихким - ваш фіктивний клас (насправді просто Structу вашому рішенні) може чи не може поводитись як справжній клас, який includeвикликає ваше занепокоєння. Крім того, якщо ви намагаєтеся перевірити проблеми з моделлю, ви не зможете робити такі речі, як перевірити дійсність об'єктів або викликати зворотні виклики ActiveRecord, якщо ви не встановите відповідну базу даних (тому що ваш клас манекена не буде підтримувати таблицю бази даних це). Крім того, ви хочете не тільки перевірити проблему, але і перевірити поведінку концерну у своїх специфікаціях.

То чому б не вбити двох птахів одним каменем? Використовуючи загальнодоступні групи прикладів RSpec , ви можете перевірити свої занепокоєння щодо фактичних класів, які їх використовують (наприклад, моделі), і ви зможете протестувати їх скрізь, де вони використовуються. І вам потрібно лише один раз написати тести, а потім просто включити їх у будь-яку специфікацію моделі, яка використовує вашу турботу. У вашому випадку це може виглядати приблизно так:

# app/models/concerns/personable.rb
module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

# spec/concerns/personable_spec.rb
require 'spec_helper'

shared_examples_for "personable" do
  let(:model) { described_class } # the class that includes the concern

  it "has a full name" do
    person = FactoryBot.build(model.to_s.underscore.to_sym, first_name: "Stewart", last_name: "Home")
    expect(person.full_name).to eq("Stewart Home")
  end
end

# spec/models/master_spec.rb
require 'spec_helper'
require Rails.root.join "spec/concerns/personable_spec.rb"

describe Master do
  it_behaves_like "personable"
end

# spec/models/apprentice_spec.rb
require 'spec_helper'

describe Apprentice do
  it_behaves_like "personable"
end

Переваги цього підходу стають ще більш очевидними, коли ви починаєте робити такі проблеми, як викликати зворотній зв'язок AR, де нічого менше, ніж об'єкт AR, просто не буде робити.


2
Одним недоліком цього є те, що він сповільниться parallel_tests. Я думаю, що буде краще мати окремі тести замість використання shared_examples_forта it_behaves_like.
Артем Калінчук

6
@ArtemKalinchuk Я не впевнений, що це правда, per github.com/grosser/parallel_tests/isissue/168 parallel_tests базується на одному файлі, тому спільні приклади не повинні сповільнювати це. Я також зауважу, що належним чином згруповані спільні форми поведінки, козирі випробовують швидкість.
Аарон К

8
Обов’язково включіть concernsкаталог у свій spec_helper.rb github.com/rspec/rspec-core/isissue/407#issuecomment-1409871
Ziggy

1
Я не зміг знайти нічого про включення до цього каталогу посилань. Не могли б ви пояснити, як це робиться? Я не можу отримати свій тест RSpec для розпізнавання модуля в одному з моїх проблем.
Джейк Сміт

4
Не додайте _specдо імені файлу, який містить shared_examples_for (персональний_спец. В цьому випадку), інакше ви отримаєте оману попереджувального повідомлення - github.com/rspec/rspec-core/isissue/828 .
Лалу

62

У відповідь на коментарі, які я отримав, ось що я закінчив (якщо хтось має покращення, будь ласка, не соромтеся опублікувати їх) :

spec / проблеми / personable_spec.rb

require 'spec_helper'

describe Personable do
  let(:test_class) { Struct.new(:first_name, :last_name) { include Personable } }
  let(:personable) { test_class.new("Stewart", "Home") }

  it "has a full_name" do
    expect(personable.full_name).to eq("#{personable.first_name} #{personable.last_name}")
  end
end

1
Так, інші тести будуть порушені, якщо вони трапляються для перевірки справжнього класу під назвою Person. Я відредагую, щоб виправити.
Рассел

Це не працює. Це дає мені помилку:undefined method 'full_name' for #<struct first_name="Stewart", last_name="Home">
Кайл Деко

Спробуйте включити Персональний, а не продовжувати його. Я оновлю відповідь.
Рассел

Зараз чудово працює. Дякуємо, що вказали на мене в правильному напрямку та допомогли мені рефактор @Russell
Kyle Decot

Чудово працює і виглядає приємно
Едвард

7

Ще одна думка - використовувати дорогоцінний камінь with_model для тестування подібних речей. Я шукав, щоб перевірити своє занепокоєння і бачив, як це робиться дорогоцінний камінь pg_search . Це здається набагато кращим, ніж тестування на окремих моделях, оскільки вони можуть змінитися, і приємно визначити речі, які вам знадобляться, у вашій специфікації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.