Прежде чем ответить на вопрос о том, как это сделать в Ruby, я бы хотел устранить некоторые недоразумения.
Во-первых, я бы не сказал, что существует такой "метод Ruby" для тестирования подобных вещей, как строгий способ тестирования чего-то подобного в .NET (который, по общему признанию, я не использовал годами). Можно использовать подход, основанный на взаимодействии (насмешливый), или, как вы сказали, больше подход, основанный на состоянии, путем создания интеграционного теста, в котором одновременно выполняются все три класса. Я полагаю, что компромисс между двумя подходами не зависит от языка. Ruby имеет много насмешливых фреймворков , которые позволили бы вам использовать интерактивный подход, если это то, что вам наиболее удобно. (Я обычно использую тот, который поставляется с RSpec.)
Во-вторых, я не думаю, что «включение модулей поверх конструктора» является точным утверждением. Модули - это дополнительный инструмент, доступный вам в Ruby, но они ни в коем случае не заменяют хороший ОО-дизайн композицией объектов. Я все время передаю зависимости своим инициализаторам в Ruby, поскольку это облегчает их тестирование и позволяет использовать их повторно. Обычно я по умолчанию устанавливаю зависимость в списке аргументов, однако, вот так def initialize(converter=CodeConverter.new)
.
Теперь, чтобы ответить на ваш вопрос. То, что Лиамкленнан сказал об использовании Dir::[]
, правильно: finder
не требуется. Итак, вопрос в том, как вы пишете тесты для методов, которые вызывают Dir::[]
? У вас есть три варианта: 1) использовать одну из вышеупомянутых библиотек насмешек и заглушку Dir::[]
(это простой и легкий подход), 2) записать файлы на диск и убедиться, что они прочитаны (ick), или 3) использовать библиотека типа FakeFS для предотвращения дискового ввода-вывода, но все же позволяет писать естественный тест. В следующем примере один возможный способ написания / тестирования этого (с использованием RSpec и FakeFS), который несколько параллелен вашему первоначальному проекту:
class CodeExtractor
def self.extract_dir(example_dir, target_dir)
Dir[example_dir + "/*.md"].each do |filename|
self.extract(filename, target_dir)
end
end
def self.extract(*args)
self.new(*args).extract
end
def extract(filename, target_dir)
# ...
end
end
# The spec...
require 'fakefs/spec_helpers'
describe CodeExtractor do
include FakeFS::SpecHelpers
describe '::extract_dir' do
it "extracts each markdown file in the provided example dir" do
FileUtils.touch(["foo.md", "bar.md"])
CodeExtractor.should_receive(:extract).with(Dir.pwd + "/foo.md","/target")
CodeExtractor.should_receive(:extract).with(Dir.pwd + "/bar.md","/target")
CodeExtractor.extract_dir(Dir.pwd, "/target")
end
end
describe '#extract' do
it "blah blah blah" do
# ...
end
end
end
Конечно, возникает вопрос, добавляет ли такой тест достаточную ценность, чтобы заслужить его существование. Я не думаю, что буду вдаваться в это, хотя .... Если вы решите использовать FakeFS, имейте в виду, что трассировки стека от ошибок могут быть бесполезны, так как FS фальсифицируется, когда RSpec пытается получить номер строки несуществующая ФС. :) По совпадению, у меня есть некоторый код, который читает и анализирует слайды уценки на github. спецификации могут служить еще примерами того, как вы можете подходить к тестированию подобных вещей в Ruby. HTH, и удачи.