我写了一个单元测试如下。
describe Youtube::Metadata do
let(:subject) { SampleMetadata.from_text(open(url)) }
context "when url is passed" do
let(:url) { "http://www.sample.com" }
describe "It should return all values from the site" do
its(:id) { should eql "234" }
its(:url) { should eql "www.sample.com" }
end
context "Given a html file with id property" do
let(:html) { File.join(PAGES, 'youtube', 'sample1.html') }
let(:subject) { Youtube::Metadata.from_text(File.read(html)) }
it "should return unique value from id property" do
subject.unique_id.should eql "65155c6e-ba11-42fc-bb91-53520176d2a8"
end
end
context "Given a html file with rel:canonical property" do
let(:html) { File.join(PAGES, 'youtube', 'sample2.html') }
let(:subject) { Youtube::Metadata.from_text(File.read(html)) }
it "should return unique value from rel=canonical content property" do
subject.unique_id.should eql "65155c6e-ba11-42fc-bb91-53520176d2a8"
end
end
end
end
我需要重构它,以便我不必在每个测试用例中重复以下语句。
let(:subject) { Youtube::Metadata.from_text(File.read(html))
我在阻止之前尝试了它,但它没有工作。
实际上我们传递url的第一个上下文和第二组上下文 我们传递文件名。此外,我不确定是否需要将其作为一个 单个上下文(传递文件名上下文,即最后两个)并描述它。
这样做的正确方法是什么?
答案 0 :(得分:2)
我认为你提出了很好的问题,但让我们退一步考虑一般的测试。您正在寻找干扰您的测试,因为您认识到重复的代码 - 很棒。测试意味着易于阅读和易于理解。
谢天谢地rspec
可让您访问context
和describe
等内容,以便将测试分成几部分。您的测试是分开的,并且您正在使用let变量(这反过来创建实例变量范围),用于您在一次测试中仅使用的内容。
对我来说,这似乎有些过分,而且你会增加一个测试的复杂性,否则这个测试会自动包含在普通it
块中。
例如,这似乎是一组更有条理的测试:
describe Youtube::Metadata do
include Helpers
# ... omitted ...
context "Given a html file with id property" do
it "should return unique value from id property" do
subject = file_loader('youtube','sample1.html')
subject.unique_id.should eql "65155c6e-ba11-42fc-bb91-53520176d2a8"
end
end
context "Given a html file with rel:canonical property" do
it "should return unique value from rel=canonical content property" do
subject = file_loader('youtube','sample2.html')
subject.unique_id.should eql "65155c6e-ba11-42fc-bb91-53520176d2a8"
end
end
end
end
然后只需创建一个帮助器:
module Helpers
def file_loader(dir, filename)
file = File.join(PAGES, dir, filename)
Youtube::Metadata.from_test(file)
end
end
答案 1 :(得分:1)
您可以使用shared_examples
:
shared_examples_for "unique id parser" do |sample_file, expected_id|
let(:html) { File.join(PAGES, 'youtube', sample_file) }
subject { Youtube::Metadata.from_text(File.read(html)) }
it "parses unique id property" do
expect(subject.unique_id).to eql expected_id
end
end
context "Given a html file with id property" do
it_behaves_like "unique id parser", 'sample1.html', "65155c6e-ba11-42fc-bb91-53520176d2a8"
end
context "Given a html file with rel:canonical property" do
it_behaves_like "unique id parser", 'sample2.html', "65155c6e-ba11-42fc-bb91-53520176d2a8"
end
答案 2 :(得分:0)
首先,为第二个和第三个使用另一个名称":subject"因为你已经有一个在outter区。
其次,你真的需要' sample1.html'和' sample2.html'?如果没有,请更改为' sample.html'并且让他们两个都开始。
第三,检查你是否有一些lazzy load的问题(改变让我们!)
答案 3 :(得分:0)
将其与另一个背景分组:
describe Youtube::Metadata do
# ...
context "given a html file" do
subject { Youtube::Metadata.from_text(File.read(file)) }
context "with id property" do
let(:file) { File.join(PAGES, 'youtube', 'sample1.html') }
it "should return unique value from id property" do
# ...
end
end
context "with rel:canonical property" do
let(:file) { File.join(PAGES, 'youtube', 'sample2.html') }
it "should return unique value from rel=canonical content property" do
# ...
end
end
end
end