MDAT 2.0.0-beta.1
See the version list below for details.
dotnet add package MDAT --version 2.0.0-beta.1
NuGet\Install-Package MDAT -Version 2.0.0-beta.1
<PackageReference Include="MDAT" Version="2.0.0-beta.1" />
<PackageVersion Include="MDAT" Version="2.0.0-beta.1" />
<PackageReference Include="MDAT" />
paket add MDAT --version 2.0.0-beta.1
#r "nuget: MDAT, 2.0.0-beta.1"
#:package MDAT@2.0.0-beta.1
#addin nuget:?package=MDAT&version=2.0.0-beta.1&prerelease
#tool nuget:?package=MDAT&version=2.0.0-beta.1&prerelease
mdAT - Tests automatiques en Markdown
mdAT est une bibliothèque simple qui remplace les tests unitaires et d'intégration. Avec mdAT, les développeurs peuvent écrire des tests unitaires de manière traditionnelle, mais sans avoir besoin d'ajouter de nombreuses données de test à partir de fichiers JSON, XML, YAML, ou d'utiliser manuellement [Arguments] avec des objets JSON échappés.
| Paquet | Contenu |
|---|---|
MDAT |
Le paquet à installer : il apporte MDAT.TUnit et MDAT.Core. |
MDAT.TUnit |
Les sources de données pour TUnit : [MarkdownDataSource] et [YamlFileDataSource]. |
MDAT.Core |
Lecture des fichiers Markdown/YAML, Verify.Assert() et comparaison JSON. Indépendant de tout framework de test. |
Cibles : .NET 8, .NET 9 et .NET 10.
Pour utiliser mdAT, suivez ces étapes :
- Créez un projet de test TUnit (
<OutputType>Exe</OutputType>) et ajoutez le paquetMDAT. - Créez un test normal avec
[Test]. - Codez votre test unitaire de manière traditionnelle (avec Moq, si nécessaire), puis appelez la méthode que vous souhaitez tester.
- Ajoutez tous les paramètres souhaités à votre méthode de test, ils seront exposés pour être remplacés par le fichier de test Markdown de
mdAT. - Ajoutez
[MarkdownDataSource("~/Tests/{method}.md")]avec votre dossierTestscomme référentiel de cas (laissez-le vide au départ). - Assurez-vous d'entourer votre méthode testée avec
Verify.Assert(), cela validera automatiquement le résultat JSON attendu, même s'il s'agit d'une exception. - Votre fichier de test
.mdsera généré automatiquement lors de la première exécution. Modifiez votre fichier.mdcomme vous le souhaitez. - Profitez-en !
Chaque cas du fichier Markdown devient un test distinct dans l'explorateur de tests. Les arguments sont construits à partir du YAML et passés tels quels à votre méthode : aucune sérialisation intermédiaire, quel que soit leur type (DateOnly, Dictionary<object, object>, JsonDocument, ...).
using MDAT;
public class Calc
{
[Test]
[MarkdownDataSource("~/Tests/{method}.md")]
public async Task Add(int val1, int val2, string expected)
{
_ = await Verify.Assert(() => Task.FromResult(Add(val1, val2)), expected);
}
// Cas d'utilisation fictif
public static int Add(int val1, int val2)
{
return val1 + val2;
}
}
Tous les cas de test peuvent être stockés dans un seul fichier Markdown :
# Test de la méthode Add
Cas de test simple pour des tests d'addition.
## Cas 1
Essayons une simple addition `1 + 1` avec un résultat attendu de `2`
``````yaml
val1: 1
val2: 1
expected:
verify:
- type: match
data: 2
``````
## Case 2
``````yaml
val1: 212
val2: 2444
expected:
verify:
- type: match
data: 2656
``````
Avec mdAT, les analystes et les développeurs peuvent travailler ensemble avec une source unique de tests, et les mainteneurs peuvent modifier et valider tous les tests localement ou sur un serveur de build.
Options d'une étape de vérification
Chaque élément de verify accepte :
| Option | Défaut | Rôle |
|---|---|---|
type |
match |
Type de vérification (seul match existe). |
jsonPath |
$ |
Partie du résultat à comparer. Se termine par .length() pour comparer une taille. |
data |
Valeur attendue. | |
allowAdditionalProperties |
false |
Ignore les propriétés présentes dans le résultat mais absentes de data. |
ignoreArrayOrder |
false |
Deux tableaux sont égaux s'ils contiennent les mêmes valeurs, dans n'importe quel ordre (les doublons sont comptés). S'applique à tous les niveaux. |
expected:
verify:
- type: match
jsonPath: $.items
ignoreArrayOrder: true
allowAdditionalProperties: true
data:
- A: second
- A: first
Comparaison JSON
La comparaison est faite par MDAT.Core (aucune dépendance à xunit ou Quibble) :
- les nombres sont comparés exactement, quelle que soit leur écriture (
1,1.0et1e0sont égaux,12345678901234567890et12345678901234567891sont différents) ; - les éléments d'un tableau sont appariés par valeur : un élément qui en remplace un autre est comparé en détail (
$.items[1].name), un élément en trop ou manquant est listé avec son index ; - une propriété en double dans un JSON (
{"a":1,"a":2}) est refusée, au lieu d'en ignorer une silencieusement ; - l'écart est décrit dans
JsonAssertException(DiffMessages,UserMessage).
Migrer vers mdAT 2.0
mdAT 2.0 abandonne MSTest au profit de TUnit. Les projets qui restent sur MSTest peuvent continuer d'utiliser mdAT 1.x.
1. Le projet de test
- Cibler .NET 8 ou plus (.NET 6 et .NET 7 ne sont plus pris en charge).
- Ajouter
<OutputType>Exe</OutputType>: un projet TUnit est un exécutable. - Retirer
Microsoft.NET.Test.Sdk,MSTest.TestAdapter,MSTest.TestFrameworketcoverlet.collector. - Mettre à jour le paquet
MDATen 2.0 (il apporte maintenantMDAT.TUnitetMDAT.Core) et ajouterTUnit.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TUnit" Version="1.73.19" />
<PackageReference Include="MDAT" Version="2.0.0-beta.1" />
</ItemGroup>
</Project>
Les fichiers .md ne changent pas et restent aux mêmes chemins (~/ désigne toujours la racine du projet de test).
2. Le code des tests
| mdAT 1.x / MSTest | mdAT 2.0 / TUnit |
|---|---|
[TestClass] |
(retirer) |
[TestMethod] |
[Test] |
[MarkdownTest("~/Tests/{method}.md")] |
[MarkdownDataSource("~/Tests/{method}.md")] |
[YamlFileData("~/Tests/x.yaml")] |
[YamlFileDataSource("~/Tests/x.yaml")] |
[DataRow(...)] |
[Arguments(...)] |
[DynamicData(...)] |
[MethodDataSource(...)] |
[TestInitialize] / [TestCleanup] |
[Before(Test)] / [After(Test)] |
[ClassInitialize] |
[Before(Class)] |
[DoNotParallelize] |
[NotInParallel] |
Assert.AreEqual(a, b) |
await Assert.That(b).IsEqualTo(a) |
Verify.Assert(), Expected, ObjectOrException<T>, ReturnsOrThrows et l'inclusion de fichiers (!include) fonctionnent sans changement. Les types restent dans l'espace de noms MDAT.
3. Changements d'API
| mdAT 1.x | mdAT 2.0 |
|---|---|
MarkdownTestAttribute |
MarkdownDataSourceAttribute (MDAT.TUnit) ; la lecture des cas est dans MarkdownTestSource.GetCases() (MDAT.Core) |
YamlFileDataAttribute |
YamlFileDataSourceAttribute ; lecture dans YamlFileTestSource.GetCases() |
InternalTestFailureException (MSTest) |
MdatTestDefinitionException |
Quibble.Xunit.JsonAssertException, JsonDiffConfig, JsonAssert |
MDAT.JsonAssertException, MDAT.JsonDiffConfig, MDAT.JsonAssert |
Les dépendances Quibble.Xunit (donc xunit), MSTest.TestFramework, System.Data.SqlClient et System.Text.RegularExpressions sont retirées, ce qui supprime leurs vulnérabilités transitives connues. Moq reste une dépendance de MDAT.Core pour les méthodes ReturnsOrThrows.
4. Convertisseurs YAML globaux
TUnit lit les cas des sources de données pendant la découverte des tests, avant l'exécution de tout hook de classe ou de test. Un convertisseur enregistré avec MdatConfig.AddYamlTypeConverter() dans un [ClassInitialize] / [Before(Class)] arrive donc trop tard. Enregistrez-le dans un hook de découverte :
public static class Setup
{
[Before(TestDiscovery)]
public static void RegisterConverters()
=> MdatConfig.AddYamlTypeConverter(new MonConvertisseur());
}
Le convertisseur s'applique alors à tous les fichiers .md du projet de test.
5. Comparaison JSON : ce qui peut changer
Le verdict d'un test (réussi ou échoué) est le même qu'avec mdAT 1.x dans tous les cas que nous avons comparés, sauf deux comportements devenus plus stricts. Un test qui passait grâce à eux peut maintenant échouer :
- les nombres sont comparés exactement et non plus en
double:12345678901234567890et12345678901234567891, ou0.1et0.10000000000000001, étaient jugés égaux et sont maintenant différents ; - un JSON avec une propriété en double (
{"a":1,"a":2}) est refusé, au lieu d'en ignorer une silencieusement.
Les autres changements portent sur les messages d'écart, qui sont plus précis :
- les valeurs répétées dans un tableau sont toutes listées (Quibble en oubliait et pouvait produire un message vide) ;
- les éléments de tableau sont appariés par valeur, pas par écriture (
1et1.0), ni selon l'ordre des clés de leurs objets ; allowAdditionalPropertiess'applique aussi aux objets contenus dans des tableaux ;- le texte de l'exception change si votre code l'analysait (
MDAT.JsonAssertExceptionn'hérite plus d'une exception xunit).
6. Intégration continue
- Un projet TUnit s'exécute avec
dotnet run --project MyTests -f net9.0(oudotnet testavec le SDK .NET 10). - La couverture de code :
dotnet run --project MyTests -- --coverage --coverage-output-format cobertura. Le fichier.runsettingset le collecteurcoverletne sont plus utilisés. - Si votre dépôt contient des fichiers binaires dont les tests lisent le contenu (PDF, images), déclarez-les dans
.gitattributes(*.pdf binary) : sous Windows, la conversion automatique des fins de ligne les corrompt.
mdAT - Markdown Auto-Tests
mdAT is a simple library that replaces unit and integration tests. With mdAT, developers can write unit tests in the traditional way, but without the need to add many test data from JSON, XML, YAML files, or use manual [Arguments] with escaped JSON object.
| Package | Content |
|---|---|
MDAT |
The package to install: it brings MDAT.TUnit and MDAT.Core. |
MDAT.TUnit |
The data sources for TUnit: [MarkdownDataSource] and [YamlFileDataSource]. |
MDAT.Core |
Markdown/YAML parsing, Verify.Assert() and JSON comparison. Independent from any test framework. |
Targets: .NET 8, .NET 9 and .NET 10.
To use mdAT, follow these steps:
- Create a TUnit test project (
<OutputType>Exe</OutputType>) and add theMDATpackage. - Create a normal test with
[Test]. - Code your unit test in the traditional way (using
Moq, if needed), then call your method you want to test. - Add all your desired parameters to your test method, theses will be exposed to be replaced by
mdATmarkdown test file. - Add
[MarkdownDataSource("~/Tests/{method}.md")]with yourTestsfolder as cases repository (let it being empty in first place). - Ensure to surround your tested method with
Verify.Assert(), it will automatically validate the JSON expected result, even if it is an exception. - Your
.mdtest file will be autogenerated during the first run. - Edit your
.mdfile as you wish. - Enjoy!
Each case of the markdown file is its own test in the test explorer. Arguments are built from the YAML and handed as is to your method: no intermediate serialization, whatever their type (DateOnly, Dictionary<object, object>, JsonDocument, ...).
using MDAT;
public class Calc
{
[Test]
[MarkdownDataSource("~/Tests/{method}.md")]
public async Task Add(int val1, int val2, string expected)
{
_ = await Verify.Assert(() => Task.FromResult(Add(val1, val2)), expected);
}
// Fake usecase
public static int Add(int val1, int val2)
{
return val1 + val2;
}
}
All test cases can be stored in a single markdown file:
# Test Add method
Simple test case for addition tests.
## Case 1
Let's try simple `1 + 1` expected to return `2`
``````yaml
val1: 1
val2: 1
expected:
verify:
- type: match
data: 2
``````
## Case 2
``````yaml
val1: 212
val2: 2444
expected:
verify:
- type: match
data: 2656
``````
Using mdAT, analysts and developers can work together with a unique source of tests, and maintainers can edit and validate all tests locally or on a build server.
Verification step options
Each verify item accepts:
| Option | Default | Purpose |
|---|---|---|
type |
match |
Kind of verification (only match exists). |
jsonPath |
$ |
Part of the result to compare. Ends with .length() to compare a size. |
data |
Expected value. | |
allowAdditionalProperties |
false |
Ignores properties found in the result but not in data. |
ignoreArrayOrder |
false |
Two arrays are equal when they hold the same values, in any order (duplicates are counted). Applies at every level. |
expected:
verify:
- type: match
jsonPath: $.items
ignoreArrayOrder: true
allowAdditionalProperties: true
data:
- A: second
- A: first
JSON comparison
The comparison is done by MDAT.Core (no dependency on xunit or Quibble):
- numbers are compared exactly whatever their spelling (
1,1.0and1e0are equal,12345678901234567890and12345678901234567891are different); - array items are paired by value: an item replacing another one is compared in depth (
$.items[1].name), an extra or missing item is listed with its index; - a duplicated property in a JSON document (
{"a":1,"a":2}) is rejected instead of silently ignoring one of them; - the difference is described in
JsonAssertException(DiffMessages,UserMessage).
Migrating to mdAT 2.0
mdAT 2.0 drops MSTest in favour of TUnit. Projects staying on MSTest can keep using mdAT 1.x.
1. The test project
- Target .NET 8 or later (.NET 6 and .NET 7 are no longer supported).
- Add
<OutputType>Exe</OutputType>: a TUnit project is an executable. - Remove
Microsoft.NET.Test.Sdk,MSTest.TestAdapter,MSTest.TestFrameworkandcoverlet.collector. - Update the
MDATpackage to 2.0 (it now bringsMDAT.TUnitandMDAT.Core) and addTUnit.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TUnit" Version="1.73.19" />
<PackageReference Include="MDAT" Version="2.0.0-beta.1" />
</ItemGroup>
</Project>
The .md files do not change and stay at the same paths (~/ still means the root of the test project).
2. Test code
| mdAT 1.x / MSTest | mdAT 2.0 / TUnit |
|---|---|
[TestClass] |
(remove) |
[TestMethod] |
[Test] |
[MarkdownTest("~/Tests/{method}.md")] |
[MarkdownDataSource("~/Tests/{method}.md")] |
[YamlFileData("~/Tests/x.yaml")] |
[YamlFileDataSource("~/Tests/x.yaml")] |
[DataRow(...)] |
[Arguments(...)] |
[DynamicData(...)] |
[MethodDataSource(...)] |
[TestInitialize] / [TestCleanup] |
[Before(Test)] / [After(Test)] |
[ClassInitialize] |
[Before(Class)] |
[DoNotParallelize] |
[NotInParallel] |
Assert.AreEqual(a, b) |
await Assert.That(b).IsEqualTo(a) |
Verify.Assert(), Expected, ObjectOrException<T>, ReturnsOrThrows and file inclusion (!include) work unchanged. Types stay in the MDAT namespace.
3. API changes
| mdAT 1.x | mdAT 2.0 |
|---|---|
MarkdownTestAttribute |
MarkdownDataSourceAttribute (MDAT.TUnit); reading the cases is done by MarkdownTestSource.GetCases() (MDAT.Core) |
YamlFileDataAttribute |
YamlFileDataSourceAttribute; reading done by YamlFileTestSource.GetCases() |
InternalTestFailureException (MSTest) |
MdatTestDefinitionException |
Quibble.Xunit.JsonAssertException, JsonDiffConfig, JsonAssert |
MDAT.JsonAssertException, MDAT.JsonDiffConfig, MDAT.JsonAssert |
The Quibble.Xunit (hence xunit), MSTest.TestFramework, System.Data.SqlClient and System.Text.RegularExpressions dependencies are removed, which removes their known transitive vulnerabilities. Moq remains a dependency of MDAT.Core for the ReturnsOrThrows methods.
4. Global YAML converters
TUnit reads the cases of data sources while discovering the tests, before any class or test hook runs. A converter registered with MdatConfig.AddYamlTypeConverter() in a [ClassInitialize] / [Before(Class)] is therefore too late. Register it in a discovery hook:
public static class Setup
{
[Before(TestDiscovery)]
public static void RegisterConverters()
=> MdatConfig.AddYamlTypeConverter(new MyConverter());
}
The converter then applies to every .md file of the test project.
5. JSON comparison: what may change
A test verdict (pass or fail) is the same as with mdAT 1.x in every case we compared, except for two behaviours that became stricter. A test that was passing thanks to them may now fail:
- numbers are compared exactly instead of as
double:12345678901234567890and12345678901234567891, or0.1and0.10000000000000001, were considered equal and are now different; - a JSON document with a duplicated property (
{"a":1,"a":2}) is rejected, instead of silently ignoring one of the values.
The other changes concern the difference messages, which are more precise:
- repeated values in an array are all listed (Quibble dropped some and could even produce an empty message);
- array items are paired by value, not by spelling (
1and1.0) nor by the key order of their objects; allowAdditionalPropertiesalso applies to objects held in arrays;- the exception text changes if your code parsed it (
MDAT.JsonAssertExceptionno longer derives from an xunit exception).
6. Continuous integration
- A TUnit project runs with
dotnet run --project MyTests -f net9.0(ordotnet testwith the .NET 10 SDK). - Code coverage:
dotnet run --project MyTests -- --coverage --coverage-output-format cobertura. The.runsettingsfile and thecoverletcollector are no longer used. - If your repository holds binary files whose content is read by tests (PDF, images), declare them in
.gitattributes(*.pdf binary): on Windows, automatic line ending conversion corrupts them.
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- MDAT.TUnit (>= 2.0.0-beta.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 79 | 10/20/2026 |
| 2.0.0-beta.7 | 67 | 10/13/2026 |
| 2.0.0-beta.6 | 52 | 10/13/2026 |
| 2.0.0-beta.5 | 66 | 10/10/2026 |
| 2.0.0-beta.4 | 64 | 10/10/2026 |
| 2.0.0-beta.3 | 78 | 10/10/2026 |
| 2.0.0-beta.2 | 78 | 10/10/2026 |
| 2.0.0-beta.1 | 69 | 10/10/2026 |
| 1.6.0 | 172 | 4/30/2026 |
| 1.5.1 | 242 | 11/8/2025 |
| 1.5.0 | 216 | 11/8/2025 |
| 1.4.1 | 321 | 12/3/2024 |
| 1.4.0 | 219 | 12/1/2024 |
| 1.3.1 | 635 | 4/20/2024 |
| 1.3.0 | 282 | 4/20/2024 |
| 1.2.4 | 322 | 9/28/2023 |
| 1.2.3 | 241 | 9/28/2023 |
| 1.2.2 | 257 | 9/23/2023 |
| 1.2.1 | 273 | 9/8/2023 |
| 1.2.0 | 332 | 6/15/2023 |
mdAT 2.0 replaces MSTest by TUnit and ships as MDAT.Core (framework independent) and MDAT.TUnit. See the migration section of the README. Projects staying on MSTest can keep using 1.x.