Tests unitaires avec Capcode
S’il y a bien un aspect, lors de la mise en place d’une application, qui obsède les développeurs, ce sont bien les tests. Et à juste titre. Au point que nous trouvons aujourd’hui de plus en plus d’équipes qui travaillent en TDD, contre toutes les lois qui nous ont été enseignées lors de nos études. L’écriture de tests unitaires peut paraitre rébarbative, cela n’est reste pas moins une très bonne habitude à prendre pour éviter par la suite de longues heures à rechercher les bugs les plus vicieux que nous avons cachés dans notre code. Je vous propose donc de voir comment faire des tests unitaires avec Capcode.
Comme vous le savez, Capcode est basé sur Rack et il existe pour ce dernier le projet Rack::Test, idéal pour ce que nous aider dans ce travail.
partons d’un exemple minimaliste :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # sample.rb require 'rubygems' require 'capcode' module Capcode class Index < Route '/' def get render "Hello World" end end class Redir < Route '/r' def get redirect( Index ) end end end |
Vous remarquerez que je n’ai volontairement pas mis l’appel à Capcode.run dans ce code. Ceci pour deux raisons. J’ai pris l’habitude de déporter cet appel dans un fichier à part ce qui me permet de créer en parallèle un fichier de configuration rackup pour le déploiement avec Passenger. De plus, Rack::Test sert à tester des applications basées sur Rack et implique d’avoir accès directement à l’application, celle-là même que vous passez à votre handler.
Rack::Test fonctionne avec Test::Unit, nous allons dons créer, pour chaque ensemble de tests, une classe héritant de Test::Unit::TestCase et nous inclurons dans cette classe le module Rack::Test::Methods :
1 2 3 4 5 6 7 8 9 10 11 | # test_sample.rb require 'rubygems' require 'test/unit' require 'rack/test' class HomepageTest < Test::Unit::TestCase include Rack::Test::Methods # ... end |
Comme je l’ai signalé, l’utilisation de Rack::Test implique que nous ayons accès à l’application. Nous allons donc la charger et faire en sorte qu’elle soit accessible dans la classe via la méthode app :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # test_sample.rb require 'rubygems' require 'test/unit' require 'rack/test' require 'sample.rb' @@app = Capcode.application( ) class HomepageTest < Test::Unit::TestCase include Rack::Test::Methods def app @@app end # ... end |
Nous pouvons ensuite ajouter nos tests. Chaque test est décrit dans une méthode de la classe, ces méthodes pouvant contenir autant d’assertions que nécessaire :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # test_sample.rb require 'rubygems' require 'test/unit' require 'rack/test' require 'sample.rb' @@app = Capcode.application( ) class HomepageTest < Test::Unit::TestCase include Rack::Test::Methods def app @@app end def test_home get '/' assert_equal "http://example.org/", last_request.url assert last_response.ok? assert_equal "Hello World", last_response.body end def test_redirect get '/r' assert_equal "http://example.org/r", last_request.url follow_redirect! assert_equal "http://example.org/", last_request.url assert_equal "Hello World", last_response.body end end |
Si vous exécutez test_sample.rb vous devriez obtenir la sortie suivante :
Loaded suite /Users/greg/dev/Capcode/tests/test_sample Started .. Finished in 0.005839 seconds. 2 tests, 6 assertions, 0 failures, 0 errors
Pour les assertions, vous pouvez utiliser tout ce que propose Test::Unit. Pour la partie « navigation », Rack::Test vous offre les méthodes suivantes :
- get, post, put, delete et head permettent respectivement de faire des requêtes de type GET, POST, PUT, DELETE et HEAD. Chacune de ces méthodes prend en paramètre l’URI à tester, mais également les paramètres, sous forme de hachage et éventuellement des données d’environnement (également sous forme de hachage).
post '/login', {"user" => "greg", "password" => "s3cr3t"}
- header permet de positionner la valeur d’une entête
header "User-Agent", "Firefox"
- basic_authorize et digest_authorize permettent de donner le login et le mot de passe pour, respectivement, une authentification basic ou digest.
digest_authorize( "greg", "p4ssw0rd" )
- follow_redirect! permet de suivre la dernière redirection renvoyée.
- set_cookie et clear_cookie permettent de gérer les cookies.
- last_request correspond à la dernière requête. C’est une instance de Rack::Request.
- last_response correspond à la dernière réponse, c’est une instance de Rack::MockResponse.
Tags: Capcode, Ruby, TDD, Tests

[...] This post was Twitted by glejeune [...]