Effectuer des tests unitaires de bibliothèques F# en utilisant dotnet test et NUnit
Ce didacticiel vous guide pas à pas dans la création d’un exemple de solution pour apprendre les concepts des tests unitaires. Si vous préférez suivre le tutoriel en utilisant une solution déjà créée, visualisez ou téléchargez l’exemple de code avant de commencer. Pour obtenir des instructions de téléchargement, consultez Exemples et tutoriels.
Cet article concerne le test d’un projet .NET Core. Si vous testez un projet ASP.NET Core, consultez Tests d’intégration dans ASP.NET Core.
Prérequis
- SDK .NET 8 ou versions ultérieures.
- Un éditeur de texte ou un éditeur de code de votre choix.
Créer le projet source
Ouvrez une fenêtre d’interpréteur de commandes. Créez un répertoire appelé unit-testing-with-fsharp qui contiendra la solution. Dans ce nouveau répertoire, exécutez la commande suivante afin de créer un fichier solution pour la bibliothèque de classes et le projet de test :
dotnet new sln
Ensuite, créez un répertoire MathService. La structure de répertoire et de fichiers est la suivante :
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
Faites de MathService le répertoire actif et exécutez la commande suivante pour créer le projet source :
dotnet new classlib -lang "F#"
Créez une implémentation défaillante du service Math :
module MyMath =
let squaresOfOdds xs = raise (System.NotImplementedException("You haven't written a test yet!"))
Accédez de nouveau au répertoire unit-testing-with-fsharp. Exécutez la commande suivante pour ajouter le projet de la bibliothèque de classes à la solution :
dotnet sln add .\MathService\MathService.fsproj
Créer le projet de test
Ensuite, créez le répertoire MathService.Tests. La structure du répertoire est illustrée ci-dessous :
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
Source Files
MathService.fsproj
/MathService.Tests
Faites de MathService.Tests le répertoire actif et créez un projet avec la commande suivante :
dotnet new nunit -lang "F#"
Cette commande crée un projet de test qui utilise NUnit comme framework de test. Le modèle généré configure le Test Runner dans MathServiceTests.fsproj :
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>
Le projet de test a besoin d’autres packages pour créer et exécuter des tests unitaires. dotnet new
dans l’étape précédente a ajouté NUnit et l’adaptateur de test NUnit. Maintenant, ajoutez la bibliothèque de classes MathService
en tant qu’une autre dépendance au projet. Utiliser la commande dotnet add reference
:
dotnet add reference ../MathService/MathService.fsproj
Vous pouvez consulter le fichier dans son intégralité dans le dépôt d’exemples sur GitHub.
La solution finale se présente comme suit :
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
Source Files
MathService.fsproj
/MathService.Tests
Test Source Files
MathService.Tests.fsproj
Exécutez la commande suivante dans le répertoire unit-testing-with-fsharp :
dotnet sln add .\MathService.Tests\MathService.Tests.fsproj
Créer le premier test
Vous allez écrire un test défaillant, le corriger pour qu’il réussisse, puis répéter le processus. Ouvrez UnitTest1.fs et ajoutez le code suivant :
namespace MathService.Tests
open System
open NUnit.Framework
open MathService
[<TestFixture>]
type TestClass () =
[<Test>]
member this.TestMethodPassing() =
Assert.That(true, Is.True)
[<Test>]
member this.FailEveryTime() = Assert.That(false, Is.True)
L’attribut [<TestFixture>]
désigne une classe qui contient des tests. L’attribut [<Test>]
désigne une méthode de test qui est exécutée par le Test Runner. À partir du répertoire unit-testing-with-fsharp, exécutez dotnet test
pour générer les tests et la bibliothèque de classes, puis exécutez les tests. Le Test Runner NUnit contient le point d’entrée de programme qui permet d’exécuter vos tests. dotnet test
démarre le Test Runner à l’aide du projet de test unitaire que vous avez créé.
Ces deux tests illustrent les tests de réussite et d’échec les plus basiques. My test
réussit et Fail every time
échoue. À présent, créez un test pour la méthode squaresOfOdds
. La méthode squaresOfOdds
retourne une séquence des carrés de toutes les valeurs de nombre entier impair qui font partie de la séquence d’entrée. Au lieu d’essayer d’écrire toutes ces fonctions simultanément, vous pouvez créer de manière itérative des tests qui valident les fonctionnalités. Pour faire en sorte que chaque test réussisse, vous créez les fonctionnalités nécessaires pour la méthode.
Le test le plus simple que vous pouvez écrire consiste à appeler squaresOfOdds
avec tous les nombres pairs, où le résultat doit être une séquence vide de nombres entiers. Voici ce test :
[<Test>]
member this.TestEvenSequence() =
let expected = Seq.empty<int>
let actual = MyMath.squaresOfOdds [2; 4; 6; 8; 10]
Assert.That(actual, Is.EqualTo(expected))
Notez que la séquence expected
est convertie en liste. Le framework NUnit s’appuie sur de nombreux types .NET standard. Cette dépendance signifie que votre interface publique et les résultats attendus prennent en charge ICollection plutôt que IEnumerable.
Lorsque vous exécutez le test, vous constatez que votre test échoue. La raison en est que vous n’avez pas encore créé l’implémentation. Écrivez le code fonctionnel le plus simple possible dans la classe Library.fs de votre projet MathService, de façon à ce que ce test réussisse :
let squaresOfOdds xs =
Seq.empty<int>
Dans le répertoire unit-testing-with-fsharp, réexécutez dotnet test
. La commande dotnet test
exécute une build pour le projet MathService
puis pour le projet MathService.Tests
. Après avoir créé les deux projets, elle exécute vos tests. À présent, les deux tests réussissent.
Satisfaire aux exigences
Maintenant que vous avez fait réussir un test, le moment est venu d’écrire plus de code. Le cas simple suivant fonctionne avec une séquence dont le seul nombre impair est 1
. Le nombre 1 est plus facile, car le carré de 1 est 1. Voici ce test suivant :
[<Test>]
member public this.TestOnesAndEvens() =
let expected = [1; 1; 1; 1]
let actual = MyMath.squaresOfOdds [2; 1; 4; 1; 6; 1; 8; 1; 10]
Assert.That(actual, Is.EqualTo(expected))
L’exécution de dotnet test
fait échouer le nouveau test. Vous devez mettre à jour la méthode squaresOfOdds
pour gérer ce nouveau test. Vous devez filtrer tous les nombres pairs hors de la séquence pour que ce test réussisse. Pour ce faire, vous pouvez écrire une petite fonction de filtre et utiliser Seq.filter
:
let private isOdd x = x % 2 <> 0
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
Encore une étape : calculer le carré de chaque nombre impair. Commencez par écrire un nouveau test :
[<Test>]
member public this.TestSquaresOfOdds() =
let expected = [1; 9; 25; 49; 81]
let actual = MyMath.squaresOfOdds [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
Assert.That(actual, Is.EqualTo(expected))
Vous pouvez corriger le test en redirigeant la séquence filtrée via une opération de mappage pour calculer le carré de chaque nombre impair :
let private square x = x * x
let private isOdd x = x % 2 <> 0
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
|> Seq.map square
Vous avez créé une petite bibliothèque et un ensemble de tests unitaires pour cette bibliothèque. Vous avez structuré la solution pour que l’ajout de nouveaux packages et de nouveaux tests fasse partie du workflow normal. Vous avez consacré la plupart de votre temps et de vos efforts à la résolution des objectifs de l’application.