Get Test-geïnfecteerd met Selenium

Testen wordt vaak verwaarloosd in de programmering en webontwikkeling is niet anders. Veel ontwikkelaars hebben zich nog niet gerealiseerd dat geautomatiseerde tests u productiever, minder gestrest en meer zelfvertrouwen kunnen geven over het coderen van de volgende functie. In dit artikel zullen we ons concentreren op het gebruik van Selenium om browsertests te automatiseren.

Als webontwikkelaars hebben we tests van een soort nodig, omdat we zeker niet willen dat bugrapporten van de gebruikers van onze applicaties onze manier van testen zijn. We willen testen automated omdat handmatig testen, hoewel soms een noodzakelijk kwaad, traag, foutgevoelig en saai is. Herhaaldelijk handmatig testen van een webtoepassing in meerdere browsers kan, eerlijk gezegd, het vernietigen van de ziel zijn! Een tool als Selenium kan je verslaafd maken aan geautomatiseerd testen.


Get Test-Infected

Misschien kun je je relateren aan deze ervaring: je opent je project met de bedoeling een nieuwe functie te coderen of een bug te repareren, en je vraagt ​​je af: "Kunnen de veranderingen die ik ga maken onbedoelde neveneffecten hebben? Zal ik mijn code breken? ?"

Deze angst om veranderingen aan te brengen wordt alleen maar erger naarmate het project vordert, en het ruïneert vaak het plezier van coderen.

Maar als u een goede reeks geautomatiseerde tests hebt en ze vaak uitvoert, maakt u een goede kans om snel te weten of u uw code heeft overtreden. Dit geeft je een gevoel van vertrouwen in plaats van angst, waardoor je gewoon verder kunt gaan met wat je moet doen, of dat nu is om nieuwe functies te implementeren, bugfixes of refactoring. Het is heel verfrissend.

Dit is gemakkelijker te begrijpen als je de pijn van het programmeren hebt doorstaan ​​zonder goede tests. Het is verleidelijk om te denken: "Ik wil gewoon doorgaan met het coderen van het volgende deel van mijn applicatie." Dit is vaak meer het geval wanneer je aan iets relatief eenvoudigs werkt. Maar zoals elke ontwikkelaar u kan vertellen, kunnen dingen snel complexer worden. Plotseling is het eng om de code aan te passen, en dat is het moment waarop je echt een uitgebreide set tests op prijs stelt om een ​​back-up van je te maken.

Maar het verminderen van angst is slechts één voordeel. Goed geschreven tests dienen om het systeem in ontwikkeling te documenteren, en dit bevordert een beter begrip tussen ontwikkelaars en klanten. Door naar een test te kijken, moet u precies kunnen aangeven hoe een bepaald aspect van het systeem zich zou moeten gedragen. Dit is een concept benadrukt door Gedraggedreven ontwikkeling (later besproken).

Een belangrijk idee is dat het belangrijk is om te overwegen hoe u uw toepassing test, net zo belangrijk als hoe u het gaat bouwen. Dat is de moeite waard om te herhalen: nadenken over hoe je je systeem moet testen is net zo belangrijk als hoe je de applicatiecode schrijft.

Het is een grote verschuiving in het denken, maar als je eenmaal denkt dat geautomatiseerde tests een fundamenteel onderdeel van programmeren zijn en de vruchten ervan hebben geplukt, zul je nooit terugkijken. Ik raakte verslaafd aan testen tijdens de kennismaking met TDD, maar het is naar mijn mening niet noodzakelijk dat een testgeïnfecteerde TDD of een eenheidstest doorkomt. Je moet gewoon de enorme waarde van geautomatiseerde tests hebben ervaren en je raar voelen over het programmeren, zo niet in de routine van het schrijven ervan.

Als je eenmaal in de mindset bent en de voordelen hebt geplukt, zul je nooit terugkijken

Een antwoord op deze argumenten kan zijn: "Dit klinkt allemaal als iets dat veel tijd kost, tijd die de volgende functie zou kunnen coderen." We hebben immers meestal maar weinig tijd om aan een project te besteden. En het klopt, het opzetten en samenstellen van geautomatiseerde tests kost tijd en moeite. Maar de hoeveelheid tijd die het op de lange termijn bespaart, en de verbeterde kwaliteit die het meestal naar de code brengt, maakt een rigoureuze routine van geautomatiseerd testen de investering waard.

We gebruiken een gratis tool genaamd Selenium. Selenium automatiseert browsers; het simuleert een gebruiker die interactie heeft met uw webapplicatie, muisklikken uitvoert, tekstinvoer en zelfs slepen en neerzetten (onder andere). Het kan ook worden gebruikt om te controleren wat op het scherm wordt weergegeven.

Weten hoe je goede tests schrijft, is een vaardigheid die je in de loop van de tijd ontwikkelt, maar in deze tutorial zullen we bespreken hoe je kunt beginnen met browser testen met Selenium.


Een weergave van testen vanaf 10.000 voet

Als u nog niet eerder bent getest, is het handig om een ​​algemeen idee te krijgen van de soorten tests die gewoonlijk worden gebruikt. Verschillende soorten tests worden voor verschillende doeleinden gebruikt. Houd er rekening mee dat de terminologie rond testen nogal inconsistent is - verschillende mensen gebruiken dezelfde term om iets verschillende dingen te bedoelen.

Unit tests worden gebruikt om de juistheid van individuele klassen, methoden en functies te controleren. De code die wordt uitgeoefend, moet geïsoleerd worden gehouden van andere delen van het systeem en dit wordt bereikt door substituten te gebruiken voor dingen waarvan de code onder de test afhankelijk is. Op die manier is het gemakkelijk om te zien waar het probleem optreedt wanneer een test mislukt. Unit-tests zijn meestal de snelste tests die moeten worden uitgevoerd en geen enkele code hoeft dingen te doen zoals een database raken of toegang krijgen tot het netwerk.

Eenheidstests moeten niet betrekking hebben op het verifiëren dat individuele componenten van het systeem goed samenwerken; dat is waar integratie testen komen.

Laag niveau integratietests kan omgaan met de interactie tussen twee of drie klassen, terwijl anderen kunnen controleren of die code goed werkt met externe bronnen, bijvoorbeeld een database of HTTP-server.

Systeemtests, waar deze tutorial in past, worden uitgevoerd tegen het hele, geïntegreerde systeem om te controleren of aan de vereisten van het hele systeem is voldaan. Systeemtests kunnen betrekking hebben op zaken als prestaties en schaalbaarheid, maar het soort tests waar we ons op zullen concentreren, heeft betrekking op de vraag of het systeem zich gedraagt ​​zoals de klant verwacht en implementeert de functies die ze hebben gespecificeerd. In Agile ontwikkelingskringen vallen deze tests in de categorie van acceptatietests.

De onderstaande voorbeeldcode doet dit soort testen. Deze tests vertellen ons of onze applicatie zich gedraagt ​​zoals we dat willen, vanuit het oogpunt van de gebruiker. We kunnen Selenium gebruiken om dergelijke tests te automatiseren omdat het een gebruiker kan simuleren die interactie heeft met het systeem (en het kan dit doen met echte webbrowsers, evenals headless-systemen zoals HtmlUnit).

Omdat we alleen geïnteresseerd zijn in wat het systeem doet, en niet hoe het doet het, we zullen bezig zijn met black-box testen. Het is ook vermeldenswaard dat, in tegenstelling tot de meeste andere soorten tests, acceptatietests moeten worden geschreven in samenwerking met klanten.


Niet nodig om te kiezen

Welke tests moet je gebruiken??

We kunnen Selenium gebruiken om tests te automatiseren omdat het een gebruiker kan simuleren die interactie heeft met het systeem

Taart is een soort voedsel, maar de meeste mensen (niet ikzelf) zouden adviseren het uitsluitend te eten; het complementeert eerder dan dat het andere voedsel vervangt. Het is belangrijk op te merken dat de verschillende soorten testen elkaar aanvullen in plaats van te concurreren. Zoals hierboven vermeld, dienen ze verschillende doeleinden. Elk van hen heeft voor- en nadelen en ze sluiten elkaar zeker niet uit.

Op systeemniveau, GUI-gestuurde tests zoals de onderstaande voorbeelden zijn meestal relatief traag om te worden uitgevoerd en bieden daarom geen snelle feedback. Dergelijke tests hebben ook de neiging broos te zijn en omdat ze zo veel van de applicatiecode raken, kan het opsporen van de oorzaak van een storing moeilijk zijn zonder een uitgebreide set unit- en integratietests. Het is zelfs een goed idee om veel meer unit-level tests te hebben dan het soort GUI-gebaseerde tests op systeemniveau waarvoor Selenium wordt gebruikt. Dat wil niet zeggen dat seleniumtests niet nuttig zijn! Het punt is dat geen enkele vorm van testen voldoende is.


Twee is beter dan een

We zullen Selenium 2 gebruiken. Meer specifiek gebruiken we WebDriver, een component van Selenium 2. WebDriver vervangt de Remote Control (RC) API van Selenium 1 en biedt een aantal voordelen ten opzichte van RC. Het is bijvoorbeeld beter om AJAX te testen en het heeft een schonere, meer objectgerichte, API. Het werkt ook op een compleet andere manier dan RC. In plaats van JavaScript te gebruiken voor interactie met een pagina, gebruikt WebDriver de browserautomatiseringsinterface die specifiek is voor elke browser. Het resultaat is dat het een echte gebruiker beter simuleert die interactief is met de te testen Website.

Een ander onderdeel van Selenium is IDE, een tool voor het opnemen en afspelen van bestanden en Firefox-plug-in. Het vereist geen kennis van programmeren en is nuttig voor verkennend testen.

De tests zijn meestal brosser dan RC- en WebDriver-scripts en een overduidelijk groot nadeel is dat het alleen in Firefox kan worden gebruikt. IDE is bedoeld als hulpmiddel voor prototypen en wordt niet aanbevolen voor serieuze tests.

WebDriver ondersteunt een breed scala aan browsers, waaronder Chrome, IE, iOS en Android. Later zullen we kijken naar het gebruik van cloudtestservices zodat tests kunnen worden uitgevoerd tegen combinaties van browserbesturingssystemen waarvoor u mogelijk geen toegang hebt.

Hier wordt WebDriver gebruikt met Python, maar een aantal taalbindingen zijn beschikbaar, waaronder die voor Java, C # en PHP. Als je onbekend bent met Python, vrees niet, dan zou je nog steeds in staat moeten zijn om de voorbeelden te volgen zoals het luidt, net als pseudo-code.

Python ... lijkt veel op pseudo-code

Er zijn een aantal andere interfaces beschikbaar, maar de twee belangrijkste onderdelen van de WebDriver API die we nodig hebben, zijn WebDrive en WebElement. Elk voorbeeld hieronder werkt met een WebDrive object, dat overeenkomt met de browser, en een of meer objecten van het type WebElement, die elementen op een pagina vertegenwoordigen.

De methoden voor het lokaliseren van elementen op een pagina (die later worden besproken) zijn gebruikelijk tussen deze twee interfaces. Aan de andere kant, methoden zoals TAG_NAME zijn alleen beschikbaar op WebElement. Evenzo is het logisch voor methoden zoals get_cookies en verversen beschikbaar zijn op WebDrive maar niet aan WebElement, en dit is inderdaad het geval.

Het is interessant om op te merken dat er een inspanning is om van WebDriver een W3C-standaard te maken.


Grijp wat je nodig hebt

Momenteel ondersteunt Selenium 2 Python 2.6 en Python 2.7, dus installeer een van deze als dit nodig is. Om erachter te komen welke versie je hebt, op het commandoregeltype python -V. Linux- en Mac-gebruikers hebben normaal gesproken al Python, maar moeten voorzichtig zijn bij het upgraden van hun versie van Python omdat het besturingssysteem mogelijk afhankelijk is van de versie van het besturingssysteem..

Als je Python 2.6 of 2.7 hebt, is pip de beste manier om pakketten te installeren. Zodra je pip hebt, installeer je het Selenium 2-type: pip install -U selenium. (-U zal elke vorige versie upgraden die u mogelijk heeft. Linux- en Mac-gebruikers hebben dit misschien nodig sudo).

Om pip op Windows te krijgen, bekijk je deze Stack Overflow-vraag.

We zullen ook Firefox gebruiken, want dat is de browser die direct met WebDriver werkt.


Je raadt het nooit

We hebben een webtoepassing nodig om te testen en we zullen een eenvoudig aantal raadsspelletjes gebruiken. Het is een bewust eenvoudig programma. Een webtoepassing wordt vaak getest op de computer van een ontwikkelaar met behulp van een lokaal uitgevoerde webserver voor ontwikkeling, omdat dit handig is om te testen voordat deze wordt geïmplementeerd. In dit geval voeren we echter tests uit tegen een geïmplementeerde web-app: http://whats-my-number.appspot.com. Dit zal de applicatie zijn die getest wordt (AUT). (In het geval dat deze site niet beschikbaar is, probeer dan http://whats-my-number-backup.appspot.com/).

Het antwoord (sorry om het plezier te verpesten) is 42.

Wat de gebruiker ook inbrengt, er moet een hint worden weergegeven. Het programma verwacht hele getallen van 0 tot 100 (inclusief) en als de gebruiker een waarde invoert die niet voldoet aan deze regel, moet de hint over deze vereiste adviseren. Wanneer de gebruiker een geheel getal probeert te raden van 0 tot 100, is de hint "te laag" of "te hoog". Wanneer 42 is ingevoerd, moet "Gefeliciteerd" de hint worden weergegeven.

Iets wat we eerder hebben aangeroerd, is het idee dat een geweldige manier om expliciet te zijn over hoe een systeem zich zou moeten gedragen is om tests te schrijven, en latere voorbeelden zullen een tamelijk uitgebreide reeks tests omvatten die het beoogde gedrag van het systeem zullen communiceren. We zullen een vorm van uitvoerbare documentatie hebben.

We zullen een vorm van uitvoerbare documentatie hebben

Een van de geweldige dingen over een taal als Python is dat je een interactieve tolk kunt gebruiken. Als u de interactieve Python-interpreter wilt uitvoeren, typt u gewoon Python op de opdrachtregel en je zou de prompt moeten zien (>>>). Als alternatief kunt u een scriptbestand gebruiken om te gebruiken python script_name.py

Het is niet de manier waarop de testcode gewoonlijk wordt uitgevoerd, maar wanneer u net begint met browserautomatisering, kan het handig zijn om de interactieve interpreter te gebruiken en een regel Python tegelijk in te voeren. Op deze manier is het gemakkelijker om een ​​idee te krijgen van hoe WebDriver de browser bestuurt en een echte gebruiker simuleert. Hoewel u in plaats daarvan een scriptbestand kunt uitvoeren en achterover kunt leunen terwijl Selenium zijn ding doet, werkt het veel sneller dan met een menselijke gebruiker, dus het uitvoeren van opdrachten met één regel tegelijk maakt het gemakkelijker om een ​​goede waardering te krijgen voor wat de opdrachten die je aan het uitbrengen bent, zijn echt aan het doen. Het is een geweldige manier om te leren en te experimenteren.


Kunnen we nu echt wat testen doen??

Typ de volgende regels code bij de prompt van de interpreter en druk na elk op Enter. De eerste stap is om een ​​import uit te voeren:

van selenium import webdriver

Vervolgens openen we een browservenster en bezoeken we de AUT:

browser = webdriver.Firefox () browser.get ('http://whats-my-number.appspot.com/')

Nu gaan we iets doen dat dit een test maakt. Python's ingebouwd beweren verklaring kan worden gebruikt om te controleren of iets waar is, en in dit geval gebruiken we het om te controleren of de paginatitel "Wat is mijn nummer" is. Dit kan een inhoudstest worden genoemd:

beweer 'What \' s My Number? ' == browser.title

Omdat de paginatitel correct is, geeft Python ons gewoon een nieuwe prompt. De titel die onjuist is zou hebben betekend beweren gooien met een AssertionError. Een AssertionError tijdens het uitvoeren van een scriptbestand loopt het programma vast (wat handig is).

Het volgende deel van onze test is wat de Selenium-documentatie een functietest noemt. We willen verifiëren dat wanneer 1 wordt ingevoerd als een schatting, het programma antwoordt met inhoud die een hint bevat waarin staat dat de schatting te laag is. Latere voorbeelden behandelen meerdere invoer van gebruikers.

Om dit te doen, moeten we het formulier invullen. Als je naar de HTML van de raadspelletjespagina kijkt, zie je dat het tekstinvoerveld a heeft naam attribuut met de waarde van 'raden'. Dit kan worden gebruikt om een WebElement object om het invoerveld te representeren:

guess_field = browser.find_element_by_name ('guess')

We kunnen nu de gok typen. WebElement heeft een send_keys methode:

guess_field.send_keys (1)

We kunnen de submit-knop vinden en erop klikken, of de geleverde gebruiken voorleggen methode, maar in plaats daarvan drukken we op de Return-toets:

van selenium.webdriver.common.keys import Keys guess_field.send_keys (Keys.RETURN)

Het formulier wordt verzonden en de pagina wordt opnieuw geladen (AJAX is niet in gebruik) en aangezien de schatting te laag is, moet "Je gissing is te laag" ergens in het hoofdgedeelte van het document worden weergegeven. Om dit als eerste te verifiëren, hebben we een WebElement object dat de HTML vertegenwoordigt lichaam:

body = browser.find_element_by_tag_name ('body')

De tekst eigendom van WebElement zal in dit geval de tekst van de pagina onthullen. Laten we daar gebruik van maken in een beweren uitspraak:

beweer 'Uw schatting is te laag' in body.text

Nogmaals, succes, dus Python geeft ons gewoon nog een prompt. Omdat dit een onjuiste schatting is, is 'Gefeliciteerd' nergens te bekennen:

beweer 'Gefeliciteerd' niet in body.text

Ten slotte sluiten we het exemplaar van Firefox dat we hebben gebruikt:

browser.quit ()

Doelwit acquisitie

Als u bekend bent met programmeren met JavaScript en de DOM, weet u dat u verwijzingen naar DOM-elementen op een webpagina moet krijgen en zoals we hebben gezien, moeten we hier iets soortgelijks doen. De twee situaties zijn echter niet precies hetzelfde, want in plaats van een verwijzing naar een DOM-element te krijgen, krijgen we een WebElement object dat overeenkomt met een DOM-element.

Hierboven hebben we gebruikt find_element_by_name, wat handig is voor vormelementen, evenals find_element_by_tag_name. Andere locator-methoden omvatten find_element_by_id en find_element_by_css_selector. Zie de Selenium-documentatie voor de volledige lijst.

Performance-wise, met behulp van een element ID of naam locator (zoals we hierboven deden) is de beste manier om een ​​element te selecteren. Natuurlijk, zodra we een hebben WebElement een object dat overeenkomt met het gewenste DOM-element, dat u op een of andere manier wilt gebruiken, zoals hier send_keys en Klik zijn handig.


Bros kunnen gevaarlijk zijn

Brosse testen zijn gevaarlijk omdat, als testen soms falen terwijl ze in feite voorbij zouden moeten gaan, je de testresultaten negeert en het hele testproces wordt gedevalueerd.

In het downloadbare zipbestand bij deze zelfstudie, ftests1.py geeft de bovenstaande voorbeeldtestcode weer in de vorm van een scriptbestand. Er is echter een omissie: u kunt merken dat de oproep naar implicitly_wait, inbegrepen ftests1.py, werd niet vermeld of besproken.

Als je tien keer een test tegen een systeem uitvoert, zou het je tien keer hetzelfde resultaat moeten geven. Breekbare en onbetrouwbare tests zoals wij doen zijn echter vrij gewoon en u kunt dit probleem tegenkomen als u experimenteert met Selenium-testen. Brosse testen zijn gevaarlijk omdat, als testen soms falen terwijl ze in feite voorbij zouden moeten gaan, je de testresultaten negeert en het hele testproces wordt gedevalueerd. impliciet_wachten is een zeer nuttig hulpmiddel bij het bestrijden van brosse testen en vanaf dit punt is er een oproep voor implicitly_wait wordt in alle voorbeeldcodes gebruikt.


Ik dacht dat je zei dat we geen unit-testen zijn

Als een testgeïnfecteerde ontwikkelaar, wil je meer weten over de xUnit-tools. Ze zijn beschikbaar voor veel programmeertalen. unittest is een hulpmiddel voor xUnit dat standaard bij Python wordt geleverd. Het lijkt misschien verwarrend, maar hoewel we geen unit tests schrijven, is unittest nuttig. Unittest helpt bijvoorbeeld bij het structureren en uitvoeren van tests en testfouten leiden tot nuttiger berichten.

De versie van unittest in Python 2.7 heeft extra functies in vergelijking met oudere versies (waarvan we sommige zullen gebruiken), dus als je Python 2.6 gebruikt, moet je de backport installeren: pip installeer unittest2

De onderstaande code is de meest onverwachte versie van de eerder gepresenteerde testcode.

Net als voorheen wordt de titel van het browservenster gecontroleerd, 1 wordt geprobeerd als een gok en wordt het antwoord van het programma gecontroleerd:

probeer: import unittest2 als unittest #voor Python 2.6 behalve ImportError: import unittest van selenium import webdriver van selenium.webdriver.common.keys import Keys klasse GuessTest (unittest.TestCase): def setUp (self): self.browser = webdriver.Firefox () self.browser.implicitly_wait (3) def tearDown (self): self.browser.quit () def test_should_see_page_title (self): # Brian bezoekt de raadselspel-website self.browser.get ('http: // whats-my -nummer.appspot.com/ ') # Hij ziet dat "Wat is mijn nummer?" is de titel van de pagina self.assertEqual ('What \' s My Number? ', self.browser.title) def test_should_get_correct_hint_from_guess_too_low (self): # Brian bezoekt de website van de raadsspel self.browser.get (' http: // whats-my-number.appspot.com/ ') # Hij typt zijn schatting in het formulierveld en drukt op de return-toets guess_field = self.browser.find_element_by_name (' guess ') guess_field.send_keys (' 1 ') guess_field.send_keys ( Keys.RETURN) # De pagina is opnieuw geladen en omdat de schatting te laag is, wordt # 'Je gissing is te laag' body = self.browser.find_element_by_tag_name ('body') self.assertIn ('Je gok is te laag' , body.text) # Omdat dit een onjuiste schatting is, is 'Gefeliciteerd' nergens te zien self.assertNotIn ('Congratulations', body.text) if __name__ == '__main__': unittest.main ()

Hersenen is de naam van onze "robotgebruiker". Zie ook ftests2.py in het zipbestand bij deze zelfstudie.

De individuele tests zijn methoden van de klas GuessTest, welke erft van unittest.TestCase. Voor meer van een idee over het zelf trefwoord en andere objectgeoriënteerde aspecten van Python zien de Nettuts-sessie op Python. De namen van testmethoden moeten met de letters beginnen test. Het is essentieel om de namen van de methoden beschrijvend te maken.

Natuurlijk een beweren is essentieel voor elke test, maar in feite in plaats van het gebruik van de beweren verklaring als voorheen hebben we toegang tot de assert-methoden van unittest. In dit geval assertEqual, assertIn en assertNotIn worden gebruikt.

De opstelling en scheuren methoden worden uitgevoerd voor en na elk van de testmethoden, en hier gebruiken we ze om een ​​WebDriver-browserinstantie op te starten en af ​​te sluiten.

Het laatste blok, if __name__ == '__main__': unittest.main (), staat dit unittest-script toe om te worden uitgevoerd vanaf de opdrachtregel. Om het script uit te voeren, gaat u naar de map met ftests2.py en typ: python ftests2.py. Doen zou moeten resulteren in uitvoer zoals deze:

Idealiter zouden tests "luidruchtig" moeten uitvallen maar "rustig" moeten verlopen, en zoals je kunt zien, is dat precies wat de meest ongeschikte persoon doet: er wordt slechts een periode afgedrukt voor elke testmethode die voorbijgaat. Ten slotte zien we een welkom "OK" (zou het niet "goed gedaan" moeten zijn?).

Zoals je ziet, wordt het "Do not Repeat Yourself" -principe geschonden, omdat de URL van de AUT tweemaal in de code voorkomt. Grondig testen maakt het mogelijk om de toepassingscode te refactoren, maar vergeet ook niet de testcode te refactoren.


Raad nogmaals

Tot nu toe hebben onze tests slechts één gissing gedaan: 1, en dit is duidelijk niet erg uitgebreid. Het volgende script zal hier iets aan doen, zie ftests3.py in het zipbestand.

De importeren verklaringen, klassenverklaring, opstelling en scheuren methoden, en de if __name__ == '__main__': blok, zijn allemaal exact hetzelfde als het laatste voorbeeld. Laten we ons concentreren op de dingen die anders zijn.

Omdat dit iets is dat we herhaaldelijk zullen doen, is het invullen van het formulier in een eigen helper-methode gezet, genaamd _enter_guess_hit_return:

def _enter_guess_hit_return (self, guess): guess_field = self.browser.find_element_by_name ('guess') guess_field.send_keys (guess) guess_field.send_keys (Keys.RETURN)

Een andere hulpmethode, _unsuccessful_guess, gaat over het bezoeken van de AUT, bellen _enter_guess_hit_return, en de assert-methoden aanroepen. Nogmaals, onze robotgebruiker zou een naam kunnen gebruiken, laten we dit deze keer als Bertie omschrijven.

def _unsuccessful_guess (self, berties_guesses, expected_msg): self.browser.get ('http://whats-my-number.appspot.com/') voor berties_guess in berties_guesses: self._enter_guess_hit_return (berties_guess) body = self.browser. find_element_by_tag_name ('body') self.assertIn (expected_msg, body.text) self.assertNotIn ('Congratulations', body.text)

Misschien merk je dat bellen _enter_guess_hit_return en het uitvoeren van de beweringen gebeurt in een lus. Dit komt omdat we doorlussen berties_guesses, wat een lijst is. berties_guesses wordt doorgegeven aan deze methode door de aanroepende testmethoden, die ook in een verwacht bericht zullen worden doorgegeven, expected_msg.

Om nu gebruik te maken van onze helpers bij de testmethoden:

def test_should_get_correct_hint_from_guess_too_low (self): berties_guesses = ['0', '01', '17', '23', '041'] expected_msg = 'Je schatting is te laag' self._unsuccessful_guess (berties_guesses, expected_msg) def test_should_get_correct_hint_from_guess_too_high (self ): berties_guesses = ['43', '80', '100'] expected_msg = 'Uw schatting is te hoog' self._unsuccessful_guess (berties_guesses, expected_msg) def test_should_get_correct_hint_from_invalid_input (self): berties_guesses = ['a', '5a' , 'c7', '1.2', '9.9778', '-1', '-10', '101', 'hkfjdhkacoe'] expected_msg = 'Geef een geheel getal op van 0 tot 100' self._unsuccessful_guess (berties_guesses, expected_msg)

Voor beknoptheid is het controleren van de paginatitel achterwege gelaten. Natuurlijk moet er een methode zijn om te verifiëren dat wanneer de juiste schatting wordt gegeven, "Gefeliciteerd" inderdaad wordt weergegeven en je wordt uitgenodigd om deze methode te schrijven (het zal leuk zijn, dat beloof ik!).


Oeps, ik drukte op de rode knop

Het laatste voorbeeldscript geeft ons een goed vertrouwen dat de AUT naar behoren functioneert. Maar stel dat de code van de applicatie nu moet veranderen. De klant wil bijvoorbeeld een nieuwe functie, of we willen refactoren, of misschien hebben unit- of integratietests een fout ontdekt die tests op systeemniveau niet hebben onthuld (en we willen nu die fout herstellen). Tijdens het proces van het wijzigen van de code moeten bestaande tests vaak worden uitgevoerd, zodat problemen eerder eerder dan later opduiken.

Laten we een wijziging van de applicatiecode simuleren. Een aangepaste versie van het spel is op http://whats-my-number-broken.appspot.com en als je rent ftests3.py tegen deze versie zie je een testfout:

test_should_get_correct_hint_from_guess_too_high faalt. Uit de test blijkt dat bij het wijzigen van de code van de toepassing een regressie is geïntroduceerd. We voeren de tests regelmatig uit, en we hoeven alleen maar te kijken naar de wijzigingen die zijn aangebracht sinds de tests het laatst werden uitgevoerd om het probleem te beperken. Op deze manier hebben schrijftests ons beloond met een gevoel van vertrouwen, in tegenstelling tot een gevoel van angst.


"Het werkt op mijn machine"

Van webtoepassingen wordt doorgaans verwacht dat ze goed werken in een groot aantal verschillende browsers, dus het is normaal om met zoveel browsers te testen op zoveel platforms als waarop je kunt komen. Wanneer een probleem met een systeem wordt ontdekt, is het niet ongebruikelijk om een ​​ontwikkelaar te horen zeggen: "Wel, het werkt op mijn machine". Dit komt vaak neer op: "We hebben het niet goed getest". In het geval van een nummer raadspel vraag je je misschien af ​​of cross-browser testen wel nodig is, maar het is natuurlijk een bewust eenvoudig systeem.

Op cloud gebaseerde services zoals Sauce Labs kunnen hierbij helpen. Sauce Labs biedt een verscheidenheid aan browser-OS-combinaties. Een andere service is Testingbot, die testen op mobiele platforms biedt.

Zoals u hebt gezien, voeren we tests uit tegen een openbaar toegankelijke site, maar voor sites die nog in ontwikkeling zijn en intranetsites, biedt Sauce Labs Sauce Connect en Testingbot-aanbiedingen Tunnel.

De codevoorbeelden tot nu toe zijn hard gecodeerd om Firefox te gebruiken. ftests3_remote.py, beschikbaar in het zipbestand, is een verbeterde versie van ftests3.py die gemakkelijk kan worden geconfigureerd om te worden uitgevoerd met een bepaalde browser-OS-combinatie (binnen de grenzen van wat wordt aangeboden door welke cloudtestservice die we gebruiken). Het platform, de browser en de browserversie worden opgegeven op de opdrachtregel wanneer het script wordt uitgevoerd.

De codevoorbeelden tot nu toe zijn hard gecodeerd om Firefox te gebruiken

U moet zich aanmelden voor een service zoals Sauce Labs of TestingBot om een ​​API-sleutel te verkrijgen en de opstelling methode (zoals weergegeven in het bestand) om deze sleutel op te nemen. Beide diensten kunnen zonder kosten worden geprobeerd.

ftests3_remote.py verwacht het platform als het eerste argument van de opdrachtregel, de naam van de vereiste browser als tweede en de browserversie wordt als laatste verwacht. Met verwijzing naar de beschikbare browser-OS-combinaties van Sauce Lab kunnen we het script bijvoorbeeld als volgt uitvoeren:

python ftests3_remote.py LINUX chrome
 

In het specifieke geval van Chrome moet geen versienummer worden opgegeven. Om Internet Explorer te gebruiken, omdat de browsernaam uit twee woorden bestaat, moeten aanhalingstekens worden gebruikt. Laten we als voorbeeld de testen uitvoeren met onze oude vriend, IE6:

python ftests3_remote.py XP 'internet explorer' 6
 

Testresultaten worden naar de terminal uitgevoerd alsof u de tests op uw eigen computer uitvoert. U kunt echter verwachten dat dit script langzamer wordt uitgevoerd dan testscripts uit voorgaande voorbeelden. Interessant is dat je met Sauce Labs een video kunt bekijken van elke test die wordt uitgevoerd zodra deze is voltooid.

Een shellscript kan eenvoudig worden gemaakt om te word