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:
		| @@ -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 | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| Feature: `ask' recipe keyword | ||||
|  | ||||
|   @exec | ||||
|   Scenario: prompts user with a list of choices on standard output | ||||
|     Given a recipe with: | ||||
|       """ | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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! | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user