Ruby : Test Unitaire

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

  {% highlight ruby %}
    require "test/unit"
  {% endhighlight %}

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

  {% highlight bash %}
    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
  {% endhighlight %}

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

Ajoutons un test maintenant

  {% highlight ruby %}
  require "test/unit"

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

  {% endhighlight %}

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:

  {% highlight bash %}
  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
  {% endhighlight %}

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

Ajoutons encore un test pour avancer:

  {% highlight ruby %}
  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

  {% endhighlight %}

Après exécution nous obtenons:

  {% highlight ruby %}
  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
  {% endhighlight %}

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:

  {% highlight ruby %}
  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
  {% endhighlight %}

exécution du test:

  {% highlight ruby %}
  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
  {% endhighlight %}

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