Как протестировать беспокойство в Rails

Учитывая, что у меня есть проблема с Personable в моем приложении Rails 4, у которого есть метод full_name, как бы я мог протестировать это с помощью RSpec?

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

module Personable
  extend ActiveSupport::Concern

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

Ответ 1

Метод, который вы нашли, безусловно, будет работать для тестирования небольшого количества функциональности, но кажется довольно хрупким - ваш фиктивный класс (фактически, просто 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

В ответ на полученные комментарии, вот что я в итоге сделал (если у кого-то есть улучшения, пожалуйста, не стесняйтесь их публиковать):

спецификации/проблемы/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

Ответ 3

Другая мысль состоит в том, чтобы использовать with_model gem для проверки подобных вещей. Я сам пытался проверить проблему и видел, как это делает гем pg_search. Кажется, это намного лучше, чем тестирование на отдельных моделях, поскольку они могут измениться, и было бы неплохо определить, что вам понадобится в вашей спецификации.