鉴于我在我的Rails 4应用程序中有一个Personable
问题,该应用程序有full_name
方法,我将如何使用RSpec进行测试?如何在Rails中测试问题
顾虑/ personable.rb
module Personable
extend ActiveSupport::Concern
def full_name
"#{first_name} #{last_name}"
end
end
鉴于我在我的Rails 4应用程序中有一个Personable
问题,该应用程序有full_name
方法,我将如何使用RSpec进行测试?如何在Rails中测试问题
顾虑/ personable.rb
module Personable
extend ActiveSupport::Concern
def full_name
"#{first_name} #{last_name}"
end
end
您发现的方法肯定会测试一些功能,但看起来非常脆弱 - 您的虚拟类(实际上在您的解决方案中只是一个Struct
)可能会或可能不会像您真正关注的真实类。此外,如果您试图测试模型问题,则无法执行诸如测试对象有效性或调用ActiveRecord回调的操作,除非相应地设置数据库(因为您的虚拟类不会有数据库表的后备它)。此外,您不仅要测试关注点,还要测试模型规范中关注点的行为。
那么,为什么不用一石二鸟呢?通过使用RSpec的shared example groups,您可以测试您对使用它们的实际类(例如,模型)和的担忧,您可以在使用它们的任何地方测试它们。你只需要编写一次测试,然后把它们包含在任何使用你的关注的模型规范中。在你的情况,这可能是这个样子:
# 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 = FactoryGirl.create(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对象刚刚获得”更加明显的优势不要做。
这样做的一个缺点是它会减缓'parallel_tests'。我认为单独的测试代替使用'shared_examples_for'和'it_behaves_like'会更好。 – 2014-01-21 12:23:18
@ArtemKalinchuk我不确定这是否属实,根据https://github.com/grosser/parallel_tests/issues/168'parallel_tests'基于每个文件,因此共享示例不应该减慢速度。我也会争辩说,适当分组的共享行为,胜过测试速度。 – 2014-04-09 22:16:43
确保在您的'spec_helper.rb'中包含'concern'目录https://github.com/rspec/rspec-core/issues/407#issuecomment-1409871 – Ziggy 2014-06-06 00:20:49
在回答我收到的意见,这里就是我最后做(如果任何人有改善,请随意张贴他们) :
规格/顾虑/ 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
personable.full_name.should == "#{personable.first_name} #{personable.last_name}"
end
end
另一个想法是使用with_model gem来测试这样的事情。我正在考虑自己测试一个问题并看过pg_search gem doing this。这似乎比在单个模型上测试要好得多,因为这些模型可能会发生变化,并且很好定义您的规范中需要的东西。
你正在使用什么测试框架?还记得Personable只是一个普通的Ruby模块。像测试其他mixin一样测试它。 – 2013-05-13 15:05:30
没有'ActiveSupport :: Concern'被从Rails中取出?我以为这是前一阵子。 – Russell 2013-05-13 15:06:36
@LeeJarvis我沿着w/FactoryGirl使用Rspec – 2013-05-13 15:08:00