Improve test suite performance with aruba wrapper:

* Implement ArubaProgramWrapper in cucumber env;
* Tag a few features to not use the wrapper as aruba doesn't support yet
  interactive testing with in process mode, and reported program name
  will not be the correct one;
* Assign required standard streams to CLI and Env classes.
This commit is contained in:
Thibault Jouan 2014-05-28 15:13:30 +00:00
parent 55f18d30bf
commit 18b835b10e
5 changed files with 77 additions and 25 deletions

View File

@ -1,5 +1,6 @@
Feature: CLI usage Feature: CLI usage
@exec
Scenario: prints the usage when an argument is missing Scenario: prints the usage when an argument is missing
When I run `producer` When I run `producer`
Then the exit status must be 64 Then the exit status must be 64

View File

@ -1,5 +1,6 @@
Feature: `ask' recipe keyword Feature: `ask' recipe keyword
@exec
Scenario: prompts user with a list of choices on standard output Scenario: prompts user with a list of choices on standard output
Given a recipe with: Given a recipe with:
""" """

View File

@ -1,2 +1,34 @@
require 'aruba/cucumber' require 'aruba/cucumber'
require 'aruba/in_process'
require 'cucumber/sshd/cucumber' require 'cucumber/sshd/cucumber'
require 'producer/core'
class ArubaProgramWrapper
def initialize(argv, stdin = $stdin, stdout = $stdout, stderr = $stderr,
kernel = Kernel)
@argv = argv
@stdin = stdin
@stdout = stdout
@stderr = stderr
@kernel = kernel
end
def execute!
Producer::Core::CLI.run!(
@argv.dup, stdin: @stdin, stdout: @stdout, stderr: @stderr
)
rescue SystemExit => e
@kernel.exit(e.status)
end
end
Before('@exec') do
Aruba.process = Aruba::SpawnProcess
end
Before('~@exec') do
Aruba::InProcess.main_class = ArubaProgramWrapper
Aruba.process = Aruba::InProcess
end

View File

@ -9,27 +9,28 @@ module Producer
EX_SOFTWARE = 70 EX_SOFTWARE = 70
class << self class << self
def run!(arguments, output: $stderr) def run!(arguments, stdin: $stdin, stdout: $stdout, stderr: $stderr)
cli = new(arguments) cli = new(arguments, stdin: stdin, stdout: stdout, stderr: stderr)
begin begin
cli.parse_arguments! cli.parse_arguments!
cli.run cli.run
rescue ArgumentError rescue ArgumentError
output.puts USAGE stderr.puts USAGE
exit EX_USAGE exit EX_USAGE
rescue RuntimeError => e rescue RuntimeError => e
output.puts "#{e.class.name.split('::').last}: #{e.message}" stderr.puts "#{e.class.name.split('::').last}: #{e.message}"
exit EX_SOFTWARE exit EX_SOFTWARE
end end
end end
end end
attr_reader :arguments, :stdout, :env attr_reader :arguments, :stdin, :stdout, :stderr, :env
def initialize(args, stdout: $stdout) def initialize(args, stdin: $stdin, stdout: $stdout, stderr: $stderr)
@arguments = args @arguments = args
@stdin = stdin
@stdout = stdout @stdout = stdout
@env = Env.new(output: stdout) @env = Env.new(input: stdin, output: stdout)
end end
def parse_arguments! def parse_arguments!

View File

@ -8,19 +8,30 @@ module Producer::Core
let(:recipe_file) { fixture_path_for 'recipes/some_recipe.rb' } let(:recipe_file) { fixture_path_for 'recipes/some_recipe.rb' }
let(:options) { [] } let(:options) { [] }
let(:arguments) { [*options, recipe_file] } let(:arguments) { [*options, recipe_file] }
let(:stdin) { StringIO.new}
let(:stdout) { StringIO.new } let(:stdout) { StringIO.new }
let(:stderr) { StringIO.new }
subject(:cli) { CLI.new(arguments, stdout: stdout) } subject(:cli) { CLI.new(arguments, stdin: stdin, stdout: stdout) }
describe '.run!' do describe '.run!' do
let(:cli) { double('cli').as_null_object } let(:cli) { double('cli').as_null_object }
let(:output) { StringIO.new }
subject(:run) { described_class.run! arguments, output: output } subject(:run) do
described_class.run! arguments,
stdin: stdin,
stdout: stdout,
stderr: stderr
end
before { allow(described_class).to receive(:new) { cli } } before { allow(described_class).to receive(:new) { cli } }
it 'builds a new CLI with given arguments' do it 'builds a new CLI with given arguments and streams' do
expect(described_class).to receive(:new).with(arguments) expect(described_class).to receive(:new).with(arguments,
stdin: stdin,
stdout: stdout,
stderr: stderr
)
run run
end end
@ -46,9 +57,9 @@ module Producer::Core
end end
end end
it 'prints the usage' do it 'prints the usage on the error stream' do
trap_exit { run } trap_exit { run }
expect(output.string).to match /\AUsage: .+/ expect(stderr.string).to match /\AUsage: .+/
end end
end end
@ -64,26 +75,24 @@ module Producer::Core
end end
end end
it 'prints exception name and message' do it 'prints exception name and message and the error stream' do
trap_exit { run } trap_exit { run }
expect(output.string).to match /\ARuntimeError: some message/ expect(stderr.string).to match /\ARuntimeError: some message/
end end
end end
end end
describe '#initialize' do describe '#initialize' do
it 'assigns the env with CLI output' do
expect(cli.env.output).to be stdout
end
context 'without options' do
subject(:cli) { described_class.new(arguments) } subject(:cli) { described_class.new(arguments) }
it 'assigns $stdin as the default standard input' do
expect(cli.stdin).to be $stdin
end
it 'assigns $stdout as the default standard output' do it 'assigns $stdout as the default standard output' do
expect(cli.stdout).to be $stdout expect(cli.stdout).to be $stdout
end end
end end
end
describe '#arguments' do describe '#arguments' do
it 'returns the assigned arguments' do it 'returns the assigned arguments' do
@ -101,6 +110,14 @@ module Producer::Core
it 'returns the assigned env' do it 'returns the assigned env' do
expect(cli.env).to be_an Env expect(cli.env).to be_an Env
end end
it 'assigns CLI stdin as the env input' do
expect(cli.env.input).to be stdin
end
it 'assigns CLI stdout as the env output' do
expect(cli.env.output).to be stdout
end
end end
describe '#parse_arguments!' do describe '#parse_arguments!' do