JustDummies

Juste des dummies, mais redoutablement efficaces.

Sections de la documentation

Nombres

Chaque type numérique du BCL possède un générateur, et tous partagent un même vocabulaire de contraintes. Apprenez les cinq familles ci-dessous et vous connaissez les quatorze générateurs.

Quel générateur pour quel type

FabriqueTireDisponibilité
Any.Byte()bytepartout
Any.SByte()sbytepartout
Any.Int16()shortpartout
Any.Int32()intpartout
Any.Int64()longpartout
Any.UInt16()ushortpartout
Any.UInt32()uintpartout
Any.UInt64()ulongpartout
Any.Decimal()decimalpartout
Any.Double()doublepartout
Any.Single()floatpartout
Any.Int128()Int128.NET 8+
Any.UInt128()UInt128.NET 8+
Any.Half()Half.NET 8+

La fabrique porte le nom du type CLR, jamais celui du mot-clé C# — Any.Int32(), et non Any.Int(). Un nom par type : rien à retenir, rien à lever comme ambiguïté.

Bornes

Cinq contraintes resserrent l’intervalle, et elles se composent :

int quantity   = Any.Int32().Between(1, 100).Generate();          // inclusif des deux côtés
int positive   = Any.Int32().GreaterThan(0).Generate();
int atLeastTen = Any.Int32().GreaterThanOrEqualTo(10).Generate();
int belowMax   = Any.Int32().LessThan(1_000).Generate();
int atMostMax  = Any.Int32().LessThanOrEqualTo(999).Generate();

// Composé : une quantité de ligne de commande, bornée des deux côtés par deux appels distincts.
int lineQuantity = Any.Int32().GreaterThanOrEqualTo(1).LessThanOrEqualTo(50).Generate();

Between est inclusif aux deux extrémités. Des bornes qui se croisent sont refusées immédiatement, avec un message les nommant toutes deux — voir Erreurs et conflits.

La ligne composée ci-dessus est délibérée : deux bornes inclusives déclarées séparément se comportent exactement comme Between(1, 50), ce qui est précisément ce qui garde un intervalle décomposable — un helper partagé peut poser le plancher et un site d’appel ajouter le plafond. JD031 désigne la forme intervalle quand les deux bornes tiennent dans une même chaîne, en information et non en verdict ; la paire reste correcte dans les deux cas.

Un entier non contraint parcourt tout son type. Ne déclarez rien et le tirage est uniforme sur toute la plage, et c’est délibéré (ADR-0031 ouvre un nouvel onglet) : un grand entier reste un entier ordinaire, là où un grand double cesse de se comporter comme de l’arithmétique — la règle sur la virgule flottante, plus bas, est l’exception et non la norme. Uniforme sur une plage signifie aussi que l’essentiel de cette plage se trouve près de ses extrêmes : un Int128 non contraint porte 38 ou 39 chiffres dans environ 94 tirages sur 100. Déclarez une borne quand votre domaine en a une.

Signe et zéro

int     positive = Any.Int32().Positive().Generate();   // > 0
int     negative = Any.Int32().Negative().Generate();   // < 0
int     nonZero  = Any.Int32().NonZero().Generate();    // != 0
int     zero     = Any.Int32().Zero().Generate();       // toujours 0
decimal price    = Any.Decimal().Positive().Generate();

Positive() et Negative() n’existent que là où le type a un signe. byte, ushort, uint, ulong et UInt128 portent NonZero() et Zero() mais pas les deux autres — demander un byte négatif n’est pas une contrainte que la bibliothèque refuse à l’exécution, c’est une méthode qui n’existe pas.

Zero() paraît inutile jusqu’au jour où il faut un dummy qui soit précisément le cas vide, tout en gardant un site d’appel qui se lit comme tous les autres.

Appartenance et exclusion

int      httpPort   = Any.Int32().OneOf(80, 443, 8080).Generate();
int      notReserved = Any.Int32().Between(1, 10).Except(3, 7).Generate();
int      notTheSame = Any.Int32().Between(1, 100).DifferentFrom(42).Generate();

OneOf restreint le tirage à un vivier explicite. Except retire des valeurs du domaine ; DifferentFrom en est la forme à valeur unique et se lit mieux quand il n’y en a qu’une.

Lister deux fois la même constante dans un vivier est le diagnostic JD025 : les doublons fusionnent, le vivier est donc plus petit qu’il n’y paraît.

Multiples et échelle

Deux contraintes placent la valeur sur une grille plutôt que simplement dans un intervalle.

MultipleOf s’applique aux types entiers :

int    evenQuantity = Any.Int32().Between(1, 100).MultipleOf(2).Generate();
int    onTheHour    = Any.Int32().Between(0, 1_440).MultipleOf(60).Generate();
long   pageOffset   = Any.Int64().GreaterThanOrEqualTo(0).MultipleOf(25).Generate();

WithScale s’applique à decimal et fixe le nombre de décimales — ce qui fait qu’un dummy de montant se comporte comme un montant :

decimal amount = Any.Decimal().Between(0m, 10_000m).WithScale(2).Generate(); // p. ex. 4172,35
decimal rate   = Any.Decimal().Between(0m, 1m).WithScale(4).Generate();      // p. ex. 0,0725

Combiner Between et MultipleOf est le seul endroit à surveiller : un intervalle ne contenant aucun multiple du pas n’admet aucune valeur, et il est refusé. Any.Int32().Between(1, 10).MultipleOf(50) nomme les deux côtés dans son message, et l’analyzer JD023 l’attrape dès la compilation quand les deux arguments sont constants.

Virgule flottante

Double, Single et Half portent les bornes, la famille du signe et celle de l’appartenance — mais ni MultipleOf ni WithScale, car une grille en virgule flottante binaire n’est pas une grille sur laquelle un test peut raisonner.

Deux comportements méritent d’être connus.

Les tirages non contraints restent ordinaires. Un double, float ou decimal non contraint est tiré dans un ordre de grandeur d’un million, au lieu de parcourir toute la plage du type (ADR-0031 ouvre un nouvel onglet). Des valeurs comme 1.7e308 sont techniquement dans la plage et inutiles dans un test : elles transforment chaque assertion arithmétique suivante en question sur le dépassement de capacité. Déclarez une borne quand votre domaine en a une.

NaN et les infinis ne sont jamais tirés, ni acceptés. Le refus couvre aussi les arguments : Except(double.NaN) et une borne non finie sont tous deux rejetés — un NaN ne restreint jamais rien, puisque toute comparaison avec lui est fausse.

Quand un test a réellement besoin d’un NaN, demandez-le explicitement via le vivier générique, qui ne porte aucune règle de finitude :

double maybeNaN = Any.OneOf(double.NaN, 1.0, 2.0).Generate();

Matrice de disponibilité

Contrainteentiers signésUInt*, bytedecimaldouble, float, Half
Between, GreaterThan, GreaterThanOrEqualTo, LessThan, LessThanOrEqualTo
OneOf, Except, DifferentFrom
NonZero, Zero
Positive, Negative
MultipleOf
WithScale

Lire la source, ou la corriger là-bas ouvre un nouvel onglet· Repris depuis lib-v1.0.0-preview.6