2009-10-13 5 views
2

À l'heure actuelle, mon processus de développement des flux comme ceci:Pratiquer le BDD avec des tests d'intégration - ai-je aussi besoin de tests unitaires?

  1. Je décris le comportement attendu comme un test d'intégration à l'aide à l'aide Webrat
  2. Je Recopiez le code Ruby on Rails pour fournir ce comportement, en passant donc le test
  3. Je Refactor, assurant que les tests passent encore à la fin du processus
  4. j'écrire le prochain test d'intégration

Il me semble que par DEFI nition, mes tests d'intégration testent chaque modèle, contrôleur et vue que je peux créer. En réalité, est-ce que je rate quelque chose en n'écrivant pas des tests unitaires aussi?

Répondre

2

Avez-vous des tâches de rake? Code capistrano personnalisé? Méthodes Cron? Une API? Monkeypatches? Qu'en est-il de l'intégration d'applications flex ou iPhone? Un coureur d'emploi?

Dans une application Rails classique, il y a beaucoup de code qui n'est pas utilisé par l'interface utilisateur HTML. Donc non, à moins que votre application ne soit incroyablement simple, les tests webrat ne seront pas suffisants.

+0

Merci Sarah. Jusqu'à présent, non. C'est une application web simple - délibérément simple. À moins que je ne construise du code qui n'est pas exercé par l'interface HTML, je suppose que WebRat est suffisant? Et si je finis par construire du code qui n'est pas exercé par l'interface HTML, j'imagine qu'un test d'intégration (évidemment pas WebRat) sera suffisant? Ou y a-t-il un réel besoin de tester chaque unité séparément en plus de les tester à travers des tests d'intégration? –

+0

Cela dépend de vos objectifs. Si vous utilisez des tests comme un filet de sécurité pour le refactoring, ou comme un moyen d'attraper des bogues lorsque vous ajoutez du code, alors vous aurez toujours besoin de tests unitaires. Aucun ensemble de tests ne testera jamais tout, alors oui, vous aurez ce qui ressemble à des tests redondants. –

3

Les tests d'intégration sont utiles pour vérifier que les différentes parties du code sont bien intégrées. Ils peuvent impliquer toutes les couches et couvrir tout le code mais ... lorsqu'un test d'intégration échoue, vous dira-t-il où se trouve le bogue? Je peux me tromper mais je ne le pense pas. Cela vous dira simplement qu'il y a un problème quelque part. D'un autre côté, quand un vrai test unitaire (écrit à l'aide de mocks ou de stubs) échoue, vous savez exactement dans quelle unité se situe le problème (c'est le but du test unitaire, vérifier qu'une unité implémente le comportement attendu) . En d'autres termes, les tests unitaires et les tests d'intégration sont utiles, mais ils ont des objectifs différents.

+0

Ou, mieux encore écrit en vase clos avec des bouchons. Environ 80-90% des attentes de test de temps sont plus fiables lorsqu'elles sont exécutées sur l'interface. Si deux implémentations d'une méthode prennent les mêmes paramètres et donnent les mêmes valeurs de retour pour tous les paramètres possibles, alors généralement vous voulez que le même ensemble de tests passe pour les deux implémentations. Avec un test double qui n'a pas d'attentes, les tests fonctionneront généralement, mais pas avec des simulacres. –

+0

Les autres 10 à 20% du temps sont généralement des appels d'API ou du code avec des effets secondaires que vous devriez probablement refactoriser de toute façon. –

+0

@Bob c'est vrai et j'aurais dû écrire "écrit en isolation". Je vais mettre à jour ma réponse. Mocks ou des talons, je me fous de cela tant que les tests sont écrits dans l'isolement (et les moqueurs sont surutilisés à mon humble avis). –

8

Je suis plutôt sympathique à votre point de vue ici. J'aime Concombre et J'aime RSpec - et je les utilise tous les deux, mais pas toujours sur le même code. Par exemple, j'écris rarement des exemples RSpec pour les contrôleurs Rails ces jours-ci, et je n'écris presque jamais les spécifications de vue. La plupart de mes contrôleurs sont très similaires et ne s'écartent pas beaucoup du modèle de contrôleur "stock" - qui est déjà bien testé par les tests unitaires de Rails. Vérifier à nouveau le même comportement ne gagne pas grand-chose pour le temps qu'il faut et les tracas de se moquer de tous les modèles. Avec le concombre au niveau de l'intégration, je peux passer cette moquerie et obtenir la vérification essentielle que je recherche. La plupart du temps, les tests de vue sont traités de manière beaucoup plus transparente dans le concombre. (Ensuite, je devrais voir "foo" et ainsi de suite.)

Mais cela ne veut pas dire que je n'utilise pas beaucoup RSpec dans Rails. Je l'utilise pour les endroits où vit ma logique: les modèles, les filtres de contrôleur, et les aides de vue. J'ai également un couple de projets qui sont presque tous logique métier, par exemple. bibliothèques ou adaptateurs d'API sur des interfaces tierces complexes. Pour ceux que je me trouve habituellement en utilisant RSpec exclusivement et en sautant le concombre.

En heuristique, je vous suggère que vous fortement envisager d'écrire un test unitaire tout moment l'une des questions suivantes peut répondre par « oui »:

  • est le code que je vous écris plus que trivialement compliqué?
  • Est-ce que ce code existe principalement pour donner des réponses à d'autres codes?
  • Ce code existe-t-il que je refaçonne (qui n'a pas encore de test unitaire)?
  • Ai-je trouvé un bogue dans ce code? (Si c'est le cas, écrivez un test unitaire avant de le réparer pour qu'il ne se faufile plus jamais.)
  • Dois-je penser pendant plus de dix secondes à la façon la plus élégante d'implémenter ce code?
  • Est-ce que mon picotement Spidey Sense?

Si aucune de ce qui précède est vrai, alors peut-être vous pouvez vous contenter de faire juste des tests d'intégration. Encore une fois, il y a beaucoup de cas où c'est raisonnable. Mais si vous rencontrez des problèmes plus tard, soyez prêt à payer le prix - et ce prix devrait inclure l'écriture de tests unitaires à tout moment si elles semblent nécessaires.

+0

+1 pour éviter les spécifications sur les contrôleurs et les vues. Unité de tester les appels de contrôleur de service Web, les modèles et d'autres éléments dans 'lib', mais sinon laissez-le à Cucumber. –