Rspec: cómo probar las operaciones y el contenido del archivo


En mi aplicación tengo dicho código:

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

Quiero probar este código a través de rspec. ¿Cuáles son las mejores prácticas para hacer esto?

Author: go minimal, 2010-11-01

5 answers

Sugeriría usar StringIOpara esto y asegurarse de que su SUT acepta una secuencia para escribir en lugar de un nombre de archivo. De esa manera, se pueden usar diferentes archivos o salidas (más reutilizables), incluida la cadena IO (buena para probar)

Así que en su código de prueba (suponiendo que su instancia SUT es sutObject y el serializador se llama writeStuffTo:

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

String IO se comporta como un archivo abierto. Así que si el código ya puede trabajar con un objeto File, funcionará con StringIO.

 54
Author: Danny Staple,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-10 10:25:04

Para e/s muy simples, solo puede simular el archivo. Así, dado:

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

Entonces:

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

Sin embargo, este enfoque cae plano en presencia de múltiples lecturas/escrituras: refactorizaciones simples que no cambian el estado final del archivo pueden causar que la prueba se rompa. En ese caso (y posiblemente en cualquier caso) deberías preferir la respuesta de @Danny Staple.

 45
Author: Wayne Conrad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-02 05:25:08

Puede usar fakefs.

Extrae el sistema de archivos y crea archivos en la memoria

Se comprueba con

File.exists? "filename" 

Si se creó el archivo.

También puedes leerlo con

File.open 

Y ejecutar la expectativa sobre su contenido.

 17
Author: mehowte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-07 20:08:37

Esta es la forma de simular el archivo (con rspec 3.4), para que pueda escribir en un búfer y comprobar su contenido más tarde:

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
 17
Author: Eduardo Santana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-27 10:32:16

Para alguien como yo que necesita modificar varios archivos en varios directorios (por ejemplo, generator for Rails), uso la carpeta 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
Author: lulalala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-02 12:47:41