Il ya quelque temps, j'ai demandé "How to test obtaining a list of files within a directory using RSpec?" et même si j'ai eu quelques réponses utiles, je suis toujours coincé, d'où une nouvelle question avec plus de détails sur ce que je suis en train de faire.Comment copier/coller un répertoire de fichiers et leur contenu en utilisant RSpec?
J'écris mon premier RubyGem. Il a un module qui contient une méthode de classe qui retourne un tableau contenant une liste de fichiers non-cachés dans un répertoire spécifié. Comme ceci:
files = Foo.bar :directory => './public'
Le tableau contient également un élément qui représente les métadonnées sur les fichiers. C'est en fait un hachage de hachages générés à partir du contenu des fichiers, l'idée étant que changer même un seul fichier change le hachage.
J'ai écrit mes exemples RSpec en attente, mais je ne sais vraiment pas comment les mettre en œuvre:
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"
Je ne veux pas avoir des tests qui dépendent des fichiers réels agissant en tant que luminaires. Comment puis-je mocker ou écraser les fichiers et leur contenu? L'implémentation de gem utilisera Find.find
, mais comme l'une des réponses à mon autre question dit, je n'ai pas besoin de tester la bibliothèque.
Je n'ai vraiment aucune idée de comment écrire ces spécifications, donc toute aide très appréciée!
Modifier: La méthode cache
est la méthode ci-dessous, je suis en train de tester:
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
Merci. Je viens d'éditer la question pour inclure le code que j'essaie de tester. –
Je serai en train de forcer le manifeste et je vous enverrai une demande de retrait une fois que j'aurai fait les changements. Semble Ok? – nas
Brillant, ça a l'air parfait. Merci! –