PythonPodcast 43 - itnett/FTD02H-N GitHub Wiki

Python Mentorkurs – Episode 8: Testing og Feilsøking av Python-kode

Mentor: "Velkommen tilbake! I forrige episode lærte vi om sikkerhet i Python-programmering, noe som er essensielt for å lage trygge og pålitelige applikasjoner. I dag skal vi se nærmere på en annen viktig del av programmeringsprosessen – testing og feilsøking. Dette er verktøyene som sikrer at koden din fungerer som forventet, og hjelper deg med å finne feil før applikasjonen går i produksjon. Testing gjør at vi kan være sikre på at vi leverer kvalitet. La oss starte med å forstå hva testing er og hvorfor det er viktig."


Hva er Testing i Programmering?

Mentor: "Testing handler om å verifisere at programmet ditt oppfører seg slik du forventer. Målet med testing er å oppdage feil før brukerne gjør det. Det finnes ulike typer testing, men vi skal fokusere på en spesifikk form som kalles 'enhetstesting' (unit testing). Enhetstesting innebærer å teste de små delene av programmet ditt – funksjoner og metoder – isolert fra resten av systemet."


Hvorfor er Testing Viktig?

Mentor: "Tenk deg at du bygger et hus. Du vil sjekke at hver del av huset, som fundamentet, veggene, og taket, er riktig før du fortsetter. På samme måte vil du teste hver del av koden din før du kombinerer dem til et fullt program. Hvis du ikke tester koden din, kan små feil utvikle seg til store problemer når programmet kjører i et produksjonsmiljø."


Enhetstesting med unittest

Mentor: "I Python har vi et innebygd bibliotek kalt unittest, som lar oss skrive og kjøre tester på en enkel måte. La oss se på et eksempel."

import unittest

Funksjon vi vil teste

def legg_til(a, b): return a + b

Testklasse

class TestLeggTil(unittest.TestCase):

def test_legger_til_to_positiver(self):
    self.assertEqual(legg_til(3, 4), 7)

def test_legger_til_negativ(self):
    self.assertEqual(legg_til(-1, 1), 0)

Kjør testene

if name == 'main': unittest.main()

Mentor: "Her har vi laget en enkel funksjon legg_til(a, b), som legger sammen to tall. Deretter har vi skrevet to tester: En for å sjekke om funksjonen fungerer med to positive tall, og en annen for å sjekke om den fungerer med et negativt tall. Testene kjøres automatisk med unittest.main(), og hvis noe går galt, vil vi få en feilmelding som forteller oss hva som gikk galt."


Automatisering av Tester med CI/CD

Mentor: "I større prosjekter vil vi ofte kjøre tester automatisk hver gang vi gjør en endring i koden. Dette kalles 'Continuous Integration' (CI). Med CI-verktøy som Jenkins eller GitHub Actions, kan vi automatisk kjøre testene våre hver gang vi endrer koden, og få beskjed om noe bryter. Dette gjør det lettere å holde koden stabil og feilfri."


Skrive Flere Tester

Mentor: "Jo flere tester vi skriver, desto sikrere kan vi være på at programmet fungerer som det skal. Det er viktig å dekke ulike tilfeller, som vanlige verdier, uvanlige verdier, og til og med feilverdier. Her er noen eksempler på flere tester vi kan legge til for funksjonen vår."

class TestLeggTil(unittest.TestCase):

def test_legger_til_to_positiver(self):
    self.assertEqual(legg_til(3, 4), 7)

def test_legger_til_negativ(self):
    self.assertEqual(legg_til(-1, 1), 0)

def test_legger_til_null(self):
    self.assertEqual(legg_til(0, 0), 0)

def test_legger_til_flyttall(self):
    self.assertAlmostEqual(legg_til(2.5, 3.1), 5.6, places=1)

Mentor: "Her har vi lagt til tester for å håndtere tilfeller der vi legger til null og flyttall. Ved å legge til tester for flere scenarier, kan vi dekke et bredere spekter av mulige input."


Assert Statements

Mentor: "Vi bruker assert-metoder for å sammenligne forventede resultater med faktiske resultater i testene våre. Noen vanlige assert-metoder inkluderer:

assertEqual(a, b) – sjekker om a er lik b

assertTrue(x) – sjekker om x er sann

assertFalse(x) – sjekker om x er usann

assertRaises(exception, function) – sjekker om en bestemt feil blir kastet

Disse metodene er viktige for å sørge for at funksjonene våre oppfører seg som forventet."


Feilsøking (Debugging)

Mentor: "Testing hjelper oss med å oppdage feil, men når vi finner en feil, må vi kunne feilsøke den effektivt. Feilsøking, eller debugging, handler om å finne og fikse feil i koden. En enkel måte å feilsøke på er å bruke print()-setninger for å skrive ut verdiene av variabler underveis i programmet."

def legg_til(a, b): print(f"a = {a}, b = {b}") return a + b

Mentor: "Ved å skrive ut verdiene av a og b, kan vi se hva som skjer før funksjonen returnerer verdien sin. Dette er en enkel form for debugging som kan være veldig effektiv."


Bruke en Debugger

Mentor: "En mer avansert metode for feilsøking er å bruke en debugger. Med en debugger kan du stoppe programmet på et bestemt sted (breakpoint), inspisere variabler, og kjøre koden linje for linje. De fleste utviklingsmiljøer (IDEer) som PyCharm og VS Code har innebygde debuggere som gjør dette enkelt."


Unntaksbehandling som Debugging-verktøy

Mentor: "Noen ganger kan det være nyttig å bruke unntaksbehandling til å fange opp feil mens du tester eller feilsøker. Ved å bruke try og except, kan vi isolere problemet og forstå hvor feilen oppstår."

def legg_til(a, b): try: return a + b except TypeError: print("Feil: Kan ikke legge sammen ulike datatyper.")

Mentor: "Her prøver vi å legge sammen a og b, men hvis vi får en TypeError, vil vi skrive ut en feilmelding som forteller oss hva som gikk galt."


Testdrevet Utvikling (TDD)

Mentor: "En tilnærming til programmering som noen bruker, kalles 'Testdrevet Utvikling' (TDD). I TDD skriver du testene først, før du skriver selve funksjonaliteten. Dette tvinger deg til å tenke på hva programmet ditt skal gjøre, og hvordan du kan teste det. Når testene er skrevet, kan du deretter implementere funksjonaliteten."


Oppsummering

Mentor: "I dag har vi lært om testing og feilsøking – to essensielle verktøy for å sikre at koden din fungerer som den skal. Vi har sett hvordan vi kan skrive tester med unittest, bruke assert-metoder for å sammenligne resultater, og feilsøke kode med både enkle print()-setninger og mer avanserte verktøy som debuggere. Testing gjør koden din mer pålitelig, og feilsøking hjelper deg med å finne problemer raskt."


Praktisk Oppgave: Test og Debug et Program

Mentor: "Her er en oppgave for deg: Lag et program som utfører grunnleggende matematiske operasjoner (addisjon, subtraksjon, multiplikasjon og divisjon), og skriv en testklasse som sjekker at alle operasjonene fungerer som forventet. Bruk en debugger for å inspisere verdier underveis hvis noe går galt."


Mentor: "I neste episode skal vi se på hvordan du kan organisere koden din bedre ved å bruke moduler og pakker. Vi vil også se på hvordan du kan jobbe med større prosjekter ved å dele koden opp i logiske enheter. Vi sees da!"


Denne episoden har gitt deltageren en solid introduksjon til testing og feilsøking, samt viktigheten av å sikre at koden fungerer som forventet før den settes i produksjon. Gjennom praktiske oppgaver og eksempler lærer deltageren