Quelles sont les écoles de TDD à Londres et à Chicago?

88

J'ai entendu parler du style TDD (Test Driven Development) de Londres contre Chicago (parfois appelé style de Detroit).

Atelier du groupe d'utilisateurs de programmation extrême d'Utah:

Le TDD de style interaction est aussi appelé style mockist , ou style londonien après le club londonien Extreme Tuesday où il est devenu populaire. Cela contraste généralement avec le TDD classique ou de style Detroit, qui est davantage basé sur les états.

L'atelier de Jason Gorman :

L’atelier couvre à la fois l’ école TDD de Chicago (tests de comportement et triangulation) et l’ école de Londres , qui se concentre plus sur les tests d’interaction, les moqueries et la TDD de bout en bout, avec un accent particulier sur la conception axée sur la responsabilité et la L' approche de Tell, Don't Ask à OO a été récemment popularisée à nouveau par l'excellent livre Guided By Tests de Steve Freeman et Nat Pryce .

Le post classique TDD ou "London School"? par Jason Gorman a été utile, mais ses exemples m'ont confondu, car il utilise deux exemples différents au lieu d'un exemple avec les deux approches. Quelles sont les différences? Quand utilisez-vous chaque style?

Arturo Herrero
la source

Réponses:

76

Supposons que vous avez classe appelée "grand livre" une méthode appelée "calculer" qui utilise une "calculatrice" pour effectuer différents types de calcul en fonction des arguments passés à "calculer", par exemple "multiplier (x, y)" ou "soustraire ( x, y) ".

Supposons maintenant que vous souhaitiez tester ce qui se passe lorsque vous appelez ledger.calculate ("5 * 7").

L'école London / Interaction voudrait vous demander si Calculator.multiply (5,7) a été appelé. Les divers frameworks moqueurs sont utiles pour cela, et cela peut être très utile si, par exemple, vous n'êtes pas propriétaire de l'objet "Calculatrice" (supposons qu'il s'agisse d'un composant ou d'un service externe que vous ne pouvez pas tester directement, mais vous sais que tu dois appeler d’une manière particulière).

La Chicago / State School voudrait que vous affirmiez si le résultat est 35. Les cadres jUnit / nUnit sont généralement conçus pour cela.

Les deux sont des tests valides et importants.

Matthew Flynn
la source
Très bel exemple.
Sevenseacat
1
J'ajouterai quelques raisons supplémentaires pour utiliser chacune d'elles: Si l'important est de déterminer si quelque chose a changé ou non en fonction de l'action entreprise (par exemple, ledger.bucket.value devenant 35 lorsque ledger.calculate ("5 * 7 ") s’appelle), vous souhaitez utiliser des affirmations d’État (école de Chicago). Ceci est particulièrement utile lorsque vous avez le contrôle total de l’état du système avant l’appel de la méthode et que vous contrôlez réellement ce que fait la méthode.
Matthew Flynn
1
Si l'important est de savoir qu'une deuxième méthode est appelée (par exemple, Calculator.multiply (5, 7)), vous souhaitez utiliser des assertions d'activité, comme via un objet fictif. Ceci est particulièrement utile si la méthode appelée a un effet secondaire souhaité (par exemple, enregistrer des données, incrémenter un compteur, envoyer un message, etc.) ou si vous ne contrôlez pas réellement le fonctionnement de la méthode, ainsi la valeur renvoyée risque d'être incohérente. . En outre, si vous ne pouvez pas contrôler facilement l’état du système, le mieux que vous puissiez faire est de déterminer quelles activités se déroulent.
Matthew Flynn
L'approche de London est utile lorsque la classe Calculator est potentiellement longue pour une raison quelconque, ou implique un réseau et peut donc être floue dans les configurations dev / qa. Cela signifie que vos tests sont rapides et fiables dans les cas où cela ne serait pas possible autrement.
Kevin
1
L’approche de Londres préconise également de fournir des signaux de rétroaction plus clairs, car si la Calculatorrégression s’effectue multiply, deux tests échouent: le test du grand livre et le test de la calculatrice, mais un seul test échoue si vous simulez la calculatrice. Cela pourrait faciliter la localisation de l'origine du bogue, surtout si le système est complexe.
Matthias
30

L'article de Mock Art Stubs , de Martin Fowler, est une bonne introduction au sujet.

Selon le style de conception que vous choisissez (et les principes de conception sur lesquels vous construisez vos programmes), il existe au moins deux façons de voir un objet:

  1. En tant qu’unité effectuant des calculs à partir d’entrées. À la suite de ce calcul, l’objet peut renvoyer une valeur ou changer d’état.
  2. En tant qu'élément actif qui communique avec d'autres éléments du système en transmettant des messages.

Dans le premier cas, vous êtes intéressé par ce qui sort du traitement ou dans quel état l'objet est laissé après ce traitement. C'est ici que des méthodes telles que assertEquals()saisir l'image. Dans ce cas, peu importe quels autres objets ont été impliqués dans le traitement, quelles méthodes ont été appelées, etc. Ce type de vérification est appelé vérification basée sur l'état et correspond au style "classique".

Dans le second cas, étant donné que la plupart des objets ne renvoient même pas de résultat (par exemple, des voidméthodes en Java), vous êtes plus intéressé par la façon dont les objets communiquent et par lesquels ils transmettent les bons messages dans les circonstances imposées par le test. Ces interactions sont généralement vérifiées à l'aide de faux cadres. Ce type de vérification s'appelle vérification basée sur le comportement ou basée sur l'interaction. L'une de ses implications est la technique appelée Behavior Driven Development, qui permet de développer une classe en supposant que ses collaborateurs existent déjà (même s'ils n'existent pas encore), ce qui vous permet de coder leurs interfaces.

Notez que ce n'est pas un choix /. Vous pouvez avoir un style qui associe les deux approches pour tirer le meilleur parti de chacune d’elles.

Otavio Macedo
la source