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?
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?



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
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