Introductie Selenium
Een tijd geleden was ik Selenium al eens tegen gekomen, het leek een interessant product maar ik heb er nooit echt veel tijd aan geschonken. Niet zo gek lang geleden kwam Selenium weer onder mijn ogen en besloot ik er dit keer wat meer tijd in te steken. In dit blogartikel deel ik mijn ervaringen.
Selenium is zoals ze het zelf omschrijven een testtool voor webapplicaties. De Selenium Core is een Javascript library. Daarom worden de tests ook in de browser uitgevoerd. Alle hedendaagse bekende browsers worden ondersteund door Selenium. Met de Selenium Core is het mogelijk om in je tests door je webapplicatie heen te navigeren en te controleren of alles zich functioneel gedraagt zoals je het verwacht. De tests worden beschreven in “Selenese” en dat komt neer op een tabel met Selenium-commando’s opgeslagen in HTML. Een testscript zou er als volgt uit kunnen zien:
| MySeleniumTest | ||
| open | http://localhost/PaginaOnderTest | |
| type | voornaam | Jeoffrey |
| clickAndWait | ok | |
| verifyTextPresent | Hallo Jeoffrey! | |
De eerste regel van dit script is commentaar, want Selenium ziet rijen met minder dan 3 kolommen als commentaar. De eerste echte actie is het laden van de pagina /PaginaOnderTest. Het script vult de waarde Jeoffrey in het tekstveld ‘voornaam’ in en klikt vervolgens op de knop ‘ok’. Na het resultaat afgewacht te hebben wordt de inhoud gecontroleerd. In dit geval moet de inhoud de tekst ‘Hallo Jeoffrey!’ bevatten.
Het nadeel van enkel de Selenium Core te gebruiken is dat je zowel de Selenium Core als je testscripts met de webapplicatie mee moet leveren. Of deze moeten beschikbaar gemaakt worden door de webserver, zolang de Selenium Core en de test scripts het domein, protocol en port van de web applicatie maar delen. Dit is nodig om aan het dezelfde bron principe te voldoen. Deze beveiliging zorgt er voor dat een script van bron A niet in staat is een document van bron B te lezen of wijzigen.
Het niet willen meeleveren van de Selenium Core en de testscripts kan één van de redenen zijn om Selenium RC te gaan gebruiken. Selenium RC bestaat uit een server en enkele client libraries. De server maakt het mogelijk om een browser te starten, vervolgens een test uit te voeren en daarna weer netjes de browser te sluiten. Dit is zeer interessant voor automatische integratie doeleinden. Er zijn client libraries voor de volgende talen: Java, Perl, PHP, Python en Ruby. Ook voor .NET is een library beschikbaar. Dus voor ieder wat wils.
Een voorbeeld van een unit test die dezelfde test als hierboven uitvoert ziet er als volgt uit:
package com.finalist.selenium; import junit.framework.TestCase; import com.thoughtworks.selenium.Selenium; import com.thoughtworks.selenium.DefaultSelenium; public class SeleniumTest extends TestCase { private Selenium selenium; public void setUp() { selenium = new DefaultSelenium("localhost", 4444, "*iexplore", "http://localhost"); selenium.start(); } public void tearDown() { selenium.stop(); } public void testHelloMsg() { selenium.open("http://localhost/PaginaOnderTest"); selenium.type("voornaam", "Jeoffrey"); selenium.click("ok"); selenium.waitForPageToLoad("2000"); assertTrue(selenium.isTextPresent("Hallo Jeoffrey!")); } }
De server is geschreven in Java en is zodoende platform onafhankelijk. Hierdoor is het in principe mogelijk om met elke gewenste browser te testen op elk mogelijk platform. De browser wordt direct geopend met een url die er in deze test uit ziet als http://localhost/selenium-server/core/RemoteRunner.html?sessionId=123abc. Voor Selenium RC is het niet nodig om de Selenium Core met de applicatie mee te leveren. Om het dan toch mogelijk te maken die url te open wordt de server ook als proxy server ingezet. De gestarte browser wordt met de server als proxy server configureerd. De proxy server luistert naar alle requests met een url met de string “/selenium-server/”. Hierdoor denkt de browsers dat de Selenium Core op de website aanwezig is. Zo wordt het dezelfde bron principe omzeild.
Als je de mogelijkheid hebt om Firefox te gebruiken is er de Selenium IDE plugin beschikbaar. Deze IDE maakt het onder andere mogelijk om testscripts op te nemen, te wijzigen en op te slaan. Ook het opslaan als source voor je favoriete client library is mogelijk. Hieronder is de door Selenium IDE geëxporteerde Java source te zien voor wederom dezelfde test:
package com.example.tests; import com.thoughtworks.selenium.*; import java.util.regex.Pattern; public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp("http://localhost/", "*chrome"); } public void testNew() throws Exception { selenium.open("http://localhost/PaginaOnderTest"); selenium.type("voornaam", "Jeoffrey"); selenium.click("ok"); selenium.waitForPageToLoad("30000"); verifyTrue(selenium.isTextPresent("Hallo Jeoffrey!")); } }
Als laatste is het ook nog mogelijk om meerdere Selenium RC servers in te zetten en deze te koppelen door middel van Selenium GRID. Hierbij fungeert de Selenium GRID als een hub die precies dezelfde interface heeft als Selenium RC. Selenium GRID lijkt voornamelijk handig te zijn om meer concurrent tests te kunnen uitvoeren.
Deze test is natuurlijk een heel simpel voorbeeld om te demonstreren hoe je een test kan opzetten met Selenium. Selenium biedt veel mogelijkheden om het gedrag van een echte gebruiker te simuleren. Het is bijvoorbeeld mogelijk om muis bewegingen te simuleren en zo drag en drop functionaliteit na te bootsen. Om precies te zien wat je met Selenium kan raad ik je aan om een kijkje te nemen op de Selnium site.
Conclusie
Selenium lijkt mij een handig product om te kunnen testen in de omgeving waar de webapplicatie uiteindelijk tot zijn recht moet komen, de browser. Het is een testtool die het mogelijk maakt de ultieme integratie test eenvoudig op te zetten. Ik ga Selenium dan ook snel in mijn huidige project introduceren.



Bij de VPRO hebben we getracht de frontend scripters bij iedere pagina ook een Selenium-test te laten schrijven. Dat ging een tijdje goed. Er bleek echter steeds meer tijd te gaan zitten in het onderhoud van de tests.
Bij het refactoren van object geörienteerde code hoef je (als je goed ontwikkeld) vaak niet heel veel (soms zelfs niets) aan je tests aan het passen. Als je echter een beetje gaat schuiven met elementen in HTML breek je bijna altijd de tests.
Nou is het wel mogelijk (tests zijn tenslotte gewoon javascript) om tests te schrijven die en goed testen en om kunnen gaan met wijzigingen in de pagina; maar dat is erg moeilijk… vooral omdat die wijziging ook een bug zou kunnen zijn.
Dit wil niet zeggen dat ik Selenium geen mooie tool vind. Maar wel dat je al vanaf het begin al erg goed moet nadenken over hoe en wat je wilt testen.
Peter Maas - april 7, 2008 19:03