Rspec: comment tester les opérations sur les fichiers et le contenu des fichiers

Dans mon application, j’ai un tel code:

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

Je veux tester ce code via rspec. Quelles sont les meilleures pratiques pour ce faire?

Je suggère d’utiliser SsortingngIO pour cela et de vous assurer que votre SUT accepte un stream à écrire au lieu d’un nom de fichier. Ainsi, différents fichiers ou sorties peuvent être utilisés (plus réutilisables), y compris la chaîne IO (bon pour les tests)

Donc, dans votre code de test (en supposant que votre instance SUT est sutObject et que le sérialiseur s’appelle writeStuffTo :

 testIO = SsortingngIO.new sutObject.writeStuffTo testIO testIO.ssortingng.should == "Hello, world!" 

Ssortingng IO se comporte comme un fichier ouvert. Donc, si le code peut déjà fonctionner avec un object File, il fonctionnera avec SsortingngIO.

Pour des e / s très simples, vous pouvez simplement simuler File. Donc, donné:

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

puis:

 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 

Cependant, cette approche tombe à plat en présence de lectures / écritures multiples: des refactorisations simples qui ne modifient pas l’état final du fichier peuvent provoquer la rupture du test. Dans ce cas (et éventuellement dans tous les cas), vous devriez préférer la réponse de @Danny Staple.

Vous pouvez utiliser des faux .

Il stubs system et crée des fichiers en mémoire

Vous vérifiez avec

 File.exists? "filename" 

si le fichier a été créé.

Vous pouvez aussi simplement le lire avec

 File.open 

et exécuter des attentes sur son contenu.

Voici comment simuler File (avec rspec 3.4), pour pouvoir écrire dans un tampon et vérifier son contenu plus tard:

 it 'How to mock File.open for write with rspec 3.4' do @buffer = SsortingngIO.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.ssortingng).to eq(@content) end 

Pour quelqu’un comme moi qui a besoin de modifier plusieurs fichiers dans plusieurs répertoires (par exemple un générateur pour Rails), j’utilise le dossier 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)