Тестирование приложения командной строки с помощью cucumber/aruba/timecop: как вставить контекст
Следующий сценарий в значительной степени подводит итог моей проблемы:
Scenario: problems with subprocesses
Given the date is 01/01/2012 10:31
When I run `ruby -e "puts Time.now"`
Then the output should contain "10:31"
Сводится к When I run ruby -e "puts Time.now"
запуск дочернего процесса и, таким образом, делая все мои Timecop.freeze
заглушки неэффективны, так как они работают только на основной процесс. Мне нужно как-то "вставить" текущий контекст в команду, которая запускается, но мне кажется, что я ничего не могу придумать. Я пытаюсь что-то невозможное здесь?
Шаг:
require 'timecop'
Given /^the date is (\d+)\/(\d+)\/(\d+) (\d+):(\d+)$/ do |month, day, year, hour, minute|
Timecop.freeze(Time.local(year.to_i, month.to_i, day.to_i, hour.to_i , minute.to_i, 0))
end
2 ответа
Я вижу 2 варианта здесь.
Создайте ловушку в тестируемой системе, которую вы можете использовать для внедрения необходимого контекста, в этом примере вы можете добавить параметр "текущего времени" в тестируемое приложение командной строки. В качестве альтернативы укажите фиксированное время в конфигурационном файле приложения или базе данных, есть много вариантов. Это предполагает, что у вас есть приложение, которое вы тестируете, и можете вносить такие изменения. Это должно быть только очень небольшое изменение, например, если указан параметр "текущее время", тогда используйте Timecop, чтобы заморозить время в это время.
Найдите способ ввести тестируемую систему в процесс Cucumber. В вашем примере вместо того, чтобы обстреливать
ruby -e "puts Time.now"
, вы могли быinstance_eval "puts Time.now"
, Более реалистично, вы могли быrequire
приложение, и если бегунок командной строки - просто тонкая оболочка вокруг некоторых классов, которые фактически выполняют работу, то вы можете вызывать их напрямую. В качестве альтернативы, вы можете заполнить любые ожидаемые параметры ARGV.puts
метод, и простоrequire
файл, который должен дать вам опыт работы с ним вне процесса, но вы сможете эффективно использовать Timecop.
Аруба также поддерживает функцию, называемую процессом выполнения, которая позволяет вам запускать все в одном процессе. Тем не менее, он в значительной степени ограничивает вас тестированием Ruby CLI с Aruba, так как он работает путем переопределения поведения по умолчанию для оболочки при вызове метода Ruby.
Вот как это выглядит для меня - я использую Aruba для тестирования приложения Thor:
require 'aruba/cucumber'
require 'aruba/in_process'
require 'thor'
require 'thor/runner'
load 'Thorfile'
class ThorFriendlyMain
def initialize(argv, stdin, stdout, stderr, kernel)
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
end
def execute!
$stdin = @stdin
$stdout = @stdout
$stderr = @stderr
Thor::Runner.start(@argv)
$stdin = STDIN
$stdout = STDOUT
$stderr = STDERR
end
end
Aruba.config.command_launcher = :in_process
Aruba.config.main_class = ThorFriendlyMain