Ruby : Test Unitaire 5

Publié par Yannick Francois Ven 15 août 2008 12:41:00 GMT

Ruby bénéficie comme beaucoup d’autres langages modernes de son framework de test. Voici donc une petite documentation sur comment écrire un test unitaire pour Ruby.

Pour ceux qui ne savent pas ce qu’est un test unitaire, je vous renvoie sur l’article Test Unitaire [wikipedia]

Pour commencer il nous faut importer la librairie “Test::Unit”

require "test/unit" 

Rien que cela nous permet déjà de faire un premier test en executant notre script.

yannick@libellule:~/Code/RubyFrance/testUnit $ ruby testUnit.rb
Loaded suite testUnit
Started

Finished in 0.000607 seconds.

0 test, 0 assertions, 0 failures, 0 errors

Le fait d’inclure la librairie de test unitaire permet d’avoir un comportement par défaut qui va:

  • Charger la suite de test à executer
  • lancer les tests
  • faire l’affichage des resultats de test
  • faire un compte rendu de cette execution

Ajoutons un test maintenant

require "test/unit" 

class StringTest < Test::Unit::TestCase
  def test_length
    s = "Bon test à tous !" 
    assert_equal(17, s.length)
  end
end

Nous avons défini une classe, celle-ci doit étendre TestCase. Cela permet au framework de test de s’y retrouver. Chaque méthode de test définie ensuite doit contenir test en début de nom (le caractère _ n’est placé que pour une meilleur lisibilité et selon les conventions couramment appliquées en Ruby)

Les méthodes assert (ici assert_equal, mais il en existe beaucoup d’autres) permettent d’effectuer un test. Ici un test d’égalité, mais nous pourrions également vérifié une différence, un bouléen répondant vrai ou faux et d’autres encore (voir la documentation sur le module Test::Unit::Assertions).

Après execution, voici le résultat:

yannick@libellule:~/Code/RubyFrance/testUnit $ ruby testUnit.rb
Loaded suite testUnit
Started
.
Finished in 0.000802 seconds.

1 test, 1 assertions, 0 failures, 0 errors

Un test a été executé avec succès.

Ajoutons encore un test pour avancer:

require "test/unit" 

class StringTest < Test::Unit::TestCase
  def test_length
    s = "Bon test à tous !" 
    assert_equal(17, s.length)
  end
  def test_expression_substitution
    assert_equal("", "#{'ah! ' * 3}")
  end
end

Après exécution nous obtenons:

yannick@libellule:~/Code/RubyFrance/testUnit $ ruby testUnit.rb
Loaded suite testUnit
Started
F.
Finished in 0.000827 seconds.

  1) Failure:
test_expression_substitution(StringTest) [testUnit.rb:12]:
<""> expectedbut was
<"ah! ah! ah! ">.
2 test, 2 assertions, 1 failures, 0 errors

Et voilà, comme vous l’aviez deviné, nous avons une erreur. Dans notre cas, l’erreur viens de notre test.

On vois ici l’interêt de mettre chaque test sur un domaine différent dans une méthode différente: on vois facilement quel type de test nous voulions effectuer. Dans le développement d’une application complète, avec plusieurs dizaines d’objets à tester, et plusieurs dizaines de méthodes sur chacun d’eux, les erreurs d’exécution de test peuvent devenir un vrai casse-tête.

Effectuons la correction:

require "test/unit" 

class StringTest < Test::Unit::TestCase
  def test_length
    s = "Bon test à tous !" 
    assert_equal(17, s.length)
  end
  def test_expression_substitution
    assert_equal("ah! ah! ah! ", "#{'ah! ' * 3}")
  end
end

exécution du test:

yannick@libellule:~/Code/RubyFrance/testUnit $ ruby testUnit.rb
Loaded suite testUnit
Started
..
Finished in 0.001273 seconds.

2 test, 2 assertions, 0 failures, 0 errors

Et voilà. Vous devriez être capables de commencer à écrire quelques tests, mais ce n’est qu’un début !.

Cet article a été écrit pour le site de l’association RubyFrance, vous pourrez le retrouver dans les documentations proposées par l’association: RubyFrance: TestUnitaire

Commentaires

laisser un commentaire

  1. Avatar
    jean-mi about 5 hours plus tard:

    Tiens tu es passé sur DragonflyBSD ?

    Autrement merci de rajouter des docs dans rubyfrance. Mais tu sais, si j’ai mis des catégories pour classer les articles pendant la migration du instiki vers le radiant c’est pas sans raisons :).

    Va falloir faire un peu de rangement :D. Il faut que je retrouve mes identifiants.

  2. Avatar
    Yannick Francois about 21 hours plus tard:

    Non, Libellule c’est le nom de ma machine, mais elle est toujours sous OpenBSD 4.4-beta :p

    Pour les docs de RubyFrance, tu n’as cas lire la mailing list, j’ai proposé un nouveau rangements pour justement que ce soit plus clair et simple.

    Si tu as des objections parlons-en sur la mailing list :-)

  3. Avatar
    Sobe about 23 hours plus tard:

    Merci beaucoup pour cet article très clair sur les tests unitaires (faut que je m’y mette, faut que je m’y mette !!!).

    C’est juste dommage que tu n’aies pas mis un cas d’erreur pour voir le comportement de la suite de tests dans ce cas là. Du coup, ce serait complet.

    Par ailleurs, je me permets de te proposer quelques corrections orthographiques (quelques coquilles t’ont échappé…) sur cette page.

  4. Avatar
    Yannick 1 day plus tard:

    Merci Sobe pour les corrections orthographiques (je les aient également reportées sur le site de l’asso).

    Par contre tu es passé à coté du cas d’erreur:

    yannick@libellule:~/Code/RubyFrance/testUnit $ ruby testUnit.rb
    Loaded suite testUnit
    Started
    F.
    Finished in 0.000827 seconds.
    
      1) Failure:
    test_expression_substitution(StringTest) [testUnit.rb:12]:
    <""> expectedbut was
    <"ah! ah! ah! ">.
    2 test, 2 assertions, 1 failures, 0 errors
    

    Même si je te l’accorde, c’est un peu basique.

    Ta remarque entraînera sûrement un autre article sur les cas d’erreur ;-)

  5. Avatar
    Sobe 1 day plus tard:

    Pardon, je me suis mal exprimé : je parlais des cas d’”exceptions” : genre un test sur une méthode non-valide/buggée. Dans ce cas, je suppose que TestUnit le passe en “errors” plutôt que “failures”, mais dans ce cas, l’interpréteur passe-t-il les tests suivants ? (j’ai qu’à essayer me diras-tu…).

Commentaires