J'ai quelque chose comme ça:
public byte[] EncodeMyObject(MyObject obj)
J'ai fait des tests unitaires comme celui-ci:
byte[] expectedResults = new byte[3]{ 0x01, 0x02, 0xFF };
Assert.IsEqual(expectedResults, EncodeMyObject(myObject));
EDIT: Les deux façons que j'ai vues proposées sont:
1) Utilisation de valeurs attendues codées en dur, comme dans l'exemple ci-dessus.
2) Utiliser un décodeur pour décoder le tableau d'octets codés et comparer les objets d'entrée / sortie.
Le problème que je vois avec la méthode 1 est qu'elle est très fragile et nécessite beaucoup de valeurs codées en dur.
Le problème avec la méthode 2 est que le test de l'encodeur dépend du bon fonctionnement du décodeur. Si l'encodeur / décodeur sont cassés de manière égale (au même endroit), alors les tests pourraient produire des faux positifs.
Ce sont peut-être bien les seuls moyens de tester ce type de méthode. Si tel est le cas, alors très bien. Je pose la question pour voir s'il existe de meilleures stratégies pour ce type de test. Je ne peux pas révéler les internes de l'encodeur particulier sur lequel je travaille. Je demande en général comment vous pourriez résoudre ce type de problème, et je ne pense pas que les internes soient importants. Supposons qu'un objet d'entrée donné produira toujours le même tableau d'octets de sortie.
la source
myObject
va demyObject
à{ 0x01, 0x02, 0xFF }
? Cet algorithme peut-il être décomposé et testé? La raison pour laquelle je demande est actuellement, il semble que vous ayez un test qui prouve qu'une chose magique produit une autre chose magique. Votre seule confiance est que la seule entrée produit la seule sortie. Si vous pouvez décomposer l'algorithme, vous pouvez gagner davantage en confiance dans l'algorithme et être moins dépendant des entrées et sorties magiques.Réponses:
Vous êtes dans une situation désagréable là-bas. Si vous aviez un format statique dans lequel vous encodiez, votre première méthode serait la voie à suivre. Si ce n'était que votre propre format, et que personne d'autre n'avait à décoder, la deuxième méthode serait la voie à suivre. Mais vous ne rentrez vraiment dans aucune de ces catégories.
Ce que je ferais, c'est essayer de décomposer les choses en fonction du niveau d'abstraction.
Donc, je commencerais par quelque chose au niveau du bit, que je testerais quelque chose comme
L'idée est donc que le bitwriter sait comment écrire les types de champs les plus primitifs, comme les entiers.
Des types plus complexes seraient mis en œuvre en utilisant et testé quelque chose comme:
Notez que cela évite de savoir comment les bits réels sont emballés. Cela a été testé par le test précédent, et pour ce test, nous supposerons à peu près que cela fonctionne.
Ensuite, au niveau d'abstraction suivant, nous aurions
donc, encore une fois, nous n'essayons pas d'inclure la connaissance de la façon dont les varstrings ou les dates ou les nombres sont réellement encodés. Dans ce test, nous ne sommes intéressés que par l'encodage produit par encodeObject.
Le résultat final est que si le format des dates est modifié, vous devrez corriger les tests qui impliquent réellement des dates, mais tous les autres codes et tests ne sont pas concernés par la façon dont les dates sont réellement encodées et une fois que vous mettez à jour le code pour le faire ce travail, tous ces tests passeront très bien.
la source
Dépend. Si le codage est quelque chose de complètement fixe, où chaque implémentation est censée créer exactement la même sortie, cela n'a aucun sens de vérifier autre chose que de vérifier que les exemples d'entrées correspondent exactement aux sorties attendues. C'est le test le plus évident, et probablement aussi le plus facile à écrire.
S'il y a une marge de manœuvre avec des sorties alternatives, comme dans la norme MPEG (par exemple, vous pouvez appliquer certains opérateurs à l'entrée, mais vous êtes libre de faire un compromis entre l'effort d'encodage et la qualité de sortie ou l'espace de stockage), il est préférable d'appliquer la défini la stratégie de décodage de la sortie et vérifiez qu'elle est identique à l'entrée - ou, si l'encodage est avec perte, qu'elle est raisonnablement proche de l'entrée d'origine. C'est plus difficile à programmer, mais vous protège contre toute amélioration future qui pourrait être apportée à votre encodeur.
la source
Testez cela
encode(decode(coded_value)) == coded_value
etdecode(encode(value)) == value
. Vous pouvez donner une entrée aléatoire aux tests si vous le souhaitez.Il est toujours possible que l'encodeur et le décodeur soient cassés de manière complémentaire, mais cela semble assez peu probable à moins que vous ayez une mauvaise compréhension conceptuelle de la norme d'encodage. Faire des tests codés en dur de l'encodeur et du décodeur (comme vous le faites déjà) devrait éviter cela.
Si vous avez accès à une autre implémentation de celle-ci qui fonctionne, vous pouvez au moins l'utiliser pour avoir l'assurance que votre implémentation est bonne même si son utilisation dans les tests unitaires serait impossible.
la source
decode(encode(char))
ce ne serait pas égalchar
(ce serait égalchar+2
).Testez les exigences .
Si les exigences ne sont que «encoder dans un flux d'octets qui, une fois décodé, produit un objet équivalent», testez simplement l'encodeur par décodage. Si vous écrivez à la fois l'encodeur et le décodeur, testez-les ensemble. Ils ne peuvent pas avoir des "erreurs de correspondance". S'ils travaillent ensemble, le test réussit.
S'il existe d'autres exigences pour le flux de données, vous devrez les tester en examinant les données codées.
Si le format codé est prédéfini, alors vous devrez vérifier les données codées par rapport au résultat attendu, comme vous l'avez fait, ou (mieux) obtenir un décodeur de référence auquel vous pouvez faire confiance pour effectuer la vérification. L'utilisation d'un décodeur de référence élimine la possibilité que vous ayez mal interprété la spécification de format.
la source
Selon le cadre de test et le paradigme que vous utilisez, vous pouvez toujours utiliser le modèle Arrange Act Assert pour cela, comme vous l'avez dit.
Vous devez connaître les exigences
EncodeMyObject()
et pouvez utiliser ce modèle pour tester par rapport à chacun d'eux des critères valides et invalides, en organisant chacun d'eux et en codant en dur le résultat attendu pourexpected
, de même pour le décodeur.Étant donné que les attendus sont codés en dur, ils seront fragiles si vous avez un changement massif.
Vous pouvez être en mesure d'automatiser avec quelque chose de paramétré (jetez un œil à Pex ) ou si vous faites DDD ou BDD jetez un œil à gerkin / concombre .
la source
Vous décidez de ce qui est important pour vous.
Est-il important pour vous qu'un objet survive à l'aller-retour et que le format de fil exact ne soit pas vraiment important? Ou le format de fil exact est-il une partie importante de la fonctionnalité de votre encodeur et décodeur?
Si c'est le premier, assurez-vous simplement que les objets survivent au voyage aller-retour. Si l'encodeur et le décodeur sont tous deux cassés de manière exactement complémentaire, vous ne vous en souciez pas vraiment.
Dans ce dernier cas, vous devez tester que le format de fil est celui que vous attendez pour les entrées données. Cela signifie soit tester le format directement, soit utiliser une implémentation de référence. Mais après avoir testé les bases, vous pouvez tirer profit de tests aller-retour supplémentaires, qui devraient être plus faciles à écrire en volume.
la source