diff --git a/.gitignore b/.gitignore index 2f9506f..82621c8 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,9 @@ man/* ## BUNDLER .bundle + +## RVM +.rvmrc + +## Aruba +tmp/* diff --git a/.rvmrc b/.rvmrc new file mode 100755 index 0000000..d06c9dc --- /dev/null +++ b/.rvmrc @@ -0,0 +1,2 @@ +rvm use ruby-1.8.7 +rvm gemset use cucumber-nagios diff --git a/Gemfile b/Gemfile index c80ee36..1cac477 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,7 @@ source "http://rubygems.org" +git "git://github.com/hedgehog/ssh-forever.git", :branch => 'master' do + gem 'ssh-forever', ">= 0.4.0" +end + gemspec diff --git a/Gemfile.lock b/Gemfile.lock index 4ffcad0..1e640d9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,13 +1,24 @@ +GIT + remote: git://github.com/hedgehog/ssh-forever.git + revision: 6ea5a2c5fea4829a1952eab3eb1d58cf16269f2b + branch: master + specs: + ssh-forever (0.4.0) + open4 (>= 1.0.1) + PATH remote: . specs: cucumber-nagios (0.9.0) amqp (= 0.6.7) - bundler (~> 1.0.7) + aruba (>= 0.3.3) + bundler (~> 1.0.10) cucumber (>= 0.10.0) + cuken (>= 0.1.0) mechanize (= 1.0.0) net-ssh (~> 2.1.0) - rspec (>= 2.3.0) + rspec (>= 2.5.0) + ssh-forever (>= 0.4.0) templater (>= 1.0.0) webrat (= 0.7.2) @@ -16,17 +27,28 @@ GEM specs: amqp (0.6.7) eventmachine (>= 0.12.4) + aruba (0.3.3) + childprocess (~> 0.1.7) + cucumber (~> 0.10) + rspec (~> 2.5) builder (3.0.0) + childprocess (0.1.7) + ffi (~> 0.6.3) cucumber (0.10.0) builder (>= 2.1.2) diff-lcs (~> 1.1.2) gherkin (~> 2.3.2) json (~> 1.4.6) term-ansicolor (~> 1.0.5) + cuken (0.1.1) + aruba (~> 0.3.3) + ssh-forever diff-lcs (1.1.2) eventmachine (0.12.10) extlib (0.9.15) - gherkin (2.3.3) + ffi (0.6.3) + rake (>= 0.8.7) + gherkin (2.3.4) json (~> 1.4.6) highline (1.6.1) json (1.4.6) @@ -34,7 +56,8 @@ GEM nokogiri (>= 1.2.1) net-ssh (2.1.3) nokogiri (1.4.4) - rack (1.2.1) + open4 (1.0.1) + rack (1.2.2) rack-test (0.5.7) rack (>= 1.0) rake (0.8.7) @@ -60,13 +83,6 @@ PLATFORMS ruby DEPENDENCIES - amqp (= 0.6.7) - bundler (~> 1.0.7) - cucumber (>= 0.10.0) cucumber-nagios! - mechanize (= 1.0.0) - net-ssh (~> 2.1.0) rake (>= 0.8.3) - rspec (>= 2.3.0) - templater (>= 1.0.0) - webrat (= 0.7.2) + ssh-forever (>= 0.4.0)! diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..59c01c3 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,50 @@ +.gitignore +.rvmrc +AUTHORS +Gemfile +Gemfile.lock +HACKING +LICENSE +MANIFEST +README.md +Rakefile +TODO +bin/cucumber-nagios +bin/cucumber-nagios-gen +cucumber-nagios.gemspec +features/commands.feature +features/creating.feature +features/files.feature +features/http_steps.feature +features/installing.feature +features/steps/creating_steps.rb +features/steps/installing_steps.rb +features/steps/using_steps.rb +features/support/env.rb +features/support/silent_system.rb +features/support/webrat_logging_patches.rb +features/using.feature +lib/cucumber-nagios.rb +lib/cucumber/formatter/nagios.rb +lib/cucumber/nagios.rb +lib/cucumber/nagios/command.rb +lib/cucumber/nagios/steps.rb +lib/cucumber/nagios/steps/amqp_steps.rb +lib/cucumber/nagios/steps/benchmark_steps.rb +lib/cucumber/nagios/steps/command_steps.rb +lib/cucumber/nagios/steps/dns_steps.rb +lib/cucumber/nagios/steps/file_steps.rb +lib/cucumber/nagios/steps/http_header_steps.rb +lib/cucumber/nagios/steps/http_steps.rb +lib/cucumber/nagios/steps/ping_steps.rb +lib/cucumber/nagios/steps/ssh_steps.rb +lib/cucumber/nagios/support/env.rb +lib/cucumber/nagios/support/webrat_logging_patches.rb +lib/cucumber/nagios/version.rb +lib/generators/feature/%feature_name%.feature +lib/generators/feature/%feature_name%_steps.rb +lib/generators/project/.bzrignore +lib/generators/project/.gitignore +lib/generators/project/Gemfile +lib/generators/project/README +man/cucumber-nagios.1.ronn diff --git a/README.md b/README.md index 673b3f6..d20ad96 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,34 @@ This will spit out a bunch of files in the directory specified as `= 0.10.0" - s.add_runtime_dependency "rspec", ">= 2.3.0" + s.add_runtime_dependency "rspec", ">= 2.5.0" + s.add_runtime_dependency "aruba", ">= 0.3.3" + s.add_runtime_dependency "cuken", ">= 0.1.0" + s.add_runtime_dependency "ssh-forever", ">= 0.4.0" s.add_runtime_dependency "webrat", "= 0.7.2" s.add_runtime_dependency "mechanize", "= 1.0.0" s.add_runtime_dependency "templater", ">= 1.0.0" s.add_runtime_dependency "net-ssh", "~> 2.1.0" s.add_runtime_dependency "amqp", "= 0.6.7" - s.add_runtime_dependency "bundler", "~> 1.0.7" + s.add_runtime_dependency "bundler", "~> 1.0.10" s.add_development_dependency "rake", ">= 0.8.3" end diff --git a/features/commands.feature b/features/commands.feature index d5b48a8..153b113 100644 --- a/features/commands.feature +++ b/features/commands.feature @@ -1,30 +1,37 @@ +# For complete reusable step listings see: +# lib/aruba/cucumber.rb +# https://github.com/aslakhellesoy/aruba/blob/master/lib/aruba/cucumber.rb +# AND +# lib/cuken/*.rb +# https://github.com/hedgehog/cuken + Feature: Executing commands - In order to test a running system + In order to test a running local system As an administrator - I want to run arbitrary commands and test the output + I want to use Aruba steps to run commands and test output - @steps Scenario: Check Stdout - When I run 'echo "i like cheese"' - Then 'stdout' should have 'i like cheese' + When I run "echo 'i like cheese'" + Then the stdout from "echo 'i like cheese'" should contain "i like cheese" - @steps Scenario: Check Stderr - When I run 'echo "i like cheese" 1>&2' - Then 'stderr' should have 'i like cheese' + When I run "some_error" + Then the stderr from "some_error" should contain "No such file or directory - some_error" - @steps Scenario: Check Stdout for multiple lines - When I run 'shopt -s xpg_echo ; echo "one\n\one\none\n"' - Then 'one' should appear on 'stdout' '3' times + When I run "echo 'one\none\none\n'" + Then the output should contain: + """ + one + one + one + """ - @steps Scenario: Check exit code - When I run 'true' - Then it should exit '0' + When I run "true" + Then the exit status should be 0 - @steps Scenario: Check exit code - When I run 'false' - Then it should exit '1' + When I run "false" + Then the exit status should be 1 diff --git a/features/creating.feature b/features/creating.feature index 21fe7d5..fb92861 100644 --- a/features/creating.feature +++ b/features/creating.feature @@ -1,18 +1,40 @@ +# For complete reusable step listings see: +# lib/aruba/cucumber.rb +# https://github.com/aslakhellesoy/aruba/blob/master/lib/aruba/cucumber.rb +# AND +# lib/cuken/*.rb +# https://github.com/hedgehog/cuken + Feature: Creating new project To test websites A cucumber-nagios project Must be created + Background: + Given cucumber-nagios is installed + @create Scenario: Create a project - Given cucumber-nagios is installed - When I create a new project called "great-website-tests" - And I freeze in dependencies - Then a Gemfile lock should be created + Given I successfully run "cucumber-nagios-gen project great-website-tests" + When I cd to "great-website-tests" + Then these directories exist: + | features/steps | + | features/support | + And these files exist: + | features/support/env.rb | + | features/steps/amqp_steps.rb | + | features/steps/benchmark_steps.rb | + | features/steps/command_steps.rb | + | features/steps/dns_steps.rb | + | features/steps/file_steps.rb | + | features/steps/http_header_steps.rb | + | features/steps/http_steps.rb | + | features/steps/ping_steps.rb | + | features/steps/ssh_steps.rb | @create Scenario: Pretend to create a project - Given cucumber-nagios is installed - When I pretend to create a new project called "greatest-website-tests" - Then I do not freeze in dependencies - And a Gemfile lock should not be created + Given I successfully run "cucumber-nagios-gen project --pretend greatest-website-tests" + Then these directories do not exist: + | greatest-website-tests/features/steps | + | greatest-website-tests/features/support | diff --git a/features/files.feature b/features/files.feature index 8567f2a..36bc824 100644 --- a/features/files.feature +++ b/features/files.feature @@ -1,3 +1,10 @@ +# For complete reusable step listings see: +# lib/aruba/cucumber.rb +# https://github.com/aslakhellesoy/aruba/blob/master/lib/aruba/cucumber.rb +# AND +# lib/cuken/*.rb +# https://github.com/hedgehog/cuken + Feature: Examining files In order to test a running system As an administrator @@ -5,60 +12,73 @@ Feature: Examining files @steps Scenario: File exists - Given we have an empty file named '/tmp/foo.file' - Then a file named '/tmp/foo.file' should exist + Given the empty file "foo.file" + Then the file "foo.file" exists @steps Scenario: File does not exist - Then a file named '/tmp/foo.filepants' should not exist + Then the file "foo.filepants" does not exist @steps Scenario: Atime - Given we have an empty file named '/tmp/foo.file' - And we have the atime/mtime of '/tmp/foo.file' - And I run 'sleep 1' - And I run 'touch -a /tmp/foo.file' - Then the atime of '/tmp/foo.file' should be different + Given the empty file "foo.file" + And we record the a/mtime of "foo.file" + And I run "sleep 1" + And I run "touch -a foo.file" + Then the atime of "foo.file" changes @steps Scenario: Mtime - Given we have an empty file named '/tmp/foo.file' - And we have the atime/mtime of '/tmp/foo.file' - And I run 'sleep 1' - And I run 'touch -m /tmp/foo.file' - Then the mtime of '/tmp/foo.file' should be different + Given an empty file named "foo.file" + And we record the a/mtime of "foo.file" + And I run "sleep 1" + And I run "touch -m foo.file" + Then the mtime of "foo.file" changes @steps Scenario: File contents - When I run 'shopt -s xpg_echo ; echo "monkeypants\nmonkeyshorts" > /tmp/monkeytest.file' - Then a file named '/tmp/monkeytest.file' should contain 'monkeypants' + When I write to "monkeytest.file" with: + """ + monkeypants + monkeyshorts + """ + Then the file "monkeytest.file" contains "monkeypants" @steps Scenario: File contents multiple times - When I run 'shopt -s xpg_echo ; echo "monkeypants\nmonkeyshorts" > /tmp/monkeytest.file' - Then a file named '/tmp/monkeytest.file' should contain 'monkey.+' only '2' times + When I write to "monkeytest.file" with: + """ + monkeypants + monkeyshorts + + """ + Then the file "monkeytest.file" contains exactly: + """ + monkeypants + monkeyshorts + """ @steps Scenario: File modes - When I run 'touch /tmp/filemode.file' - And I run 'chmod 644 /tmp/filemode.file' - Then the file named '/tmp/filemode.file' should have mode '644' - And the file named '/tmp/filemode.file' should have mode '0644' + When I run "touch filemode.file" + And I run "chmod 644 filemode.file" + Then the file "filemode.file" has mode "644" + And the file "filemode.file" has mode "0644" @steps Scenario: Directory exists - When I run 'mkdir -p /tmp/dirtest' - Then a directory named '/tmp/dirtest' should exist + When I run "mkdir -p dirtest" + Then the directory "dirtest" exists @steps Scenario: Directory does not exist - Then a directory named '/tmp/dirtest-m000' should not exist + Then the directory "dirtest-m000" does not exist @steps Scenario: Directory mode - When I run 'mkdir -p /tmp/dirtest' - And I run 'chmod 755 /tmp/dirtest' - Then the directory named '/tmp/dirtest' should have mode '755' - And the directory named '/tmp/dirtest' should have mode '0755' + When I run "mkdir -p dirtest" + And I run "chmod 755 dirtest" + Then the directory "dirtest" has mode "755" + And the directory "dirtest" has mode "0755" diff --git a/features/installing.feature b/features/installing.feature index e829f80..3be3700 100644 --- a/features/installing.feature +++ b/features/installing.feature @@ -1,13 +1,22 @@ +# For complete reusable step listings see: +# lib/aruba/cucumber.rb +# https://github.com/aslakhellesoy/aruba/blob/master/lib/aruba/cucumber.rb +# AND +# lib/cuken/*.rb +# https://github.com/hedgehog/cuken + Feature: Installation To set up a cucumber-nagios project A user Must be able to install the gem + Background: + Given I build the gem + @install Scenario: Installing the gem - When I build the gem - And I install the latest gem - Then I should have "cucumber-nagios-gen" on my path - And I should have "cucumber-nagios" on my path - And I can generate a new project + Given I install the latest gem + When I successfully run "which cucumber-nagios-gen" + When I successfully run "which cucumber-nagios" + Then I successfully run "cucumber-nagios-gen project testproj" diff --git a/features/ssh.feature b/features/ssh.feature new file mode 100644 index 0000000..60931f2 --- /dev/null +++ b/features/ssh.feature @@ -0,0 +1,28 @@ +# For complete reusable step listings see: +# lib/aruba/cucumber.rb +# https://github.com/aslakhellesoy/aruba/blob/master/lib/aruba/cucumber.rb +# AND +# lib/cuken/*.rb +# https://github.com/hedgehog/cuken + +Feature: SSH steps + In order to specify remote command execution + As a developer using Cucumber + I want to use Aruba and custom steps to describe SSH sessions + + Background: + Given default ssh-forever options + And I initialize password-less SSH access + + Scenario: Aruba steps for remote commands via password-less SSH access + Given I successfully run "ssh cuken 'echo Supercalifragilisticexpialidocious;'" + Then the output should contain "Supercalifragilisticexpialidocious" + + Scenario: Batch initialize password-less SSH access + When I initialize password-less SSH access for: + | user | hostname | name | port | + | `whoami` | `hostname` | `echo cuken` | `echo 22` | + | :default | localhost | `echo cuken` | 22 | + | :default | :default | :default | :default | + And I successfully run "ssh cuken 'echo Supercalifragilisticexpialidocious;'" + Then the output should contain "Supercalifragilisticexpialidocious" diff --git a/features/steps/creating_steps.rb b/features/steps/creating_steps.rb index ed3f484..e3dd808 100644 --- a/features/steps/creating_steps.rb +++ b/features/steps/creating_steps.rb @@ -1,51 +1,6 @@ Given /^cucumber\-nagios is installed$/ do - When 'I build the gem' - And 'I install the latest gem' - Then 'I should have "cucumber-nagios-gen" on my path' - And 'I should have "cucumber-nagios" on my path' + Given %Q{I build the gem} + When %Q{I install the latest gem} + Then %Q{I successfully run "which cucumber-nagios-gen"} + And %Q{I successfully run "which cucumber-nagios"} end - -When /^I create a new project called "([^\"]*)"$/ do |project_name| - @project_name = project_name - FileUtils.rm_rf("/tmp/#{@project_name}") - - Dir.chdir("/tmp") do - silent_system("cucumber-nagios-gen project #{@project_name}").should be_true - end -end - -When /^I pretend to create a new project called "([^\"]*)"$/ do |project_name| - @project_name = project_name - FileUtils.rm_rf("/tmp/#{@project_name}") if File.directory?("/tmp/#{@project_name}") - - Dir.chdir("/tmp") do - silent_system("cucumber-nagios-gen project --pretend #{@project_name}").should be_true - end -end - -When /^I freeze in dependencies$/ do - @project_name.should_not be_nil - Dir.chdir("/tmp/#{@project_name}") do - silent_system("bundle install --local").should be_true - end -end - -Then /^I do not freeze in dependencies$/ do - @project_name.should_not be_nil - lambda do - Dir.chdir("/tmp/#{@project_name}") do - $stderr.puts "This should not run" - end - end.should raise_error(Errno::ENOENT) -end - -Then /^a Gemfile lock should be created$/ do - @project_name.should_not be_nil - File.exists?("/tmp/#{@project_name}/Gemfile.lock").should be_true -end - -Then /^a Gemfile lock should not be created$/ do - @project_name.should_not be_nil - File.exists?("/tmp/#{@project_name}/Gemfile.lock").should be_false -end - diff --git a/features/steps/installing_steps.rb b/features/steps/installing_steps.rb index dc1c5a0..0fbbda1 100644 --- a/features/steps/installing_steps.rb +++ b/features/steps/installing_steps.rb @@ -1,9 +1,8 @@ When /^I build the gem$/ do project_root = Pathname.new(File.dirname(__FILE__)).parent.parent.expand_path rakefile = project_root.join('Rakefile') - File.exist?(rakefile).should be_true - - silent_system("rake -f #{rakefile} build").should be_true + check_file_presence([rakefile], true) + silent_system(unescape("rake -f #{rakefile} build")) end When /^I install the latest gem$/ do @@ -12,20 +11,6 @@ glob = File.join(pkg_dir, '*.gem') latest = Dir.glob(glob).sort {|a, b| File.ctime(a) <=> File.ctime(b) }.last - silent_system("gem install --local #{latest}").should be_true -end - -Then /^I should have "([^"]*)" on my path$/ do |file| - silent_system("which #{file}").should be_true -end - -Then /^I can generate a new project$/ do - testproj = "testproj-#{Time.now.to_i}" - FileUtils.rm_rf("/tmp/#{testproj}") - - Dir.chdir("/tmp") do - silent_system("cucumber-nagios-gen project #{testproj}").should be_true - end - File.exists?("/tmp/#{testproj}").should be_true + run_simple(unescape("gem install --local --force --ignore-dependencies --no-ri --no-rdoc #{latest}")) end diff --git a/features/steps/using_steps.rb b/features/steps/using_steps.rb index 5875d04..c95b3ee 100644 --- a/features/steps/using_steps.rb +++ b/features/steps/using_steps.rb @@ -1,49 +1,25 @@ -Given /^a project called "([^\"]*)" is created and frozen$/ do |project_name| - @project_name = project_name - Given 'cucumber-nagios is installed' - When "I create a new project called \"#{@project_name}\"" - And 'I freeze in dependencies' - Then 'a Gemfile lock should be created' -end - -When /^I generate a new feature called "([^\"]*)" for "([^\"]*)"$/ do |feature, site| - Dir.chdir("/tmp/#{@project_name}") do - silent_system("cucumber-nagios-gen feature #{site} #{feature}") - end -end - -Then /^a feature file should exist for "([^\"]*)" on "([^\"]*)"$/ do |feature, site| - File.exists?("/tmp/#{@project_name}/features/#{site}/#{feature}.feature").should be_true -end - -Then /^the "([^\"]*)" feature on "([^\"]*)" should exit cleanly$/ do |feature, site| - Dir.chdir("/tmp/#{@project_name}") do - silent_system("cucumber-nagios features/#{site}/#{feature}.feature").should be_true - end -end - -Then /^the "([^\"]*)" feature on "([^\"]*)" should not exit cleanly$/ do |feature, site| - Dir.chdir("/tmp/#{@project_name}") do - silent_system("cucumber-nagios features/#{site}/#{feature}.feature").should be_false - end -end - -When /^the "([^\"]*)" feature on "([^\"]*)" checks for something preposterous$/ do |feature, site| - file_name = "/tmp/#{@project_name}/features/#{site}/#{feature}.feature" - File.open(file_name,'a') do |file| - file << " Then I should see \"supercalifragilisticexpialidocious\"" - end -end - -Then /^"([^"]*)" in the "([^"]*)" project should not exist$/ do |file, project_name| - filename = File.join(file, project_name) - File.exists?(filename).should be_false -end +# Most steps are now described using Aruba's steps. +# +# For an example see: +# ./cucumber-nagios/features/ssh.feature +# +# For step definitions see: +# ./cucumber-nagios/lib/cuken/cucumber/ssh.rb +# +# For the SSH api see: +# ./cucumber-nagios/lib/cuken/api/ssh.rb +# +# To use step definitions in your cucumber +# feature files, add to env.rb: +# +# require 'cuken/ssh' +# +# Enjoy. +# -Then /^the "([^"]*)" feature on "([^"]*)" should produce multiline output$/ do |feature, site| - Dir.chdir("/tmp/#{@project_name}") do - command = "cucumber-nagios features/#{site}/#{feature}.feature" - @output = `#{command}` - @output.split("\n").size.should > 1 - end +# +# Some WWW access features/steps can take a while: +# +Before do + @aruba_timeout_seconds.nil? || @aruba_timeout_seconds < 30 ? @aruba_timeout_seconds = 10 : @aruba_timeout_seconds end diff --git a/features/support/env.rb b/features/support/env.rb index b048efa..da7eb84 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,4 +1,12 @@ #!/usr/bin/env ruby +require 'bundler' +begin + Bundler.setup(:default, :development) +rescue Bundler::BundlerError => e + $stderr.puts e.message + $stderr.puts "Run `bundle install` to install missing gems" + exit e.status_code +end $: << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib')) $: << File.expand_path(File.dirname(__FILE__)) @@ -9,3 +17,8 @@ World do Webrat::Session.new(Webrat::MechanizeAdapter.new) end + +require 'cuken/common' +require 'cuken/ssh' +require 'cuken/cmd' +require 'cuken/file' diff --git a/features/using.feature b/features/using.feature index 114cdb6..73599aa 100644 --- a/features/using.feature +++ b/features/using.feature @@ -1,3 +1,10 @@ +# For complete reusable step listings see: +# lib/aruba/cucumber.rb +# https://github.com/aslakhellesoy/aruba/blob/master/lib/aruba/cucumber.rb +# AND +# lib/cuken/*.rb +# https://github.com/hedgehog/cuken + Feature: Using features To test websites And other infrastructure @@ -5,37 +12,76 @@ Feature: Using features Needs helper tools To create and run features + Background: + Given cucumber-nagios is installed + Given I successfully run "cucumber-nagios-gen project using-tests" + And I cd to "using-tests" + @using Scenario: Create a feature - Given cucumber-nagios is installed - And a project called "more-great-tests" is created and frozen - When I generate a new feature called "login" for "github.com" - Then a feature file should exist for "login" on "github.com" + Given I successfully run "cucumber-nagios-gen feature github.com login" + Then the output should contain: + """ + Generating with project generator: + [ADDED] .gitignore + [ADDED] .bzrignore + [ADDED] Gemfile + [ADDED] features/steps + [ADDED] features/support + [ADDED] README + + Your new cucumber-nagios project can be found in /usr/src/cucumber-nagios/tmp/aruba/using-tests. + + Next, install the necessary RubyGems with: + + bundle install + + Your project has been initialised as a git repository. + + Generating with feature generator: + [ADDED] features/github.com/login.feature + [ADDED] features/github.com/steps/login_steps.rb + """ @using Scenario: Run a successful feature - Given a project called "passing-features" is created and frozen - When I generate a new feature called "homepage" for "github.com" - Then the "homepage" feature on "github.com" should exit cleanly + Given I successfully run "cucumber-nagios-gen feature google.com homepage" + When I successfully run "cucumber-nagios features/google.com/homepage.feature" + Then the output should contain: + """ + CUCUMBER OK - Critical: 0, Warning: 0, 2 okay | passed=2; failed=0; nosteps=0; total=2; + """ @using - Scenario: Run a failing feature - Given a project called "failing-features" is created and frozen - When I generate a new feature called "profile" for "github.com" - And the "profile" feature on "github.com" checks for something preposterous - Then the "profile" feature on "github.com" should not exit cleanly + Scenario: Run a feature without steps + Given I successfully run "cucumber-nagios-gen feature github.com profile" + And the file "features/github.com/profile.feature" with: + """ + Feature: Failure + Scenario: The only option + Given the output should contain "supercalifragilisticexpialidocious" + """ + When I run "cucumber-nagios features/google.com/profile.feature" + Then the exit status should be 4 - @using - Scenario: webrat.log output - Given a project called "passing-features" is created and frozen - When I generate a new feature called "homepage" for "github.com" - Then the "homepage" feature on "github.com" should exit cleanly - Then "webrat.log" in the "passing-features" project should not exist +# We should really switch to Capybara and friends ASAP +# @using +# Scenario: webrat.log output +# When I generate the feature "homepage" for "github.com" +# Then the "homepage" feature on "github.com" should exit cleanly +# Then "webrat.log" in the "passing-features" project should not exist @using Scenario: Multiline output - Given a project called "multiline-output" is created and frozen - When I generate a new feature called "profile" for "github.com" - And the "profile" feature on "github.com" checks for something preposterous - Then the "profile" feature on "github.com" should not exit cleanly - And the "profile" feature on "github.com" should produce multiline output + Given I successfully run "cucumber-nagios-gen feature google.com profile" + And the file "features/google.com/profile.feature" with: + """ + Feature: Failure + Scenario: The only option + Given the output should contain "supercalifragilisticexpialidocious" + """ + When I run "cucumber-nagios features/google.com/profile.feature" + Then the output from "cucumber-nagios features/google.com/profile.feature" contains: + """ + CUCUMBER CRITICAL - Critical: 1, Warning: 0, 0 okay | passed=0; failed=1; nosteps=0; total=1; + """ diff --git a/lib/cucumber-nagios.rb b/lib/cucumber-nagios.rb index 075162c..579a308 100644 --- a/lib/cucumber-nagios.rb +++ b/lib/cucumber-nagios.rb @@ -1 +1,9 @@ +require 'bundler' +begin + Bundler.setup(:default) +rescue Bundler::BundlerError => e + $stderr.puts e.message + $stderr.puts "Run `bundle install` to install missing gems" + exit e.status_code +end require 'cucumber/nagios' # compat \ No newline at end of file diff --git a/lib/cucumber/nagios/steps/command_steps.rb b/lib/cucumber/nagios/steps/command_steps.rb index 5565df5..a7332db 100644 --- a/lib/cucumber/nagios/steps/command_steps.rb +++ b/lib/cucumber/nagios/steps/command_steps.rb @@ -1,80 +1,23 @@ +require 'cuken/cmd' +# Place your custom command line steps in this file. +# For a suite of reusable steps see the note below. +# Cuken's reusable steps are modelled on Aruba. # -# Author:: Adam Jacob () -# Copyright:: Copyright (c) 2008 Opscode, Inc. +# Note: +# Shell commands are now described using Aruba steps. # -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# For an example see: +# ./cuken/features/commands.feature +# +# For step definitions see: +# ./lib/cuken/cucumber/cmd.rb +# +# For the SSH api see: +# ./lib/cuken/api/cmd.rb +# +# To use the step definitions in your cucumber +# feature files, add to env.rb: +# +# +# Enjoy. # -# Portions of this file originally from Chef (github.com/opscode/chef) - -When /^I run '(.+)'$/ do |cmd| - status = Cucumber::Nagios::Command.popen4(cmd) do |p, i, o, e| - @stdout = o.gets(nil) - @stderr = e.gets(nil) - end - @status = status -end - -### -# Then -### -Then /^it should exit '(.+)'$/ do |exit_code| - begin - @status.exitstatus.should eql(exit_code.to_i) - rescue - print_output - raise - end -end - -Then /^it should exit from being signaled$/ do - begin - @status.signaled?.should == true - rescue - print_output - raise - end -end - -def print_output - puts "--- run stdout:" - puts @stdout - puts "--- run stderr:" - puts @stderr -end - -# Then 'stdout' should have 'foo' -Then /^'(.+)' should have '(.+)'$/ do |which, to_match| - self.instance_variable_get("@#{which}".to_sym).should match(/#{to_match}/m) -end - -# Then 'stderr' should not have 'foo' -Then /^'(.+)' should not have '(.+)'$/ do |which, to_match| - self.instance_variable_get("@#{which}".to_sym).should_not match(/#{to_match}/m) -end - -# Then 'my dog ate my homework' should appear on 'stdout' '5' times -Then /^'(.+)' should appear on '(.+)' '(.+)' times$/ do |to_match, which, count| - seen_count = 0 - self.instance_variable_get("@#{which}".to_sym).split("\n").each do |line| - seen_count += 1 if line =~ /#{to_match}/ - end - seen_count.should == count.to_i -end - diff --git a/lib/cucumber/nagios/steps/file_steps.rb b/lib/cucumber/nagios/steps/file_steps.rb index bc4cc5b..3abbc92 100644 --- a/lib/cucumber/nagios/steps/file_steps.rb +++ b/lib/cucumber/nagios/steps/file_steps.rb @@ -1,120 +1,25 @@ +require 'cuken/file' +# Place your custom File steps in this file. +# For a suite of reusable steps see the note about Cuken below. +# Cuken's reusable steps are modelled on Aruba. # -# Author:: Adam Jacob () -# Copyright:: Copyright (c) 2008 Opscode, Inc. +# NOTE: +# Command and (local) file/directory interactions are +# described using Aruba steps. +# Which Cuken augments for some special cases. # -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# For an example of usage see: +# ./cuken/features/files.feature +# +# For Cuken step definitions see: +# ./lib/cuken/cucumber/file.rb +# +# For the Cuken File API see: +# ./lib/cuken/api/file.rb +# +# To use the step definitions in your cucumber +# feature files, add to env.rb: +# +# +# Enjoy. # -# Portions of this file originally from Chef (github.com/opscode/chef) - -require 'etc' - -### -# Given -### - -Given /^we have an empty file named '(.+)'$/ do |filename| - filename = File.new(filename, 'w') - filename.close -end - -Given /^we have the atime\/mtime of '(.+)'$/ do |filename| - @mtime = File.mtime(filename) - @atime = File.atime(filename) -end - -#### -# Then -#### - -Then /^a file named '(.+)' should exist$/ do |filename| - File.exists?(filename).should be(true) -end - -Then /^a file named '(.+)' should not exist$/ do |filename| - File.exists?(filename).should be(false) -end - -Then /^'(.+)' should exist and raise error when copying$/ do |filename| - File.exists?(filename).should be(true) - lambda{copy(filename, filename + "_copy", false)}.should raise_error() - File.delete(filename) -end - - -Then /^the (.)time of '(.+)' should be different$/ do |time_type, filename| - case time_type - when "m" - current_mtime = File.mtime(filename) - current_mtime.should_not == @mtime - when "a" - current_atime = File.atime(filename) - current_atime.should_not == @atime - end -end - -Then /^a file named '(.+)' should contain '(.+)'$/ do |filename, contents| - file = IO.read(filename) - file.should =~ /#{contents}/m -end - -Then /^a file named '(.+)' should contain '(.+)' only '(.+)' time(?:s)?$/ do |filename, string, count| - seen_count = 0 - IO.foreach(filename) do |line| - if line =~ /#{string}/ - seen_count += 1 - end - end - seen_count.should == count.to_i -end - -Then /^the file named '(.+)' should be owned by '(.+)'$/ do |filename, owner| - uid = Etc.getpwnam(owner).uid - cstats = File.stat(filename) - cstats.uid.should == uid -end - -Then /^the file named '(.+)' should have mode '(.+)'$/ do |filename, expected_mode| - cstats = File.stat(filename) - (cstats.mode & 007777).should == octal_mode(expected_mode) -end - -def octal_mode(mode) - ((mode.respond_to?(:oct) ? mode.oct : mode.to_i) & 007777) -end - -Then /^a directory named '(.+)' should exist$/ do |dir| - File.directory?(dir).should be(true) -end - -Then /^a directory named '(.+)' should not exist$/ do |dir| - File.directory?(dir).should be(false) -end - -Then /^the directory named '(.+)' should be owned by '(.+)'$/ do |dirname, owner| - uid = Etc.getpwnam(owner).uid - cstats = File.stat(File.join(tmpdir, dirname)) - cstats.uid.should == uid -end - -Then /^the directory named '(.+)' should have mode '(.+)'$/ do |dirname, expected_mode| - cstats = File.stat(dirname) - (cstats.mode & 007777).should == octal_mode(expected_mode) -end - diff --git a/lib/cucumber/nagios/steps/http_header_steps.rb b/lib/cucumber/nagios/steps/http_header_steps.rb index 09fea6d..6ce904f 100644 --- a/lib/cucumber/nagios/steps/http_header_steps.rb +++ b/lib/cucumber/nagios/steps/http_header_steps.rb @@ -1,3 +1,10 @@ +# +# Some WWW access features/steps can take a while: +# +Before do + @aruba_timeout_seconds.nil? || @aruba_timeout_seconds < 30 ? @aruba_timeout_seconds = 10 : @aruba_timeout_seconds +end + When /I fetch headers from "(.*)"/ do |url| visit(url) @headers = response.header diff --git a/lib/cucumber/nagios/steps/http_steps.rb b/lib/cucumber/nagios/steps/http_steps.rb index 2ea9641..96dc1fe 100644 --- a/lib/cucumber/nagios/steps/http_steps.rb +++ b/lib/cucumber/nagios/steps/http_steps.rb @@ -1,4 +1,11 @@ # Setup +# +# Some WWW access features/steps can take a while: +# +Before do + @aruba_timeout_seconds.nil? || @aruba_timeout_seconds < 30 ? @aruba_timeout_seconds = 10 : @aruba_timeout_seconds +end + Given /^I am HTTP digest authenticated with the following credentials:$/ do |table| attrs = table.hashes.first username = attrs["username"] diff --git a/lib/cucumber/nagios/steps/ssh_steps.rb b/lib/cucumber/nagios/steps/ssh_steps.rb index 7334eb3..a2ea5d6 100644 --- a/lib/cucumber/nagios/steps/ssh_steps.rb +++ b/lib/cucumber/nagios/steps/ssh_steps.rb @@ -1,79 +1,25 @@ -Given /^I have no public keys set$/ do - @auth_methods = %w(password) -end - -Then /^I can ssh to "([^\"]*)" with the following credentials:$/ do |host, table| - @auth_methods ||= %w(publickey password) - - credentials = table.hashes - credentials.each do |creds| - lambda { - Net::SSH.start(host, creds["username"], :password => creds["password"], :auth_methods => @auth_methods) - }.should_not raise_error - end -end - -Then /^I can ssh to the following hosts with these credentials:$/ do |table| - @keys ||= [] - @auth_methods ||= %w(password) - session_details = table.hashes - - session_details.each do |session| - # initialize a list of keys and auth methods for just this session, as - # session can have session-specific keys mixed with global keys - session_keys = Array.new(@keys) - session_auth_methods = Array.new(@auth_methods) - - # you can pass in a keyfile in the session details, so we need to - if session["keyfile"] - session_keys << session["keyfile"] - session_auth_methods << "publickey" - end - - lambda { - Net::SSH.start(session["hostname"], session["username"], :password => session["password"], - :auth_methods => session_auth_methods, - :keys => session_keys) - }.should_not raise_error - end -end - -Given /^I have the following public keys:$/ do |table| - @keys = [] - public_key_paths = table.hashes - - public_key_paths.each do |key| - File.exist?(key["keyfile"]).should be_true - @keys << key["keyfile"] - end - - @auth_methods ||= %w(password) - @auth_methods << "publickey" -end - -When /^I ssh to "([^\"]*)" with the following credentials:$/ do |hostname, table| - @keys = [] - @auth_methods ||= %w(password) - session = table.hashes.first - session_keys = Array.new(@keys) - session_auth_methods = Array.new(@auth_methods) - if session["keyfile"] - session_keys << session["keyfile"] - session_auth_methods << "publickey" - end - - lambda { - @connection = Net::SSH.start(hostname, session["username"], :password => session["password"], - :auth_methods => session_auth_methods, - :keys => session_keys) - }.should_not raise_error -end - -When /^I run "([^\"]*)"$/ do |command| - @output = @connection.exec!(command) -end - -Then /^I should see "([^\"]*)" in the output$/ do |string| - @output.should =~ /#{string}/ -end - +require 'cuken/ssh' +# Place your custom SSH steps in this file. +# For a suite of reusable steps see the note below. +# Cuken's reusable steps are modelled on Aruba. +# +# NOTE: +# SSH sessions are set-up using the ssh-forever gem. +# Command and (local) file/directory interactions are +# described using Aruba steps. +# +# For an example see: +# ./cuken/features/ssh.feature +# +# For step definitions see: +# ./lib/cuken/cucumber/ssh.rb +# +# For the SSH api see: +# ./lib/cuken/api/ssh.rb +# +# To use the step definitions in your cucumber +# feature files, add to env.rb: +# +# +# Enjoy. +# diff --git a/lib/cucumber/nagios/support/env.rb b/lib/cucumber/nagios/support/env.rb index 77ab0ac..0402fb3 100644 --- a/lib/cucumber/nagios/support/env.rb +++ b/lib/cucumber/nagios/support/env.rb @@ -1,4 +1,12 @@ #!/usr/bin/env ruby +require 'bundler' +begin + Bundler.setup(:default, :development) +rescue Bundler::BundlerError => e + $stderr.puts e.message + $stderr.puts "Run `bundle install` to install missing gems" + exit e.status_code +end $: << File.expand_path(File.dirname(__FILE__)) @@ -16,3 +24,9 @@ def response ResponseHelper.new Webrat::Session.new(Webrat::MechanizeAdapter.new) end + +require 'cuken/ssh' +require 'cuken/cmd' +require 'cuken/file' + +require 'rspec/expectations'