2010-06-15 6 views
3

J'apprends le TDD et j'ai une question sur les variables privées/protégées. Ma question est: Si une fonction que je veux tester fonctionne sur une variable privée, comment dois-je la tester?Développement piloté par les tests: Rédaction de tests pour les variables privées/protégées

Voici l'exemple que je travaille avec:

J'ai une classe appelée Table qui contient une variable d'instance appelée internalRepresentation qui est un tableau 2D. Je veux créer une fonction appelée multiplyValuesByN qui multiplie toutes les valeurs dans le tableau 2D par l'argument n.

J'écrire le test pour elle (en Python):

def test_multiplyValuesByN (self): 
    t = Table(3, 3) # 3x3 table, filled with 0's 
    t.set(0, 0, 4) # Set value at position (0,0) to 4 
    t.multiplyValuesByN(3) 

    assertEqual(t.internalRepresentation, [[12, 0, 0], [0, 0, 0], [0, 0, 0]]) 

Maintenant, si je fais privé ou protégé internalRepresentation, ce test ne fonctionnera pas. Comment suis-je supposé écrire le test de sorte qu'il ne dépend pas de internalRepresentation mais teste toujours qu'il semble correct après avoir appelé multiplyValuesByN?

Répondre

10

Vous ne devez pas dépendre de la représentation interne d'un objet. C'est pourquoi il est marqué comme privé ou protégé. Considérez les changements observables lorsque vous appelez t.multiplyValuesByN (3). Ensuite, testez ce que vous pouvez observer.

def test_multiplyValuesByN (self): 
    t = Table(3, 3) # 3x3 table, filled with 0's 
    t.set(0, 0, 4) # Set value at position (0,0) to 4 
    t.multiplyValuesByN(3) 

    assertEqual(t.get(0,0), 12) 
0

Ne pas tester pour les variables/état privés. Vos tests doivent confirmer que l'unité testée est conforme à sa spécification et que cette spécification est déterminée par son interface. Votre test doit donc être écrit en termes d'entrées pour votre unité de test, et vérifiez que la sortie correspond à ce que vous attendez.

Vous souhaitez pouvoir modifier l'implémentation de l'unité testée (pour des raisons d'efficacité, par exemple) et confirmer que cela fonctionne comme prévu. Donc, vérifier l'état privé causerait des difficultés dans cette situation.

3

Si elle est interne, c'est nobodys business en dehors de la classe et qui inclut les tests.

Dans TDD, vous concevez l'API de vos classes et les futurs clients ne peuvent voir que le comportement observable de la classe.

Je sais que c'est plus facile à dire qu'à faire.

Dans le test que vous voyez souvent un modèle reoccuring: configuration - fonctionnement - vérifier (- teardown)

La phase d'installation est responsable de faire l'objet dans l'état des conditions préalables.

La phase de vérification doit vérifier les postconditions grâce au comportement observable de la classe. Cela n'a aucun sens de stocker un état invisible, si jamais et jamais nulle part.

+0

... également connu sous le nom d'Arrange-Act-Assert (mais sans correspondance allitérative pour Teardown - devinez que c'est une bonne chose qu'il n'est pas très utilisé!) –

+0

Oui, c'est pourquoi je l'ai mis entre parenthèses. C'est une de ces choses pratiques qui sont parfois nécessaires mais qui ne cadrent pas bien dans la théorie. J'aime l'allitération 3-A. Je n'ai pas entendu ça avant, merci! –

3

D'autres ont posté de bonnes réponses, mais à mon humble avis n'a pas mis l'accent sur une chose: l'aspect de la conception (bien que Peter Tillemans l'a mentionné). J'ajoute donc un peu d'explication à ce sujet. Lorsque vous effectuez TDD, vous testez efficacement la conception de votre API ainsi que l'implémentation. Si vous trouvez que le résultat d'un appel de méthode est difficile ou impossible à voir de l'extérieur, c'est presque toujours un signe que votre interface de classe n'est pas bien conçue. S'il est difficile d'écrire des tests pour votre classe, il sera généralement difficile de l'utiliser dans la vie réelle - vos tests unitaires sont en effet les premiers clients de votre classe.Ainsi, si vous constatez qu'un scénario de test a des difficultés à utiliser votre interface de classe, vous devriez envisager de revenir en arrière et de repenser votre API pour la rendre plus facile à utiliser (sans compromettre l'encapsulation, si possible).

Questions connexes