Skip to content

Testing

Ivar Nesje edited this page Apr 25, 2024 · 5 revisions

Innhold

  1. Testing av abo skjema
  2. Unit tester

Testing av abonnement (abo) skjema

Abonnementskjema er skjema som ikke er åpne, men heller blir instansiert av tjenesteeier. Disse kommer gjerne med preutfylte verdier som TE setter selv. For eksempel så ønsker man å lage et skjema med låst felt på periode som enten er "1. halvår" eller "2. halvår". Når disse skjemaene instansieres på vegne av TE, vil verdiene være satt fra før i XMLen.

For å teste dette lokal må man ha denne filen på pc fra før. Dette kan du gjøre ved å laste ned en eksisterende XML fil av et ferdig innsendt skjema og så fjerne alle verdier som ikke skal være preutfylt. Deretter kan man teste dette ved å laste opp filen i filopplastningsboksen under, og deretter bare starte skjema. Instansiering gjøres da med et mock maskinporten token som tjensteeier, slik at policy.xml må ha rettigheter til tjenesteeier (instanceOwner kan dermed fint være uten rettighet til instansiering) image

Unit testing med xUnit

Veiledning for oppset av unit tester i appene.

Prerequisites

For VSCode: Sørg for å ha følgende utvidelser i din IDE.

  • C#
  • C# Dev Kit

Create Test project

Oppsett av tester kan enten skje manuelt eller i terminal

Solution Explorer

Til venstre i menyen, velg Explorer. Denne er som regel på toppen.

Etter nedlastning av C# Dev Kit skal man kunne se en nedtrekksliste som sier Solution Explorer.

└── <AppName>
    ├── App
    ├── .dockerignore
    ├── .gitignore
    └── README.md
└── Solution explorer
    └── App
        └── App

For å kunne skrive unit testene må vi først ha et eget prosjekt som inneholder filene vi trenger for å kjøre testene og knytte dem til appen vår.

I Solution Explorer finn fram knappen som sier New Project.... Denne finner man ved å trykke på + som dukker opp når man holder musen over første mappen med navnet App.

Velg deretter xUnit Test Project og gi den navnet Tests. Filtreet vil deretter se slik ut:

└── <AppName>
    ├── App
    ├── .dockerignore
    ├── .gitignore
    └── README.md
└── Solution explorer
    └── App
        ├── App
        └── Tests

Til slutt må man høyreklikke på Tests, velg Add Project Reference og velg App.

I Terminal

Opprett nytt test-prosjekt:

dotnet new xunit -o TestProjectName

Legg til test-prosjekt til solution:

dotnet sln add TestProjectName/TestProjectName.csproj

Legg til referense til prosjekt som skal tests:

dotnet add TestProjectName/TestProjectName.csproj reference ProjectName/ProjectName.csproj

Create Tests

For unit testene benytter vi oss av følgende nuget pakker: Moq & FluentAssertions

Disse legges til i prosjektet ved å kjøre følgende:

cd Tests
dotnet add package Moq
dotnet add package FluentAssertions

Endre navn på UnitTes1.cs til noe passende. F.eks 1 fil for hver logikk modul.

└── Tests
    ├── Dependencies/
    ├── GlobalUsings.cs
    ├── ValidationTests.cs
    ├── InstantiationTests.cs
    └── DataProcessorTests.cs

Examples

Single unit test example

Før vi ser på et spesifikt eksempel er det greit å definere et par begreper og beskrive strukture på testene.

Navngivning

Vi bruker følgende navngivning for navnet på en funksjon: [MethodName]_[ExpectedResult]_[StateUnderTest]

For eksempel

private Task GetBirthdateFromSSN_ShouldMapSSNToBirthdate_WhenSSNIsValid()
{
    //Arrange
    //Act
    //Assert
}

Arrange, Act, Assert

  • Arrange: Oppsett, klargjøring av dummy data etc.

  • Act: Invoker metoden som skal testes

  • Assert: Verifiser at resultatet av Act er som forventet

Fact vs. Theory

Fact: Representerer en enkel enhetstest

  • Betegner noe som alltid er sant
  • Støtte ikke parametre

Theory: Representerer en parametrisert enhetstest

  • Kjører flere ganger, en for hvert datasett
  • Brukes for å teste flere "veier" gjennom en metode

Enkelt eksempel

[Fact]
private async Task SumTwoNumbers_ShouldSumNumbers_WhenInputValid()
{
    //Arrange
    int a = 1;
    int b = 2;
    int expected = 3;

    //Act

    await _dataProcessor.ProcessDataWrite(_instance, _dataId, model);

    //Assert
    model.sum.Should().Be(expected);
}

[Theory]
[InlineData(1, 2, 3)]
[InlineData(null, 0, null)]
private async Task SumTwoNumbers_ShouldSumNumbers_WhenInputValid(int? a, int? b, int? expected)
{
    //Arrange
    // nothing to arrange

    //Act

    await _dataProcessor.ProcessDataWrite(_instance, _dataId, model);

    //Assert
    model.sum.Should().Be(expected);
}

For DataProcessor:

public class DataProcessingTests
{
    private Instance _instance { get; set; }
    private Guid _dataId { get; set; }
    private readonly Mock<IPersonLookup> _mockPersonClient;
    private readonly Mock<ILogger<DataProcessingHandler>> _mockLogger;
    private readonly Mock<IHttpContextAccessor> _mockHttpContextAccessor;
    private readonly DataProcessingHandler _dataProcessor;

    public DataProcessingTests()
    {
        _instance = new Instance();
        _dataId = Guid.NewGuid();

        _mockPersonClient = new Mock<IPersonLookup>();
        _mockLogger = new Mock<ILogger<DataProcessingHandler>>();
        _mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
        _dataProcessor = new DataProcessingHandler(_mockPersonClient.Object, _mockLogger.Object, _mockHttpContextAccessor.Object);
    }

    // write your tests here...

}

Her ser man at alle properties som er med i DataProcessor også må være her.

For alle interfaces og klasser som brukes i DataProcessor må implementeres gjennom en Mock.

For FormDataValidator/GenericFormDataValidator:

public class FormDataValidatorTests
{
    FormDataValidator _formDataValidator = new();
    Instance _instance = new();
    DataElement _dataElement = new();
    readonly string _language = "nb";

    [Fact]
    public async void Validation_ShouldNotGiveError_IfValidModel()
    {
        // Arrange
        var model = new ModelBuilder()
        .CreateValidModel()
        .Build();

        // Act
        List<ValidationIssue> result = await _formDataValidator.ValidateFormData(_instance, _dataElement, model, _language);

        // Assert
        result.Should().BeEmpty();

    }
}

result er her en liste med ValidationIssue og man kan derfor sjekke hvor mange elementer som er i result, eller for et spesifikt element når man gjør assert.

Run Tests

Bygg tester:

cd Tests
dotnet build

Kjør tester:

dotnet test TestProjectName/TestProjectName.csproj

Hvis det er ønskelig å teste release kan følgende kjøres:

dotnet test TestProjectName/TestProjectName.csproj --configuration Release