web-dev-qa-db-ja.com

Rspec:ファイル操作とファイルコンテンツをテストする方法

私のアプリにはそのようなコードがあります:

File.open "filename", "w" do |file|
  file.write("text")
end

このコードをrspecでテストしたいと思います。これを行うためのベストプラクティスは何ですか?

42
petRUShka

このためにStringIOを使用し、 [〜#〜] sut [〜#〜] がファイル名の代わりに書き込むストリームを受け入れることを確認することをお勧めします。このように、文字列IO(テストに適しています)を含む、さまざまなファイルまたは出力を使用できます(より再利用可能)

したがって、テストコードでは(SUTインスタンスがsutObjectで、シリアライザーの名前がwriteStuffToであると仮定します。

testIO = StringIO.new
sutObject.writeStuffTo testIO 
testIO.string.should == "Hello, world!"

String IOは開いているファイルのように動作します。したがって、コードがFileオブジェクトで既に動作できる場合、StringIOで動作します。

57
Danny Staple

非常にシンプルなI/Oの場合は、Fileをモックできます。だから、与えられた:

def foo
  File.open "filename", "w" do |file|
    file.write("text")
  end
end

その後:

describe "foo" do

  it "should create 'filename' and put 'text' in it" do
    file = mock('file')
    File.should_receive(:open).with("filename", "w").and_yield(file)
    file.should_receive(:write).with("text")
    foo
  end

end

ただし、このアプローチは、複数の読み取り/書き込みが存在する場合、フラットになります。ファイルの最終状態を変更しない単純なリファクタリングにより、テストが中断する可能性があります。その場合(場合によっては)、@ Danny Stapleの回答を好むべきです。

47
Wayne Conrad

これは、ファイル(rspec 3.4を使用)をモックする方法です。したがって、バッファに書き込んで、その内容を後で確認できます。

it 'How to mock File.open for write with rspec 3.4' do
  @buffer = StringIO.new()
  @filename = "somefile.txt"
  @content = "the content fo the file"
  allow(File).to receive(:open).with(@filename,'w').and_yield( @buffer )

  # call the function that writes to the file
  File.open(@filename, 'w') {|f| f.write(@content)}

  # reading the buffer and checking its content.
  expect(@buffer.string).to eq(@content)
end
18
Eduardo Santana

fakefs を使用できます。

ファイルシステムをスタブ化し、メモリ内にファイルを作成します

確認する

File.exists? "filename" 

ファイルが作成された場合。

次のように読むこともできます

File.open 

その内容に期待をかけます。

17
mehowte

複数のディレクトリ内の複数のファイルを変更する必要がある私のような人(例えばRailsのジェネレーター)には、tempフォルダーを使用します。

Dir.mktmpdir do |dir|
  Dir.chdir(dir) do
    # Generate a clean Rails folder
    Rails::Generators::AppGenerator.start ['foo', '--skip-bundle']
    File.open(File.join(dir, 'foo.txt'), 'w') {|f| f.write("write your stuff here") }
    expect(File.exist?(File.join(dir, 'foo.txt'))).to eq(true)
0
lulalala