Automatisch testen via de browser

Je kunt tests op vele niveaus schrijven, van low-level unittests tot integratietests, maar testen op het hoogste niveau, de browser, wordt meestal met de hand door een tester gedaan. In hoeverre valt dit te automatiseren?


Wat is Watir?

Watir is een Ruby-library om Internet Explorer te scripten. Zodra je Ruby geïnstalleerd hebt (met de One-Click-Installer) kun je Watir via de command-line installeren met gem install watir.
Vervolgens kun je via irb (interactive ruby) de browser besturen. Start irb op vanuit de command line en voer de volgende commando’s uit:

require 'watir'
include Watir
ie = IE.start 'http://nieuwsfilter.finalist.com/'

We gebruiken de voor de publieke omroep gebouwde nieuwsfilter-site als voorbeeld. Via het ie object kunnen we nu de browser besturen. Dit object heeft een groot aantal ingebouwde methodes. Een paar belangrijke zijn html, die de huidige HTML als
string ophaalt, goto, die de browser naar een gegeven pagina stuurt, en back, identiek aan klikken op de back-button.

Interactie met de pagina gaat meestal via een specifiek element.
Methodes zoals link, button, checkbox, hidden, image, p, radio, span, en text_field zoeken binnen de pagina een element.

ie.link(:text, "Pickaxe").click

is bijvoorbeeld een manier om de eerste link met de tekst ‘Pickaxe’ te zoeken, en erop te klikken.

ie.checkbox(:name,
"checkme").clear

deselecteert de checkbox met naam ‘clickme’.

ie.text_field(:index,3).set('hallo')

zet de tekst van het derde tekstveld op ‘hallo’.
Een stukje script ziet er dan als volgt uit:

require 'watir'
include Watir
ie = IE.start 'http://nieuwsfilter.finalist.com'
def ie.cb(i)
  case i
  when Numeric: buttons[i]
  else button(:value, i)
  end.click
end
def ie.cl(i)
  case i
  when Regexp: link(:url, i)
  when String: link(:text, i)
  when Numeric: links[i]
  end.click
end
def ie.tf(i,s); text_fields[i].set(s) ; end
cl = lambda {|i| ie.cl i }

We definiëren een paar extra methodes op het ie object: cl klikt op een link op basis van index, text of url, cb klikt op een button, en tf zet de tekst van een tekstveld.

1.upto(7, &cl) # alle categorieen
ie.cb 1 # goed button van eerste artikel
ie.back
ie.cl 10 # link eerste artikel
ie.back
ie.cl /gebruiker/ # link naar gebruiker
ie.cb /vriend/ # button naar 'dit is een friend'
ie.back
ie.back
ie.cl 12
ie.cl 11
ie.back

Nu klikken we op wat links en buttons, en gaan terug via de back-button als dat ons niet bevalt.

Vervolgens moeten we ons aanmelden. Dat is een probleem, want er wordt een gegenereerd wachtwoord toegestuurd. Bovendien kunnen we een email-adres maar eenmaal gebruiken. Een oplossing is Mailinator - een website voor openbare webmail, waarvan elke mailbox via RSS te
benaderen is. We schrijven een methode die ons wachtwoord probeert op te halen.

require 'rss'
URL = "http://mailinator.com/mailinator/rss.jsp?email="
def mailinator_pwd(u)
 # try until match
 loop do
   puts "waiting for email" ; sleep 10
   open(URL + u) {|c| RSS::Parser.parse(c.read, false).items }.each do |item|
     item.description =~ /wachtwoord is: ([a-z0-9]{8})$/ and return $1
   end
 end
end

Met deze methode kunnen we ons aanmelden en de extra features gaan gebruiken.

ie.cl 'aanmelden'
login = (1..6).map{?a + rand(26)}.pack('c*')
ie.tf 1, login
ie.tf 2, "#{login}@mailinator.com"
ie.cb "Registreren"
ie.cl "inloggen"
ie.tf 1, "#{login}@mailinator.com"
ie.tf 2, mailinator_pwd(login)
ie.cb "Inloggen"
ie.cl "profiel"
ie.tf 1, 'I love pink bunnies!'
ie.cb "Opslaan"
ie.link(:text, /alle categorie/).click
ie.cl 12 # submitter eerste artikel
ie.cb /vriend/
11.upto(13, &cl) # stemmen, reacties, vrienden
ie.cl "artikel toevoegen"
ie.tf 1, 'Fascinating article on Ruby and VIM'
ie.tf 2, "http://nieuwsfilter.finalist.com/artikel/#{rand(100)}"
ie.tf 3, 'VIM and Ruby - what a match!'
ie.checkboxes[4].set
ie.cb "Toevoegen"
sleep 1 # tijd voor redirect
ie.tf 1, 'Best article ever!'
ie.cb /reactie/

Zodra de stylesheets van de nieuwsfilter-site af zijn, zal ik een screencast posten van het runnen van het test-script.

Het uitvoeren van een script zoals het vorige is erg handig en spoort een heleboel problemen op. Maar voordat het de naam test verdient, moet er nog wat meer gebeuren.
Daarover volgende keer meer.            
       

   

———————————————————————————–
Meer weten over Ruby-specialist Finalist IT Group?


2 reacties »

  1. Goed bedacht dat gebruik van mailinator, maar is het nou wel zou handig om je testsuite van een dergelijke constructie afhankelijk te laten zijn?

    Verder vroeg ik me af of watir testsuites ook kan draaien op een remote machine?

    Bij de VPRO hebben wij een test-setup gemaakt waarbij we Selenium (http://www.openqa.org/selenium/) op een soortgelijke manier inzetten. Het is daarbij wel geinig dat deze tests niet op de CI machine (solaris) worden uitgevoerd maar op een daarvoor ingerichte windows (zou vmware kunnen zijn) machine. Selenium is overigens vanuit een heel scala aan programmeertalen te gebruiken en heeft verder als er interessante optie dat je een testsuite in de browser kunt bouwen.

    p3t0r - januari 2, 2007 17:39

  2. Dit is extreem veel cooler dan je zou denken op het eerste gezicht. Vandaag heb ik even gespeeld met watir for Safari (Mac OS) en je kunt watir voor Firefox krijgen. De syntax is mooi gelijk gehouden, dus je kunt je test-script door een generatortje halen en meteen op verschillende browsers testen.

    Felix - maart 8, 2007 15:14

Reageer

RSS feed for comments on this post · TrackBack URI