Robot Framework on user storyjen hyväksymistestauksen automatisointiin hyvin soveltuva sovelluskehys. Robot Frameworkin avulla user storyjen testit voidaan kirjoittaa asiakkaan ymmärtämässä muodossa, luonnollisella kielellä, mutta tehdä niistä kuitenkin automaattisesti suoritettavia.

Vaikka Robot Framework on perinteisesti tarkoitettu koko ohjelmiston “end-to-end”-testaukseen, tarkastellaan ensin Robot Frameworkin toimintaperiaatteita testaamalla yksittäistä luokkaa. Hae kurssirepositorion hakemistossa koodi/viikko3/hello-robot oleva projekti.

  • Kopioi projekti palatusrepositorioosi, hakemiston viikko3 sisälle.

Testattavana on yksinkertainen laskuri:

class Counter:
    def __init__(self, initial_value=0):
        self.initial_value = initial_value
        self.value = initial_value

    def increase(self):
        self.value = self.value + 1

    def increment(self, amount):
        self.value = self.value + amount

    def decrease(self):
        self.value = self.value - 1

    def reset(self):
        self.value = self.initial_value

Laskurille on toteutettu Robot Frameworkin avulla muutama testi src/tests-hakemiston increase_counter.robot-tiedostoon. Tutustu tiedoston sisältöön ja pohdi, vaatiiko testattavien skenaarioiden ymmärtäminen lukijalta erityistä teknistä osaamista esimerkiksi unittest-testeihin verrattuna.

Robot Frameworkin käyttö onnistuu Pythonilla robotframework-kirjaston avulla, joka on määritelty projektin riippuvuudeksi. Ota projekti käyttöön asentamalla sen riippuvuudet komennolla poetry install. Suorita tämän jälkeen testit siirtymällä virtuaaliympäristöön komennolla poetry shell ja suorittamalla siellä komento robot src/tests.

Testien suorittamisen jälkeen komentoriville ilmestyy lyhyt raportti testien suorituksesta. Tämän raportin lisäksi projektin juurihakemiston report.html-tiedostoon ilmestyy yksityiskohtaisempi, HTML-muotoinen raportti. Klikkailemalla raporttia, avautuu mukava testien suorituksen statusta kuvaava näkymä:

Vaatimuksien ilmaiseminen

Laskurin haluttua toiminnallisuutta kuvaavat seuraavat user storyt

  • As a user I want to be able to increase the counter value
  • As a user I want to be able to set the counter to value zero

Robot Framework testaamisen ytimessä on niin kutsutut avainsanat (keywords). Avainsana on selkokielinen selitys tehtävästä asiasta. Esimerkiksi laskurin testaamisen kannalta yksi erittäin oleellinen avainsana on Increase Counter, jonka avulla laskurin arvoa voidaan kasvattaa. Avainsanoilla voi olla myös argumentteja (arguments), jotka tekevät niistä uudelleenkäytettäviä. Argumenteilla varustettu avainsana voisi olla esimerkiksi Counter Value Should Be, joka tarkistaa, että laskurin arvo vastaa argumentin arvoa.

Avainsanoja hyödyntävät niin kutsutut testitapaukset (test cases), jotka ovat itse testejä. Testitapauksilla on nimi (kuten avainsanoilla) ja ne suorittavat avainsanoja tietyssä järjestyksessä. Esimerkiksi testitapaus laskurin kasvattamiselle voisi olla seuraava:

*** Test Cases ***
Increase Counter Once
    Counter Value Should Be  0
    Increase Counter
    Counter Value Should Be  1

Testitapaus koostuu nyt kolmesta avainsanasta. Ensin tarkistetaan että laskurin arvo on aluksi nolla, tämän jälkeen kasvatetaan laskuria ja lopuksi vielä varmistetaan että laskurin arvo on yksi.

Testitapaukset listataan *** Test Cases ***-osion alle. Avainsanojen ja testitapausten nimet kirjoitetaan yleensä suurilla alkukirjaimilla niin, että sanojen välissä on yksi välilyönti. Argumenttien väliin tulee jättää vähintään kaksi välilyöntiä (esimerkiksi Counter Value Should Be  0). Jotta syntaksivirheet huomaisi helposti, kannattaa Visual Studio Codeen asentaa sopiva lisäosa, esim. Robot Framework Language Server tai RobotCode:

Testien suorituskelpoiseksi tekeminen

Avainsanojen, kuten Increase Counter taustalla on avainsanan tekninen toteutus. Nämä toteutukset tuottavat niin kutsutut kirjastot (libraries). hello-robot-projektin src-hakemistosta löytyy tiedosto CounterLibrary.py. Tiedosto määrittelee luokan CounterLibrary:

from counter import Counter

class CounterLibrary:
    def __init__(self):
        self._counter = Counter()

    def increase_counter(self):
        self._counter.increase()

    def increment_counter_by(self, amount):
        int_amount = int(amount)
        self._counter.increment(int_amount)

    def counter_value_should_be(self, expected):
        int_expected = int(expected)
        if self._counter.value != int_expected:
            raise AssertionError(f"{self._counter.value} != {int_expected}")

Kyseisen luokan metodit ovat avainsanojen toteutuksia. Esimerkiksi metodi increase_counter toteuttaa avainsanan Increase Counter (huomaa, ettei avainsanan väliin tule alaviivaa, vaan se korvaantuu välilyönnillä). Luokan konstruktorissa alustetaan uusi Counter-luokan olio, jonka metodeja luokan metodit kutsuvat.

Robot Framework alustaa kirjastot ennen jokaista testitapausta, joten jokaisella testitapauksella on käytössään kirjastosta oma instanssi. Tämä mahdollistaa mm. sen, että jokaista projektin testitapausta varten alustetaan CounterLibrary-luokan konstruktorin kautta uusi Counter-olio.

Metodi increment_counter_by toteuttaa avainsana Increment Counter By, jolla on yksi argumentti, amount. Argumenttien arvot ovat aina merkkijonoja, joten ne täytyy tarvittaessa muuttaa oikean tyyppisiksi, kuten metodi tekee int-funktion avulla:

def increment_counter_by(self, amount):
    int_amount = int(amount)
    self._counter.increment(int_amount)

Huomaa, että kaikki metodit, joiden nimessä ei ole _-etuliitettä muodostavat avainsanan toteutuksen. Jos haluat tehdä kirjastoon metodin, josta et halua avainsanaa, nimeä se _-etuliitteellä:

from counter import Counter

class CounterLibrary:
    def __init__(self):
        self._counter = Counter()

    def _some_helper_method(self):
        pass

    # ...

Jotta kirjaston tarjoamia avainsanoja voi käyttää testitiedostossa, se täytyy erikseen tuoda käyttöön. Tämä onnistuu Settings-osiossa:

*** Settings ***
Library  ../CounterLibrary.py

*** Test Cases ***
Increase Counter Once
    Counter Value Should Be  0
    Increase Counter
    Counter Value Should Be  1

Huomaa, että kirjaston polku on suhteellinen tiedostoon nähden.

Tiedostoon voi tuoda myös useamman kirjaston lisäämällä monta Library-riviä:

*** Settings ***
Library  ../CounterLibrary.py
Library  ../SomeUsefulLibrary.py

Avainsanojen yhdistely

Kirjastojen lisäksi avainsanoja voi määritellä myös .robot-tiedostoissa. Tämä onnistuu määrittelemällä uusi avainsana *** Keywords ***-osion alle. Voimme esimerkiksi hyödyntää avainsanaa Increase Counter ja toteuttaa avainsanan Increase Counter Three Times, joka kasvattaa laskurin arvoa kolmesti:

*** Settings ***
Library  ../CounterLibrary.py

*** Keywords ***
Increase Counter Three Times
    Increase Counter
    Increase Counter
    Increase Counter

Resurssit

Testihakemiston increase_counter.robot-tiedoston *** Settings ***-osiosta löytyy rivi Resource resource.robot. Mistä on kyse?

Useammissa testeissä uudelleenkäytettävät avainsanat ja asetukset kannattaa siirtää omiin tiedostoihinsa, joita kutsutaan resursseiksi (resource). Resurssitiedostot voi tuoda muiden tiedostojen käyttöön Resource-asetuksen kautta:

*** Settings ***
Resource  resource.robot

Huomaa, että resurssin polku on relatiivinen tiedostoon nähden.

Tiedostoon voi tuoda useamman resurssin lisäämällä monta Resource-riviä.

Nollaamisen skenaariot

Lisää src/tests-hakemistoon tiedosto reset_counter.robot, joka sisältää laskimen nollaamiseen liittyvät hyväksymistestit.

Lisää tiedostoon seuraavat testitapaukset:

*** Settings ***
Resource  resource.robot

*** Test Cases ***
Reset Counter After One Increment
    Counter Value Should Be  0
    Increase Counter
    Counter Value Should Be  1
    Reset Counter
    Counter Value Should Be  0

Reset Counter After Several Increments
    Counter Value Should Be  0
    Increment Counter By  5
    Counter Value Should Be  5
    Reset Counter
    Counter Value Should Be  0

Siirry virtuaaliympäristöön komennolla poetry shell ja suorita siellä komento robot src/tests. Testit eivät mene läpi ja tulosteessa on seuraava virhe:

No keyword with name 'Reset Counter' found.

Robot Framework siis ilmoittaa, ettei avainsanalle Reset Counter ole toteutusta.

Toteuta seuraavaksi CounterLibrary-luokkaan sopiva metodi, jotta testit menevät läpi.

Typoja materiaalissa

Tee korjausehdotus editoimalla tätä tiedostoa GitHubissa.