From 18b835b10e7aa44b55da550ad27fb8cb1d29078f Mon Sep 17 00:00:00 2001 From: Thibault Jouan Date: Wed, 28 May 2014 15:13:30 +0000 Subject: [PATCH] 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. --- features/cli_usage.feature | 1 + features/recipe_ask.feature | 1 + features/support/env.rb | 32 ++++++++++++++++++++ lib/producer/core/cli.rb | 15 +++++----- spec/producer/core/cli_spec.rb | 53 ++++++++++++++++++++++------------ 5 files changed, 77 insertions(+), 25 deletions(-) diff --git a/features/cli_usage.feature b/features/cli_usage.feature index 2ad288b..cd5758a 100644 --- a/features/cli_usage.feature +++ b/features/cli_usage.feature @@ -1,5 +1,6 @@ Feature: CLI usage + @exec Scenario: prints the usage when an argument is missing When I run `producer` Then the exit status must be 64 diff --git a/features/recipe_ask.feature b/features/recipe_ask.feature index 9871162..ae091d7 100644 --- a/features/recipe_ask.feature +++ b/features/recipe_ask.feature @@ -1,5 +1,6 @@ Feature: `ask' recipe keyword + @exec Scenario: prompts user with a list of choices on standard output Given a recipe with: """ diff --git a/features/support/env.rb b/features/support/env.rb index 668fcef..af6b07d 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,2 +1,34 @@ require 'aruba/cucumber' +require 'aruba/in_process' 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 diff --git a/lib/producer/core/cli.rb b/lib/producer/core/cli.rb index 22f4127..d7d6eb3 100644 --- a/lib/producer/core/cli.rb +++ b/lib/producer/core/cli.rb @@ -9,27 +9,28 @@ module Producer EX_SOFTWARE = 70 class << self - def run!(arguments, output: $stderr) - cli = new(arguments) + def run!(arguments, stdin: $stdin, stdout: $stdout, stderr: $stderr) + cli = new(arguments, stdin: stdin, stdout: stdout, stderr: stderr) begin cli.parse_arguments! cli.run rescue ArgumentError - output.puts USAGE + stderr.puts USAGE exit EX_USAGE rescue RuntimeError => e - output.puts "#{e.class.name.split('::').last}: #{e.message}" + stderr.puts "#{e.class.name.split('::').last}: #{e.message}" exit EX_SOFTWARE 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 + @stdin = stdin @stdout = stdout - @env = Env.new(output: stdout) + @env = Env.new(input: stdin, output: stdout) end def parse_arguments! diff --git a/spec/producer/core/cli_spec.rb b/spec/producer/core/cli_spec.rb index fe4f34b..3c160ce 100644 --- a/spec/producer/core/cli_spec.rb +++ b/spec/producer/core/cli_spec.rb @@ -8,19 +8,30 @@ module Producer::Core let(:recipe_file) { fixture_path_for 'recipes/some_recipe.rb' } let(:options) { [] } let(:arguments) { [*options, recipe_file] } + let(:stdin) { 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 - let(:cli) { double('cli').as_null_object } - let(:output) { StringIO.new } - subject(:run) { described_class.run! arguments, output: output } + let(:cli) { double('cli').as_null_object } + + subject(:run) do + described_class.run! arguments, + stdin: stdin, + stdout: stdout, + stderr: stderr + end before { allow(described_class).to receive(:new) { cli } } - it 'builds a new CLI with given arguments' do - expect(described_class).to receive(:new).with(arguments) + it 'builds a new CLI with given arguments and streams' do + expect(described_class).to receive(:new).with(arguments, + stdin: stdin, + stdout: stdout, + stderr: stderr + ) run end @@ -46,9 +57,9 @@ module Producer::Core end end - it 'prints the usage' do + it 'prints the usage on the error stream' do trap_exit { run } - expect(output.string).to match /\AUsage: .+/ + expect(stderr.string).to match /\AUsage: .+/ end end @@ -64,24 +75,22 @@ module Producer::Core end end - it 'prints exception name and message' do + it 'prints exception name and message and the error stream' do trap_exit { run } - expect(output.string).to match /\ARuntimeError: some message/ + expect(stderr.string).to match /\ARuntimeError: some message/ end end end describe '#initialize' do - it 'assigns the env with CLI output' do - expect(cli.env.output).to be stdout + subject(:cli) { described_class.new(arguments) } + + it 'assigns $stdin as the default standard input' do + expect(cli.stdin).to be $stdin end - context 'without options' do - subject(:cli) { described_class.new(arguments) } - - it 'assigns $stdout as the default standard output' do - expect(cli.stdout).to be $stdout - end + it 'assigns $stdout as the default standard output' do + expect(cli.stdout).to be $stdout end end @@ -101,6 +110,14 @@ module Producer::Core it 'returns the assigned env' do expect(cli.env).to be_an Env 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 describe '#parse_arguments!' do