Тестирование приложения командной строки с помощью 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 варианта здесь.

  1. Создайте ловушку в тестируемой системе, которую вы можете использовать для внедрения необходимого контекста, в этом примере вы можете добавить параметр "текущего времени" в тестируемое приложение командной строки. В качестве альтернативы укажите фиксированное время в конфигурационном файле приложения или базе данных, есть много вариантов. Это предполагает, что у вас есть приложение, которое вы тестируете, и можете вносить такие изменения. Это должно быть только очень небольшое изменение, например, если указан параметр "текущее время", тогда используйте Timecop, чтобы заморозить время в это время.

  2. Найдите способ ввести тестируемую систему в процесс 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
Другие вопросы по тегам