How to taunt / stifle a file directory and their contents with RSpec?

Some time ago, I asked " how to check the receipt of a list of files in a directory using RSpec? ", And although I got a couple of useful answers, m is still stuck, therefore, a new question arises with more details about what I'm trying to do.

I am writing my first RubyGem. It has a module containing a class method that returns an array containing a list of non-hidden files in the specified directory. Like this:

files = Foo.bar :directory => './public'

The array also contains an element representing metadata about the files. This is actually a hash of the hashes generated from the contents of the files, the idea is that changing even one file changes the hash.

I wrote my pending RSpec examples, but I really don't know how to implement them:

it "should compute a hash of the files within the specified directory"
it "shouldn't include hidden files or directories within the specified directory"
it "should compute a different hash if the content of a file changes"

I really do not want the tests to depend on real files playing the role of lights. How can I mock files and their contents? The gem implementation will use Find.find, but as one of the answers to my other question said, I do not need to test the library.

I really don't know how to write these specifications, so any help is much appreciated!


Change . The following is the method cacheI'm trying to verify:

require 'digest/md5'
require 'find'

module Manifesto   
  def self.cache(options = {})
    directory = options.fetch(:directory, './public')
    compute_hash  = options.fetch(:compute_hash, true)
    manifest = []
    hashes = ''
    Find.find(directory) do |path|

      # Only include real files (i.e. not directories, symlinks etc.)
      # and non-hidden files in the manifest.
      if File.file?(path) && File.basename(path)[0,1] != '.'
        manifest << "#{normalize_path(directory, path)}\n"
        hashes += compute_file_contents_hash(path) if compute_hash
      end
    end

    # Hash the hashes of each file and output as a comment.
    manifest << "# Hash: #{Digest::MD5.hexdigest(hashes)}\n" if compute_hash
    manifest << "CACHE MANIFEST\n"
    manifest.reverse
  end

  # Reads the file contents to calculate the MD5 hash, so that if a file is
  # changed, the manifest is changed too.
  def self.compute_file_contents_hash(path)
    hash = ''
    digest = Digest::MD5.new
    File.open(path, 'r') do |file|
      digest.update(file.read(8192)) until file.eof
      hash += digest.hexdigest
    end
    hash
  end

  # Strips the directory from the start of path, so that each path is relative
  # to directory. Add a leading forward slash if not present.
  def self.normalize_path(directory, path)
    normalized_path = path[directory.length,path.length]
    normalized_path = '/' + normalized_path unless normalized_path[0,1] == '/'
    normalized_path
  end      
end
+3
source share
3 answers

, , , . get_file_hash .

def get_file_hash
  file_hash = {}
  Find.find(Dir.pwd) do |file| 
    file_hash[file] = compute_hash(File.read(file))
  end
  file_hash
end

, Find.find File.read. compute_hash, . compute_hash .

describe "#get_file_hashes"

  ......

  before(:each)
    File.stubs(:find).returns(['file1', 'file2'])
    File.stubs(:read).with('file1').returns('some content')
    File.stubs(:read).with('file2').returns('other content')
  end

  it "should return the hash for all files"
@whatever_object.get_file_hashes.should eql({'file1' => "hash you are expecting for 'some content'", 'file2' => "hash you are expecting for 'other content'"})
end

end

compute_hash . , compute_hash , . , compute_hash. , compute_hash , get_file_hash.

; , , , . - ( , ), , .

; , - , . .

+3

MockFS ? http://mockfs.rubyforge.org/

, Fake FS , , .

+1

, , ? , , , , .

: , FakeFS File.read, , , .

+1

Source: https://habr.com/ru/post/1748539/


All Articles