我正在尝试为从文本文件读取的FileProcessor创建测试,将其传递给另一个类然后写入输出。我制作了一个测试文件并且能够访问,但感觉很笨重。我还需要测试它是否将输出写入新文件中,我不知道如何设置它。我已经看过很多教程,但它们都是以rails为中心的。我的目标是摆脱在测试中编写路径并在每次测试后清理生成的输出文件。
describe FileProcessor do
test_file = File.dirname(__FILE__) + '/fixtures/test_input.txt'
output_file = File.dirname(__FILE__) + '/fixtures/test_output.txt'
subject {FileProcessor.new(test_file, output_file)}
describe '#read_file' do
it 'reads a file' do
expect(subject.read_file).to eq('This is a test.')
end
end
def write_file(str)
File.open("#{output_file}", "w+") { |file| file.write(str) }
end
end
答案 0 :(得分:2)
避免编写输入文件的路径并不是一个好方法。您可以将其移动到辅助方法中,但另一方面,在测试中使用路径具有以下好处:其他人(或者您从现在起六个月后)查看代码将立即知道测试数据的来源。
对于输出文件,最简单的解决方案是使用Ruby的内置Tempfile类。 Tempfile.new
与File.new
类似,不同之处在于它会自动将文件放入/tmp
(或您的操作系统的临时文件目录所在的位置)并为其指定唯一名称。这样您就不必担心要清理它,因为下次运行测试时,它会使用一个名称不同的文件(您的操作系统会自动删除该文件)。例如:
require 'tempfile'
describe FileProcessor do
let(:test_file_path) { File.dirname(__FILE__) + '/fixtures/test_input.txt' }
let(:output_file) { Tempfile.new('test_output.txt').path }
subject { FileProcessor.new(test_file_path, output_file.path) }
describe '#read_file' do
it 'reads a file' do
expect(subject.read_file).to eq('This is a test.')
end
end
end
使用let
(而不仅仅是分配局部变量)可确保每个示例都使用自己唯一的输出文件。在RSpec中,您几乎总是更喜欢let
。
如果你想变得非常认真,你可以使用FakeFS gem来嘲笑所有Ruby内置的文件相关类(文件,路径名等),这样你就可以# 39;永远不要写入你的实际文件系统。这是使用FakeFS的快速教程:http://www.bignerdranch.com/blog/fake-it/
答案 1 :(得分:2)
如何使用StringIO:
require 'stringio'
class FileProcessor
def initialize(infile, outfile)
@infile = infile
@outfile = outfile
@content = nil
end
def read_file
@content ||= @infile.read
end
def write_file(text)
@outfile.write(text)
end
end
describe FileProcessor do
let(:outfile) { StringIO.new }
subject(:file_processor) do
infile = StringIO.new('This is a test')
FileProcessor.new(infile, outfile)
end
describe '#read_file' do
it "returns correct text" do
expect(file_processor.read_file).to eq("This is a test")
end
end
describe '#write_file' do
it "writes correct text" do
file_processor.write_file("Hello world")
outfile.rewind
expect(outfile.read).to eq("Hello world")
end
end
end