🧪 Øvelse 39 – Unit tests i CI/CD
ℹ️ Information
I denne øvelse skal du tilføje unit tests til din build pipeline.
Som tidligere vist i undervisningen kan unit tests understøtte sikkerheden i software, da en unit test hurtigt kan påvise en uhensigtsmæssig ændring i koden, som potentielt kan introducere en sårbarhed i softwaren. I undervisningen har vi dog manuelt eksekveret disse unit tests for at få påvist fejl, hvilket er uhensigtsmæssigt, da en udvikler kan glemme at eksekvere testene efter en ændring i koden. Build-pipelinen kan sikre, at alle disse unit tests bliver eksekveret, hver gang der skubbes ændret kode ind i repositoriet. Hvis nogen af unit testene fejler, afbrydes processen, og applikationen bliver ikke deployeret. Samtidig bliver udvikleren underrettet om, at nogen af testene har fejlet.
I øvelsen skal du foretage ændringer i GitHub Actions konfigurationsfilen. Disse ændringer er dokumenteret på GitHub Docs.
Men du bør blot kunne følge de nedstående instruktioner.
🚀 Instruktioner
- I . yml konfigurationsfilen i det lokale repo, skal du tilføje et test job som det første job:
test:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
working-directory: ./<Navnet på folderen med unit tetst projektet>
run: dotnet test
Yaml-filer kan være lidt skrøbelige med hensyn til indrykning, så du skal muligvis rette dem et par gange, indtil det virker.
- Sikre at build først køre efter test, ved at Tilføje
needs: testtil build jobbet, som vis på nedstående billede

-
Push de nye ændringer til GitHub repository.
-
Verificer, at alle test blev eksekveret i build-processen og at ingen tests fejlet.

I dette konkrete tilfælde sikrer unit testene, at modelobjekterne opretholder deres invarians (disse tests implementerede du tidligere). Hvis invariansen ikke længere opretholdes, fejler unit testene. Invarians er et ekstra lag af sikkerhed, hvis inputvalideringen skulle fejle. Samtidig fungerer unit testene som et ekstra lag af sikkerhed, hvis invariansen skulle fejle. Således er du nu helgarderet imod eventuelle uhensigtsmæssige ændringer i koden, som kan føre til ugyldigt data i softwaren.
Her kunne man også havde lavet unit test til forskellige Controller metoder, for at sikre at input valideringen virker.
I de næste trin skal du bevidst få unit testene til at fejle, for at observere, hvordan dette håndteres.
- Udkommenter invariansen i domæne-primitiverne.
- Eksekver unit testene lokalt, og verificer, at de fejler.
- Push koden til GitHub.
- Observer build-jobbet. Hvordan håndteres en fejlet unit test? Afbrydes processen? Bliver deployment-trinene udført?
Du bør nu have et nogenlunde overblik over, hvordan unit tests kan bidrage til sikkerheden i software. I de sidste trin skal du blot "ryde op" i applikationen.
- Fjern udkommenteringen af invariansen i domæne-primitiverne.
- Eksekver unit testene lokalt, og verificer, at de ikke fejler.
- Push koden til GitHub.
- Observer build-jobbet, og verificer, at alle trin eksekveres uden fejl.
Eksempel på typisk fejlsituation i testen
For at illustrere hvad der sker, hvis invariansen brydes, kan du forestille dig en testcase som denne, hvor vi forventer at konstruktøren kaster en exception ved ugyldigt input:
[Fact]
public void Firstname_ShouldThrowException_WhenNameIsTooShort()
{
Assert.Throws<ArgumentException>(() => new Firstname("A"));
}
Hvis denne test fejler, betyder det, at objektet accepterer ugyldige værdier, og dermed kan der opstå inkonsistens i systemet.
Advarsel om YAML-formatering
YAML-konfigurationsfiler er meget følsomme over for indrykninger og mellemrum. En forkert indrykning kan føre til fejl i GitHub Actions.
For at undgå frustration anbefales det at bruge online YAML-validatorer som YAML Lint eller editor-plugins, der understøtter syntaksvalidering.
Sørg for altid at tjekke din fil grundigt, før du pusher den til GitHub.
Kobling til sikkerhedsmæssige konsekvenser
Unit tests hjælper med at forebygge mange typer af sikkerhedsproblemer, fordi de sikrer, at kritisk funktionalitet og forretningsregler overholdes. Eksempler på sårbarheder, der kan fanges eller mindskes gennem veludførte unit tests:
- SQL Injection: Ved at teste inputvalidering kan du sikre, at specielle karakterer ikke tillades.
- Broken Access Control: Tests kan verificere, at kun autoriserede brugere får adgang til bestemte metoder eller data.
- Ugyldige domæneværdier: Unit tests sikrer, at objekter kun kan oprettes med gyldige værdier og derved undgår forretningslogiske fejl.
Vigtigheden af testdækning
Det er ikke nok bare at have nogle unit tests – det er vigtigt at sikre, at de dækker kritisk kode og domænelogik grundigt. Høj testdækning giver større sikkerhed for, at ændringer i koden ikke utilsigtet bryder eksisterende funktionalitet eller indfører sårbarheder.
Overvej at måle testdækningen i projektet, og fokusér på at dække centrale komponenter som inputvalidering, autentificering, autorisation og databehandling.
Test dækning benævnes Code coverage
🤔 Refleksionsspørgsmål
- 🛡️ Hvordan bidrager unit tests i CI/CD til at sikre softwarekvalitet og forhindre sårbarheder?
- 🔄 Hvilken effekt har automatiseret test på udviklingsprocessens effektivitet og pålidelighed?
- 🧑🤝🧑 Hvordan kan unit tests fungere som en kommunikationsform mellem udviklere om intentionen bag koden?
- ⚠️ Hvad er konsekvenserne af at ignorere eller springe over unit tests i en CI/CD pipeline?
- 🧩 Hvordan kan unit tests kombineres med andre sikkerhedsforanstaltninger for at opnå defense in depth?
💡 Automatiserede unit tests i CI/CD er et effektivt middel til at forhindre fejl og sårbarheder ved tidlig opdagelse og sikre, at kodens intention opretholdes gennem hele udviklingsprocessen.