RSpec-Command
rspec-command is a helper module for using RSpec to test command-line
applications.
Quick Start
Add gem 'rspec-command' to your Gemfile and then configure it in your
spec_helper.rb:
require 'rspec_command'
RSpec.configure do |config|
config.include RSpecCommand
endYou can then use the helpers in your specs:
require 'spec_helper'
describe 'myapp' do
command 'myapp --version'
its(:stdout) { is_expected.to include('1.0.0') }
endcommand
The core helper is command. It takes a command to run and sets it as the
subject for the example group. The command can be given as a string, array, or
block. If the command is given as an array, no shell processing is done before
running it. If the gem you are running inside has a Gemfile, all commands will
be run inside a bundle exec. Each command is run in a new temporary directory
so the results of one test won't affect others.
command also optionally takes a hash of options to pass through to
Mixlib::ShellOut.new. Some common options include :input to provide data on
stdin and :timeout to change the execution timeout. The option allow_error
is not passed through to the underlying ShellOut, but should be set to true
to avoid raising an exception if the command fails.
The subject will be set to a Mixlib::ShellOut object so you can use
rspec-its to check individual attributes:
describe 'myapp' do
command 'myapp --version'
its(:stdout) { is_expected.to include '1.0.0' }
its(:stderr) { is_expected.to eq '' }
its(:exitstatus) { is_expected.to eq 0 }
endfile
The file method writes a file in to the temporary directory. You can provide
the file content as either a string or a block:
describe 'myapp' do
command 'myapp read data1.txt data2.txt'
file 'data1.txt', <<-EOH
a thing
EOH
file 'data2.txt' do
"another thing #{Time.now}"
end
its(:stdout) { is_expected.to include '2 files imported' }
endfixture_file
The fixture_file method copies a file or folder from a fixture to the
temporary directory:
describe 'myapp' do
command 'myapp read entries/'
fixture_file 'entries'
its(:stdout) { is_expected.to include '4 files imported' }
endThese fixtures are generally kept in spec/fixtures but it can be customized
by redefining let(:fixture_root).
environment
The environment method sets environment variables for subprocesses run by
command:
describe 'myapp' do
command 'myapp show'
environment MYAPP_DEBUG: true
its(:stderr) { is_expected.to include '[debug]' }
endmatch_fixture
The match_fixture matcher lets you check the files created by a command
against a fixture:
describe 'myapp' do
command 'myapp write'
it { is_expected.to match_fixture 'write_data' }
endcapture_output
The capture_output helper lets you redirect the stdout and stderr of a block
of code to strings. This includes any subprocesses or non-Ruby output. This can
help with integration testing of CLI code without the overhead of running a full
subprocess.
The returned object behaves like a string containing the stdout output, but has
stdout, stderr, and exitstatus attributes to simulate the object used by
command. exitstatus will always be 0.
describe 'myapp' do
subject do
capture_output do
MyApp::CLI.run('show')
end
end
its(:stdout) { is_expected.to include 'Entry:' }
endRSpecCommand::Rake
The RSpecCommand::Rake helper is an optional module you can include in your
example groups to test Rake tasks without the overhead of running Rake in a full
subprocess.
require 'rspec_command'
RSpec.configure do |config|
config.include RSpecCommand::Rake
end
describe 'rake myapp' do
rake_task 'myapp'
rakefile <<-EOH
require 'myapp'
task 'myapp' do
MyApp.rake_task
end
EOH
its(:stdout) { is_expected.to include 'Initialized new project' }
endLicense
Copyright 2015, Noah Kantrowitz
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.