Schon häufiger wurde hier im Blog end 2 end monitoring behandelt, z.B. auto-it, webinject.
Das rubygem watir-webdriver ist ein weiteres tool aus diesem Bereich. Mit Ihm kann man Webseiten abrufen, auf Elemente überprüfen und Aktionen ausführen. Das besondere am watir-webdriver ist, dass er einen echten Browser zum simulieren der Verbindung nutzt.
Auf einem Linux Server ohne GUI schön und gut könnte man sich jetzt denken, doch mit gem headless und Xvfb kann man seinen Browser auch ohne GUI nutzen.
Im folgenden Beispiel zeige ich die Funktionsweise von watir. Als System dient mir ein debian wheezy

Vorbereitung

Als Voraussetzung braucht man folgende Pakete

aptitude install rubygems curl xvfb

Unter debian installiert an jetzt iceweasel, unter anderen distros wohl eher firefox. Chrome sollte auch funktionieren (und safari auf dem mac)

aptitude install iceweasel

Ich empfehle ruby mit rvm zu verwalten. Dann kann man zwischen verschiedenen Projekten und ruby Versionen einfach hin und her springen.

curl -L http://get.rvm.io | bash -s stable
# su -
rvm install 1.9.3
rvm use ruby 1.9.3@watir --create

Projektverzeichnis anlegen und Gemset für dieses Verzeichnis festlegen

mkdir check_watir
cd $_
rvm use @watir --ruby-version

Ein Gemfile erleichtert es einem die plugins auf andere Server zu kopieren. Nach einem “bundle” stehen dort wieder alle gems zur verfügung.

vim Gemfile
source 'https://rubygems.org'
gem 'watir-webdriver'
gem 'headless'
bundle

Erster Test im irb

Um die Funktionalität von watir ersteinmal auszuprobieren bietet es sich an irb zu benutzen.

irb
1.9.3p194 :001 > require 'watir-webdriver'
 => true
1.9.3p194 :002 > require 'headless'
 => true
1.9.3p194 :003 > headless = Headless.new
 => #
1.9.3p194 :004 > headless.start
 => #
1.9.3p194 :005 > b = Watir::Browser.start 'www.google.com'
 => #
1.9.3p194 :006 > b.text_field(:name => 'q').set("Icinga Monitoring")
 => ""
1.9.3p194 :007 > b.button(:name => 'btnG').click
 => []
1.9.3p194 :008 > b.a(:text => 'Home - Icinga: Open Source Monitoring').exists?
 => true
1.9.3p194 :013 > quit

Ein echtes plugin

Dieses Plugin geht zuerst auf www.netways.de. Dort sucht es den Link ‘Shop’ und klickt diesen an; sucht anschließend den Link Warenkorb, klickt diesen und überprüft ob der Warenkorb leer ist.

#!/usr/bin/env ruby
require 'watir-webdriver'
require 'headless'
headless = Headless.new
headless.start
b = Watir::Browser.start 'www.netways.de'
l = b.link :text =>; 'Shop'
unless l.exists?
  puts "Critical - Missings link Warenkorb"
  exit 2
end
l.click
l = b.link :text =>; 'Warenkorb'
unless l.exists?
  puts "Critical - Missings link Warenkorb"
  exit 2
end
l.click
p = b.p :class =>; 'warning'
unless p.text == "Ihr Warenkorb ist leer."
  puts "Critical - cart corrupt"
  exit 2
end
b.close
headless.destroy
puts "OK"
exit 0

Das nächste Plugin hat ein paar Parameter und überprüft den Titel einer Webseite

#!/usr/bin/env ruby
require 'watir-webdriver'
require 'headless'
require 'optparse'
options = {}
optparse = OptionParser.new do |opts|
  opts.banner = "Usage: check_title.rb [options]"
  opts.on("-u", "--url URL", "URL of website") do |u|
    options[:url] = u
  end
  opts.on("-p", "--criticalpattern CRITICALP", "This pattern must be found on the page") do |cp|
    options[:criticalpattern] = cp
  end
  opts.on("-h", "--help", "Display this screen") do
    puts opts
    exit 3
  end
end
begin
  ARGV << "-h" if ARGV.size < 4
  optparse.parse!(ARGV)
rescue OptionParser::ParseError
  $stderr.print "Error: " + $! + "\n"
  exit
end
url = options[:url]
criticalpattern = options[:criticalpattern]
headless = Headless.new
headless.start
b = Watir::Browser.start url
if b.title == criticalpattern
  puts "OK - Title = #{b.title}"
else
  puts "Critical - #{b.title} != #{criticalpattern}"
end
b.close
headless.destroy

Mit diesen Tools kann man schon ein wenig anfangen. Richtig mächtig wird dies alles aber erst wenn man dieses noch mit cucumber nutzt, dann hat man am ende einen check in diesem Stil:

Feature: Buying Sensors
  Background:
    Given I am on the shopping page
  Scenario: Verify cart with one sensor
    When I buy "Teltonika ModemUSB/E10 GSM Modem"
    Then I should see "1" in the quantity for line "1"
    And I should see "Teltonika ModemUSB/E10 GSM Modem" in the description for line "1"
    And I should see "149,00" in the cart total

Aber hierzu schreibe ich mal später etwas.

Christoph Niemann
Christoph Niemann
Senior Consultant

Christoph hat bei uns im Bereich Managed Service begonnen und sich dort intensiv mit dem internen Monitoring auseinandergesetzt. Seit 2011 ist er nun im Consulting aktiv und unterstützt unsere Kunden vor Ort bei größeren Monitoring-Projekten und PERL-Developer-Hells.