Question

J'ai commencé à utiliser TDD. Comme mentionné dans la une question précédente , la plus grande difficulté est gérer les changements d'interface. Comment réduisez-vous l'impact sur vos scénarios de test lorsque les exigences changent?

Était-ce utile?

La solution

La modification d'une interface nécessite la mise à jour du code utilisant cette interface. Le code de test n'est pas différent du code de non-test à cet égard. Il est inévitable que les tests de cette interface doivent être modifiés.

Souvent, lorsqu'une interface change, vous constatez que "trop ??de" et les tests sont interrompus, c’est-à-dire que les tests portant sur des fonctionnalités en grande partie non liées dépendent de cette interface. Cela peut être un signe que vos tests sont trop larges et nécessitent une refactorisation. Cela peut se produire de nombreuses manières, mais voici un exemple qui illustre l'idée générale ainsi qu'un cas particulier.

Par exemple, si la manière de construire un objet Account a changé et que cela nécessite la mise à jour de tous vos tests ou de la plupart de vos tests pour votre classe Order, quelque chose ne va pas. La plupart de vos tests unitaires Ordre ne s’intéressent probablement pas à la création d’un compte. Par conséquent, procédez comme suit pour les tests de refactorisation:

def test_add_item_to_order(self):
    acct = Account('Joe', 'Bloggs')
    shipping_addr = Address('123 Elm St', 'etc' 'etc')
    order = Order(acct, shipping_addr)
    item = OrderItem('Purple Widget')
    order.addItem(item)
    self.assertEquals([item], order.items)

à ceci:

def make_order(self):
    acct = Account('Joe', 'Bloggs')
    shipping_addr = Address('123 Elm St', 'etc' 'etc')
    return Order(acct, shipping_addr)

def make_order_item(self):
    return OrderItem('Purple Widget')

def test_add_item_to_order(self):
    order = self.make_order()
    item = self.make_order_item()
    order.addItem(item)
    self.assertEquals([item], order.items)

Ce modèle particulier est une méthode de création .

Un avantage ici est que vos méthodes de test pour Order sont isolées de la manière dont les comptes et les adresses sont créés; si ces interfaces changent, vous n’avez qu’un emplacement à modifier, plutôt que tous les tests utilisant des comptes et des adresses.

En bref: les tests sont aussi du code et, comme tout code, ils nécessitent parfois un refactoring.

Autres conseils

Je pense que c'est l'une des raisons de l'argument à la mode selon lequel les interfaces sont trop utilisées.

Cependant, je ne suis pas d'accord.

Lorsque les exigences changent, vos tests doivent l'être également. Droite? Je veux dire, si les critères pour lesquels vous avez écrit le test ne sont plus valides, vous devez alors réécrire ou éliminer ce test.

J'espère que cela vous aidera, mais je pense avoir mal compris votre question.

Il aura un impact. Vous devez simplement accepter que la modification de l'interface nécessite du temps pour modifier d'abord les scénarios de test associés. Il n'y a pas moyen de contourner cela.

Cependant, vous tenez compte du temps que vous gagnez en n'essayant pas de trouver un bogue insaisissable dans cette interface plus tard et en ne le corrigeant pas pendant la semaine de parution, cela en vaut la peine.

En mode TDD, vos tests ne sont pas des tests. Ce sont des spécifications exécutables. IOW: ils sont un encodage exécutable de vos besoins. Toujours gardez cela à l'esprit.

Tout à coup, cela devient évident: si vos exigences changent, les tests doivent changer! C'est tout l'intérêt du TDD!

Si vous faisiez une chute d'eau, vous devriez changer votre document de spécification. Dans TDD, vous devez faire de même, sauf que votre spécification n’est pas écrite dans Word, elle est écrite dans xUnit.

"Que devons-nous faire pour éviter que notre code et nos tests ne dépendent de la dépendance? Semble que rien. Chaque fois que les requêtes changent, nous devons changer notre code & amp; tests. Mais peut-être pouvons-nous simplifier notre travail? Oui nous pouvons. Et le principe de base est le suivant: l’incapsulation de code pouvant être modifié. "

http://dmitry-nikolaev.blogspot.com /2009/05/atch-your-changes.html

Vous écrivez les tests avant d'écrire le code de la nouvelle interface.

Si vous suivez l'approche Test First, il ne devrait en principe y avoir aucun impact des modifications d'interface sur votre code de test. Après tout, lorsque vous devez modifier une interface, modifiez d’abord le ou les cas de test pour répondre aux exigences, puis modifiez vos interfaces / implémentations jusqu’à ce que les tests soient réussis.

Lorsque les interfaces changent, vous devez vous attendre à ce que les tests échouent. Si trop de tests échouent, cela signifie que votre système est trop étroitement couplé et que trop d'éléments dépendent de cette interface. Vous devez vous attendre à quelques tests, mais pas beaucoup.

La rupture des tests est une bonne chose. Toute modification de votre code devrait interrompre les tests.

Si les exigences changent, vos tests doivent être la première chose à changer, plutôt que l'interface.

Je commencerais par modifier la conception de l'interface dans le premier test approprié, en mettant à jour l'interface pour réussir le test qui venait de se terminer. Une fois que l'interface est mise à jour pour réussir le test, vous devriez voir d'autres tests s'interrompre (car ils utiliseront l'interface obsolète).

Il devrait s’agir de mettre à jour les tests qui échouent avec la nouvelle conception de l’interface pour les faire passer à nouveau.

La mise à jour de l'interface à l'aide de tests garantira que les modifications sont réellement nécessaires et peuvent être testées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top