Mon 'ah-ha!' des moments sur les tests dans Ruby and Rails sont venus quand je me suis vraiment assis et j'ai lu les ressources définitives sur le sujet, les livres Rspec et Cucumber . J'ai partagé votre dédain initial pour le concombre, mais j'ai réalisé que je regardais l'image sous un mauvais angle.
Fondamentalement, Cucumber concerne le BDD (développement axé sur le comportement) - vous utilisez Cucumber pour planifier vos fonctionnalités, sur quoi vous allez travailler ensuite. Hmm, ensuite, vous voulez que les utilisateurs puissent promouvoir des messages sur un forum ou quelque chose (pour voler un exemple;)) Donc, vous écrivez quelque chose de simple.
Given I am logged in
And I can see the post "BDD is awesome"
When I vote the post up
Then the post should have one more vote
And the page should show a message thanking me for my vote.
Notez qu'il n'y a à peu près aucune référence à quelque chose de code. Cela vient dans vos pas. Lorsque vous refactorisez votre code, vous devrez peut-être modifier vos définitions d'étape, mais le comportement (votre fonctionnalité) n'aura jamais besoin de changer.
Maintenant, chaque fois que vous exécutez votre fonctionnalité Cucumber, vous serez à peu près guidé à travers la façon de tester la fonctionnalité à l'aide de TDD (développement piloté par les tests). Cela se fait à un niveau inférieur à l'aide de RSpec.
Première exécution - ma première définition d'étape n'est pas définie. Copiez le bloc pour le définir dans par exemple user_steps.rb ou même session_steps.rb car il concerne les utilisateurs et leurs sessions. Maintenant, comment définissez-vous qu'un utilisateur est connecté? Vous pouvez les suivre via le processus de connexion.
Given /^I am logged in$/ do
visit login_path
fill_in :name, :with => 'Joe'
fill_in :password, :with => 'Password'
click_button 'submit'
end
Devrait être tout heureux. Deuxième étape.
Given /^I can see the post "(.+)"$/ do |name|
visit post_path(Post.find_by_name(name))
end
Encore une fois assez facile. Notez que si nous refaisons totalement notre processus de connexion, ou comment nos messages sont définis et affichés, nous n'avons pas à changer le comportement. Troisième étape.
When /^I vote the post up$/ do
pending
end
Voici où vous commencez à parler de nouvelles fonctionnalités, mais vous ne savez pas encore comment cela va fonctionner. Comment votez-vous pour un article? Vous pouvez cliquer sur une image d'un +1 ou quelque chose, qui envoie un message ajax à un contrôleur, qui renvoie JSON, ou quelque chose du genre. Alors maintenant, vous pouvez passer à des tests Rspec purs.
- Testez votre vue pour vous assurer que l'image +1 est affichée,
- Testez votre contrôleur qu'il se comporte correctement lorsqu'il reçoit une demande ajax donnée du bon format (les chemins heureux et malheureux - que se passe-t-il si un ID de message non valide est reçu? Que se passe-t-il si l'utilisateur a utilisé ses 25 votes positifs en une journée? Augmente-t-il correctement le nombre de votes?)
- Testez votre javascript pour qu'il réponde correctement lorsqu'il reçoit un blob de JSON au bon format (met-il à jour l'image +1 pour montrer qu'il a été utilisé? (En pensant à Google+ ici ...) Est-ce qu'il affiche le message de remerciement? Etc. )
Tout cela n'affecte pas le comportement - mais lorsque vous avez terminé de traiter les tests de niveau inférieur, il sera trivial de remplir la définition d'étape pour savoir comment voter un message. Cela pourrait être aussi simple que click_link '+1'
. Et le reste des étapes consiste à tester les résultats, ce qui devrait encore être simple à faire. Et lorsque vous avez terminé, vous savez que votre fonctionnalité est terminée et terminée. Si le comportement nécessaire change, vous pouvez modifier votre fonctionnalité, sinon vous pouvez modifier votre code d'implémentation en toute sécurité.
J'espère que cela a du sens. Tout cela m'a échappé, mais je pense que cela démontre la différence entre BDD et TDD, et pourquoi le concombre et RSpec répondent à des besoins différents.