Unit Testing og validering

Skip to content

Nå som vi har laget classes og arbeidet med validering, har vi et godt grunnlag for å begynne med testing. Testing er en viktig del av utviklingsprosessen, og det hjelper oss med å sikre at koden vår fungerer som forventet.

For hvordan kan vi være sikre på at koden fungerer som den skal, hvis vi ikke tester den?

Hva er Unit Testing?

Unit Testing er en metode for å automatisk og systematisk teste små deler av koden vår. I Python bruker vi en modul som heter pytest for å skrive og kjøre tester. En “unit” er den minste testbare delen av en applikasjon, ofte en enkelt funksjon eller metode. Når vi bruker pytest er det viktig at vi følger riktige navnekonvensjoner for at pytest skal kunne finne testene våre, slik som å navngi testfiler med test_ foran, og testfunksjoner med test_ foran.

Eksempel på en unit test:

def test_add():
    assert 0.3 + 0.3 + 0.3 == 0.9

Kjøres ved å skrive pytest i terminalen.

Fun fact

Koden over vil feile, fordi .3+.3+.3 blir til 0.8999999999 i Python!

Easy Oppgave 1 - Installer pytest

Installer pytest i ditt virtuelle miljø. Dette gjør du ved å kjøre følgende kommando i terminalen:

pip install pytest

Easy Oppgave 2 - Lag en test

Lag en ny fil i prosjektmappen din som heter test_data.py. I denne filen skal du lage en test for Person klassen du lagde i forrige modul. Testen skal sjekke at en Person kan opprettes med gyldige verdier.

Eksempel på hvordan testen kan se ut:

from main import Person

def test_person_working():
    bob_kaare = Person(name="Bob Kåre",
                       eye_color=EyeColor.BLUE,
                       phone_number=PhoneNumber("12345678"),
                       email=Email("bob_kaare@example.com"))
    assert bob_kaare.name == "Bob Kåre"
    assert bob_kaare.eye_color == EyeColor.BLUE

Denne type testing er kalt “happy path” testing, fordi vi tester at alt fungerer som det skal når vi gir gyldige verdier, og er ikke særlig nyttig.

Medium Oppgave 3 - Test validering

Lag flere tester i test_person.py som sjekker at valideringen i Email og PhoneNumber fungerer som den skal. Test både gyldige og ugyldige verdier. Her må du bruke en funksjon i pytest som heter raises, som sjekker at en bestemt feil blir kastet.

import pytest

def test_exception():
    with pytest.raises(KeyError):
        my_dict = {"a": 1, "b": 2}
        value = my_dict["c"]  # Dette vil "raise" en KeyError

Tip

Du kan lage så mange funksjoner du vil, så lenge funksjonsnavnet begynner med test_.

Løsning: Eksempel på en test for ugyldig e-post
from main import Email

import pytest

def test_invalid_email():
    with pytest.raises(ValueError):
        email = Email("not-an-email")

Hvorfor gjøre dette?

Ved å ha gode tester for koden vår så kan vi være sikre på at den fungerer som den skal, og vi kan enkelt finne ut om noe har gått galt hvis vi gjør endringer i koden. Dette er spesielt viktig i større prosjekter, der mange utviklere jobber sammen, og det er lett å gjøre feil.

Ved å for eksempel bruke programvare som Jest eller Selenium kan man teste nettsider automatisk, og dermed sørge for at alt fungerer som det skal etter hver endring i koden. Vi vil jo gjerne vite at “brukerregistrering”, “betaling” og “innlogging” fungerer som det skal, ikke sant?

Tenk over følgende scenarioer

Hva skjer (eller skal skje) hvis..:

  • En bruker prøver å registrere seg med en e-post som allerede er i bruk?
  • En bruker har fødselsdato i fremtiden?
  • En bruker som skriver inn navnet “jOHN dOE”?

A software tester walks into a bar...

Hard Oppgave 4 - Automatisk Testing (CI)

Når vi publiserer kode på GitHub, så kan vi sette opp noe som heter GitHub Actions som kan kjøre testene våre automatisk hver gang vi gjør en endring i koden. Dette kalles Continuous Integration (CI), og det hjelper oss med å sikre at koden vår alltid fungerer som den skal.

Lag en fil i prosjektmappen din som heter .github/workflows/pytest.yml. I denne filen skal du legge til følgende kode:

name: Pytest

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.11'
    - name: Install dependencies
      run: |

        python -m pip install --upgrade pip
        pip install pytest
        # Install any other dependencies your project needs
        pip install -r requirements.txt
    - name: Run tests with pytest
      run: pytest

Dersom du har lagt den inn riktig, vil du nå se en ny fane i GitHub-repoet ditt som heter “Actions”. Her vil du kunne se at testene dine blir kjørt automatisk hver gang du gjør en endring i koden, og du vil få beskjed dersom noen av testene feiler (rødt kryss og via e-post).

Merknad om filstruktur

Filstrukturen din vil avgjøre om GitHub Actions fungerer eller ikke. Sørg for at .github mappen ligger i rotmappen av prosjektet ditt, og det samme gjør en tests mappe hvor testfilene dine ligger.

Du kan eventuelt endre på pytest.yml filen for å peke til riktig mappe.

Slike Actions filer kan også brukes til å teste koden din på flere versjoner av Python eller operativsystemer, de kan også brukes til å bygge og publisere programvaren din automatisk, f.eks. publisere en nettside, eller oppdatere en app i App Store eller Google Play.

Code Coverage

Det finnes også noe som heter “Code Coverage”, som kan hjelpe deg med å se hvor mye av koden din som faktisk blir testet. Dette kan være nyttig for å finne ut om du har nok tester, eller om det er deler av koden din som ikke blir testet i det hele tatt.

Enkelte arbeidsplasser krever at du har en viss prosentandel av koden din dekket av tester før du kan deploye den, for å sikre at koden er robust og fungerer som den skal.

Unit Test Meme