我正在尝试测试Author类的#初始化:
# lib/author.rb
class Author
attr_reader :name, :filename, :website
def initialize(name, filename, website)
@name = name
@filename = filename
set_filename_from_name if filename == :auto
@website = website
end
end实际上,Author有8-9个属性,而不仅仅是3个,我已经决定在#初始化中要求它们全部实现。
我正试图把我的规格弄干,但我有很多重复。
我创建了一个助手模块:
#spec/helpers/create_author.rb
module CreateAuthor
# Creates author with default values except for those listed
# under params.
def create_author(params = {})
defaults = {
name: "Ford",
filename: "Ford",
website: 'www.ford.com'
}
opt = defaults.merge(params)
Author.new(opt[:name],
opt[:filename],
opt[:website])
end
end但是现在我有了未经测试的代码,我需要进行测试。这是该助手方法的规范:
# spec/authors_helper_spec.rb
require_relative 'helpers/create_author'
describe 'Create Author Helper' do
# subject do
# Class.new { include CreateAuthor }
# end
include CreateAuthor
let(:defaults) do
{
name: "Ford",
filename: "Ford",
website: 'www.ford.com'
}
end
describe '#create_author' do
it 'returns author with default values when called with no parameters' do
author = create_author()
expect(author.class).to eq(Author)
expect(author.name).to eq(defaults[:name])
expect(author.filename).to eq(defaults[:filename])
expect(author.website).to eq(defaults[:website])
end
it 'returns author with custom name when specified' do
author = create_author(name: 'New Name')
expect(author.class).to eq(Author)
expect(author.name).to eq('New Name')
expect(author.filename).to eq(defaults[:filename])
expect(author.website).to eq(defaults[:website])
end
end
end我需要对其他类做类似的事情,所以我只需要将create_author(options={})更改为create_class(class, options={})并对其进行测试。
我怎么才能把它弄干,让它不那么冗长呢?
发布于 2016-10-11 23:04:07
您可以使用以下解决方案,除非在"create_author“中调用初始化很重要。
# spec/helpers/create_author.rb
module CreateEntity
def create_entity(klass, params = {}, defaults = {})
opt = defaults.merge(params)
entity = klass.allocate
opt.each do |key, value|
entity.instance_variable_set("@#{key}", value)
end
entity
end
def create_author(params = {})
create_entity(Author, params, {
name: "Ford",
filename: "Ford",
website: 'www.ford.com'
})
end
end
create_author(name: "Ford 1")发布于 2016-10-13 10:15:26
我会给大家举一个例子。它没有经过测试,但它应该像这样工作:
#spec/helpers/shares_examples/check_default_behaviour.rb
RSpec.shared_examples 'check default behaviour' do |class_to_instantiate|
def create_instance(params = {})
opt = defaults.merge(params)
class_to_instantiate.new(opt[:name],
opt[:filename],
opt[:website])
end
# let(:defaults) has to be set within your spec
describe "#create_#{class_to_instantiate}" do
it "returns #{class_to_instantiate} with default values when called with no parameters" do
instance = create_instance()
expect(instance.class).to eq(class_to_instantiate)
expect(instance.name).to eq(defaults[:name])
expect(instance.filename).to eq(defaults[:filename])
expect(instance.website).to eq(defaults[:website])
end
it "returns #{class_to_instantiate} with custom name when specified" do
instance = create_instance(name: 'New Name')
expect(instance.class).to eq(class_to_instantiate)
expect(instance.name).to eq('New Name')
expect(instance.filename).to eq(defaults[:filename])
expect(instance.website).to eq(defaults[:website])
end
end
end
# spec/...
describe 'Create Author Helper' do
let(:defaults) do
{
name: "Ford",
filename: "Ford",
website: 'www.ford.com'
}
end
include_examples 'check default behaviour', Author
end发布于 2016-10-23 20:12:49
您应该尽可能地使您的测试用例依赖于共享代码。
这是一个更大的策略的一部分,以使更多的“可测试”代码。在您的主要应用程序中,如果您有三种类似的方法,并且想要100%的单元测试覆盖率,那么您必须对这三种方法进行测试。但是,如果您重构应用程序代码以使用一种方法,那么应用程序代码和测试都将更加简洁。
重申一下--仅仅是为了理智,如果你打算写100%的单元测试覆盖率,那么写“可测试的”代码是值得的--如果你的代码杂乱无章,就没有什么神奇的方法可以让你的测试套件变得简洁。
我可能是误解了,但是除了应用程序代码之外,您还想测试您的助手吗?这样做可能有点过分--人们真的在测试他们的测试套件吗?
https://codereview.stackexchange.com/questions/143818
复制相似问题