Il arrive souvent que pour tester unitairement des règles de validation, on doive tester le même cas mais avec des exemples différents. Sans tests paramétrés, ça revient à faire un test par cas ce qui peut alourdir notre fichier de tests.
On va voir comment simplifier tout ça avec des tests paramétrés.
Prenons l’exemple d’une classe “Nom de Royaume” où je veux m’assurer dès sa construction que la valeur fournie ait plus de 3 caractères.
public RealmName(string Value)
{
if (Value.Length <= MinimumLength)
{
throw new InvalidRealmNameException("Realm name must have at least 3 characters");
}
this.Value = Value;
}
Pour écrire le cas de test sans tests paramétrés, j’aurais probablement dû écrire un cas pour 0,1,2,3 caractères soit 4 tests:
public void Should_not_build_empty_realm_name()
{
var action = () => new RealmName ("");
action.Should().Throw<InvalidRealmNameException>();
}
public void Should_not_build_empty_realm_name_with_single_character()
{
var action = () => new RealmName ("a");
action.Should().Throw<InvalidRealmNameException>();
}
public void Should_not_build_empty_realm_name_with_two_characters()
{
var action = () => new RealmName ("bb");
action.Should().Throw<InvalidRealmNameException>();
}
public void Should_not_build_empty_realm_name_with_three_characters()
{
var action = () => new RealmName ("ccc");
action.Should().Throw<InvalidRealmNameException>();
}
Avec des tests paramétrés on écrit un seul test. Chaque exemple devient un “TestCase” et il suffit de le passer en argument à la méthode de test.
De cette façon, notre test est joué une fois avec chaque exemple ce qui réduit la quantité de code nécessaire sans qu’on perde en lisibilité, c’est bien mieux ! 🙂
[TestCase("")]
[TestCase("a")]
[TestCase("bb")]
[TestCase("ccc")]
public void Should_not_build_invalid_realm_name(string realmName)
{
var action = () => new RealmName (realmName);
Check.ThatCode(action).Throws<InvalidRealmNameException>();
}
Résultat
Autre exemple:
[TestCase(1, 1000)]
[TestCase(2, 3000)]
[TestCase(3, 6000)]
[TestCase(4, 10000)]
[TestCase(5, 15000)]
public void Should_compute_score_to_next_level(int level, int requiredScoreToLevelUp)
{
var nextLevelPoints = new RealmLevel(level).GetScoreToLevelUp();
Check.That(nextLevelPoints).IsEqualTo(requiredScoreToLevelUp);
}
Avant .Net 8, tester du code qui utilise DateTime.Now() n’était pas trivial, on devait faire en sorte de mocker la Clock dans nos tests. Depuis .Net 8, c’est beaucoup plus facile grâce à TimeProvider inclut par défaut !
En deux mots, TimeProvider est une classe abstraite et on va pouvoir injecter dans nos tests une implémentation “Fake” qui va nous permettre de changer la date actu...
La gestion des erreurs de son API est très importante pour que les consommateurs puissent avoir une description claire du problème mais c’est souvent fastidieux à maintenir.
On va voir comment avoir des statuts de réponse cohérent et des messages d’erre...
On va voir comment avoir en quelques minutes des assertions qui vont vérifier les endpoints de notre API avec des scénarios de ce genre:
Feature: Create a new account
As a visitor,
I can create an account to access the game
Scenario: A visitor c...
Depuis .NET 9, le le support d’OpenAPI est directement inclus dans .NET et ne passe plus par les librairies Swagger par défaut (plus d’info sur ce choix ici si jamais ça vous intéresse).
De façons simplifiée, la librairie Swashbuckle.AspNetCore.Sw...