diff --git a/.gitignore b/.gitignore index b7a885f..292e150 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ Gemfile.lock *.orig *.rej *.patch +tmp/aruba/ diff --git a/.travis.yml b/.travis.yml index 1d1f6aa..824d958 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,6 @@ rvm: - 1.9.2 - 1.9.3 - 2.0.0 +script: "rake spec features" notifications: email: false diff --git a/README.md b/README.md index 23933af..790d9b5 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,24 @@ Install Usage ----- +The formatter may be used by either passing the `-f|--format` flag to `rspec` or with the included `check_rspec` script. The later sets the appropriate exit status for a failing Nagios/Icinga plugin. + +### `check_rspec` + + Usage: check_rspec [options] [--] [passed to rspec] + + Specific options: + -t, --timeout TIMEOUT default: 30.0 (seconds) + -h, --help Show this message + +Any options to `check_rspec` not prefixed with `-` or `--` are passed directly +on to the `rspec` utility. If you need to pass an option flag you may +terminated `check_rspec`'s option parsing with a bare `--`. + + check_rspec -- -e 'foo' trivial_spec.rb + +### `rspec` + rspec -f RSpec::Nagios::Formatter See the documentation on [rspec --format](https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/command-line/format-option) @@ -55,3 +73,10 @@ Support ------- Please log tickets and issues at [github](https://github.com/jhoblitt/rspec-nagios-formatter) + +See Also +-------- + +* [cucumber-nagios](http://auxesis.github.io/cucumber-nagios/) +* [RSpec](https://github.com/rspec/rspec) +* [Icinga Plugins](http://docs.icinga.org/latest/en/plugins.html) diff --git a/Rakefile b/Rakefile index 9c7e45c..d85fad9 100644 --- a/Rakefile +++ b/Rakefile @@ -6,3 +6,10 @@ RSpec::Core::RakeTask.new(:spec) task :default => [ :spec, ] + +require 'cucumber' +require 'cucumber/rake/task' +Cucumber::Rake::Task.new(:features) do |t| + t.cucumber_opts = "features --format pretty -x" + t.fork = false +end diff --git a/bin/check_rspec b/bin/check_rspec new file mode 100755 index 0000000..df7371c --- /dev/null +++ b/bin/check_rspec @@ -0,0 +1,42 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'open3' +require 'timeout' + +EXIT_CRITICAL = 2 + +options = { :timeout => 30.0 } +option_parser = OptionParser.new do |opts| + opts.banner = "Usage: check_rspec [options] [--] [passed to rspec]" + opts.separator "" + opts.separator "Specific options:" + + opts.on("-t", "--timeout TIMEOUT", "default: 30.0 (seconds)", Float) do |t| + options[:timeout] = t + end + + opts.on_tail("-h", "--help", "Show this message") do + puts opts + exit + end +end + +option_parser.parse! + +cmd = ['rspec', '--format', 'RSpec::Nagios::Formatter', ARGV] +cmd_stdout, cmd_stderr, cmd_status = nil + +begin + Timeout::timeout(options[:timeout]) { + cmd_stdout, cmd_stderr, cmd_status = Open3.capture3(cmd.join(' ')) + } +rescue Timeout::Error + puts "RSPEC Critical - timeout after #{options[:timeout]} seconds" + exit EXIT_CRITICAL +end + +puts cmd_stdout +unless cmd_status.exitstatus == 0 + exit EXIT_CRITICAL +end diff --git a/features/check_rspec/options.feature b/features/check_rspec/options.feature new file mode 100644 index 0000000..1e2780a --- /dev/null +++ b/features/check_rspec/options.feature @@ -0,0 +1,96 @@ +Feature: command line options + In order to modifiy the behavior of check_rspec + As an Icinga administrator + I want to be able to set command line options + +Scenario: run a passing rspec test + Given a file named "trivial_spec.rb" with: + """ + describe do + it { true.should == true } + end + """ + When I successfully run `check_rspec trivial_spec.rb` + Then the stdout should contain: + """ + RSPEC OK + """ + +Scenario: run a failing rspec test + Given a file named "trivial_spec.rb" with: + """ + describe do + it { true.should == false } + end + """ + When I run `check_rspec trivial_spec.rb` + Then the exit status should be 2 + And the stdout should contain: + """ + RSPEC Critical + """ + +Scenario: run a test with --timeout + Given a file named "trivial_spec.rb" with: + """ + describe do + it { true.should == true } + end + """ + When I successfully run `check_rspec --timeout 1 trivial_spec.rb` + Then the stdout should contain: + """ + RSPEC OK + """ + +Scenario: run a test with --timeout that times out + Given a file named "trivial_spec.rb" with: + """ + describe do + it { sleep(1) } + end + """ + When I run `check_rspec --timeout 0.5 trivial_spec.rb` + Then the exit status should be 2 + And the stdout should contain: + """ + RSPEC Critical - timeout after 0.5 seconds + """ + +Scenario: view usage with -h + When I successfully run `check_rspec -h` + And the stdout should contain: + """ + Usage: check_rspec [options] [--] [passed to rspec] + + Specific options: + -t, --timeout TIMEOUT default: 30.0 (seconds) + -h, --help Show this message + """ + +Scenario: view usage with --help + When I successfully run `check_rspec --help` + And the stdout should contain: + """ + Usage: check_rspec [options] [--] [passed to rspec] + + Specific options: + -t, --timeout TIMEOUT default: 30.0 (seconds) + -h, --help Show this message + """ + +Scenario: pass options to rspec + Given a file named "trivial_spec.rb" with: + """ + describe 'foo' do + it { true.should == true } + end + describe 'bar' do + it { true.should == true } + end + """ + When I successfully run `check_rspec -- -e 'foo' trivial_spec.rb` + Then the stdout should contain: + """ + RSPEC OK - 1 example + """ diff --git a/features/check_rspec/run.feature b/features/check_rspec/run.feature new file mode 100644 index 0000000..12a13e2 --- /dev/null +++ b/features/check_rspec/run.feature @@ -0,0 +1,31 @@ +Feature: run rspec tests + In order to monitor the enviroment + As an Icinga administrator + I want to get RSpec test results in Icinga plugin format + +Scenario: run a passing rspec test + Given a file named "trivial_spec.rb" with: + """ + describe do + it { true.should == true } + end + """ + When I successfully run `check_rspec trivial_spec.rb` + Then it should pass with regexp: + """ + ^RSPEC OK - 1 example, 0 failures, finished in 0.\d+ seconds | examples=1 passing=1 failures=0 pending=0 conformance=100% time=0.\d+s$ + """ + +Scenario: run a failing rspec test + Given a file named "trivial_spec.rb" with: + """ + describe do + it { true.should == false } + end + """ + When I run `check_rspec trivial_spec.rb` + Then the exit status should be 2 + And it should fail with regexp: + """ + ^RSPEC Critical - 1 example, 1 failures, finished in 0.\d+ seconds | examples=1 passing=0 failures=1 pending=0 conformance=0% time=0.\d+s$ + """ diff --git a/features/support/env.rb b/features/support/env.rb new file mode 100644 index 0000000..fb0a661 --- /dev/null +++ b/features/support/env.rb @@ -0,0 +1 @@ +require 'aruba/cucumber' diff --git a/lib/rspec/nagios/formatter.rb b/lib/rspec/nagios/formatter.rb index 65148bc..2d6fc9d 100644 --- a/lib/rspec/nagios/formatter.rb +++ b/lib/rspec/nagios/formatter.rb @@ -14,17 +14,16 @@ def dump_summary(duration, example_count, failure_count, pending_count) def summary_line(duration, example_count, failure_count, pending_count) passing_count = example_count - failure_count # conformance is expressed as a percentage - # if example_count is zero we need to aviod div by 0 + # if example_count is zero we need to avoid div by 0 if example_count > 0 conformance = passing_count / example_count.to_f conformance *= 100 - #conformance = "%.2f" % conformance conformance = conformance.round(0) else conformance = 0 end # limit duration precision to microseconds - time = duration.round(6) + time = duration.round(6) summary = 'RSPEC' if failure_count == 0 diff --git a/rspec-nagios-formatter.gemspec b/rspec-nagios-formatter.gemspec index 389a4df..02d5400 100644 --- a/rspec-nagios-formatter.gemspec +++ b/rspec-nagios-formatter.gemspec @@ -18,10 +18,11 @@ Gem::Specification.new do |s| s.add_development_dependency("rspec-expectations", ">= 2.0.0") s.add_development_dependency("rspec-mocks", ">= 2.0.0") s.add_development_dependency("rake", ">= 10.0.0") + s.add_development_dependency('aruba', '~> 0.4.6') s.rubygems_version = ">= 1.6.1" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {spec,features}/*`.split("\n") -# s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_path = "lib" end