w moim app mam taki kod:RSpec: jak sprawdzić operacje na plikach i złożyć zawartości
File.open "filename", "w" do |file|
file.write("text")
end
Chcę przetestować ten kod poprzez RSpec. Jakie są najlepsze praktyki w tym zakresie?
w moim app mam taki kod:RSpec: jak sprawdzić operacje na plikach i złożyć zawartości
File.open "filename", "w" do |file|
file.write("text")
end
Chcę przetestować ten kod poprzez RSpec. Jakie są najlepsze praktyki w tym zakresie?
Proponuję użyć do tego celu StringIO
i upewnić się, że SUT akceptuje strumień do zapisu zamiast nazwy pliku. W ten sposób różne pliki lub wyjścia mogą być wykorzystane (więcej wielokrotnego użytku), w tym ciąg IO (dobry do testowania)
to w kodzie testowym (zakładając, że instancja SUT jest sutObject
i serializer nazwie writeStuffTo
:
testIO = StringIO.new
sutObject.writeStuffTo testIO
testIO.string.should == "Hello, world!"
String IO zachowuje się jak otwartego pliku. Więc jeśli kod już może pracować z obiektem pliku, to będzie działać z StringIO.
To była doskonała odpowiedź. Chciałbym móc cię głosować więcej niż raz. – Jazzepi
Dobra odpowiedź, wiem, że nie została zadana, ale byłoby idealnie, gdyby zawierała również przykład "przeczytania" partnera. –
Jak zmodyfikować kod, aby użyć String.IO? Wydaje się, że wynikowy kod będzie znacznie brzydszy, tak więc testowanie jest łatwiejsze? –
przypadku bardzo prosty I/o, można po prostu mock plików. Tak więc, biorąc pod uwagę :
def foo
File.open "filename", "w" do |file|
file.write("text")
end
end
następnie:
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
Jednak takie podejście spada płasko w obecności wielu odczytuje/zapisuje: proste refaktoryzacji, które nie zmieniają stan końcowy pliku może spowodować test złamać. W takim przypadku (i ewentualnie w każdym przypadku) powinieneś wybrać odpowiedź @Danny Staple.
Można użyć fakefs.
To odcinki plików i tworzy pliki w pamięci
sprawdzeniu z
File.exists? "filename"
jeśli plik został utworzony.
Można też po prostu czytać z
File.open
i uruchomić oczekiwanie na jego zawartość.
Należy pamiętać, że FakeFS nie działa z Rspec (zarówno Rspec 2, jak i Rspec 3) - https://github.com/fakefs/fakefs/issues/215 –
ten sposób mock File (z rspec 3.4), więc można pisać do bufora i sprawdzić jego zawartość później:
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
Dla kogoś takiego jak ja, który trzeba zmodyfikować kilka plików w różnych katalogach (np. generator dla Railsów), używam folderu tymczasowego.
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)
@Wayne Zastanawiam się, w jaki sposób postępować z testunit patrz [to pytanie] [1] [1]: http://stackoverflow.com/questions/11619884/ testunit-how-to-test-file-operations-and-file-content – netbe