Friendly command-line test runner and matchers for shell scripting in ruby using RSpec.
Installation
With Bundler, add the following to your Gemfile:
group :test do
gem "blue-shell"
end
Then require and configure BlueShell in your spec_helper.rb
:
require 'blue-shell'
RSpec.configure do |c|
c.include BlueShell::Matchers
end
Usage
Running commands
Shell commands in BlueShell get executed by creating a new runner instance BlueShell::Runner.run
.
Running a command by default times out after 30 seconds or raises a Timeout::Error
.
BlueShell::Runner.run 'sleep 1' # success
BlueShell::Runner.run 'sleep 6' # fails with Timeout::Error
Expectations on exit codes
BlueShell::Runner.run 'false' do |runner|
runner.should exit_with 1
runner.should have_exit_code 1 # #exit_with and #have_exit_code are aliases
end
Expectations on STDOUT
BlueShell::Runner.run 'echo "foo bar baz"' do |runner|
runner.should say 'foo'
runner.should have_output 'bar' # #say and #have_output are aliases
end
By default #say
and #have_output
will smartly wait a maximum of 30 seconds.
If you need to increase that timeout, you can do so:
BlueShell::Runner.run 'sleep 35 && echo "foo bar baz"' do |runner|
runner.with_timeout(40) do
runner.should have_output 'bar'
end
end
Interacting with STDIN
BlueShell::Runner.run 'read' do |runner|
runner.send_keys 'foo'
end
BlueShell::Runner.run 'read' do |runner|
runner.send_return
end
About timeouts...
Within the run block you can call #wait_for_exit
within #with_timeout
if you want to make sure your command finishes within a certain amount
of time. (The default timeout is 30 seconds.)
BlueShell::Runner.run 'sleep 6' do |runner|
runner.with_timeout(7) do
runner.wait_for_exit
end
end
It is important to note the difference between calling .run
'one-off' vs passing in a block:
# raises a Timeout::Error after 30 seconds
BlueShell::Runner.run 'sleep 60'
# raises a Timeout::Error after 5 seconds
BlueShell.with_timeout(5) do
BlueShell::Runner.run 'sleep 60'
end
# succeeds
BlueShell::Runner.run 'sleep 60' do |_|
# unless #wait_for_exit or #have_exit_code are invoked
# your specs do not wait for the command to exit
# and also do not fail if it never does
end
That being said, in most cases you probably want to invoke #wait_for_exit
or #have_exit_code
at the end of your block to ensure the command finishes.
Credits
BlueShell is maintained and funded by Pivotal Labs. Thank you to all the contributors.
Copyright
Copyright © Pivotal Labs. See LICENSE for details.