Xavier Nayrac

Rubyiste accro au TDD, serial blogger, apprenti data scientist, heureux utilisateur de Vim, accordéoniste.
Si vous vous sentez particulièrement généreux, suivez moi sur Twitter.

Tester facilement vos dates avec Timecop

| Comments

Niveau : facile

Timecop n’est pas une nouvelle gem. Mais je ne la découvre qu’aujourd’hui. Ça fait pourtant 4 ans que je travaille quotidiennement avec Ruby et/ou Rails… Et je ne me suis jamais sentis très à l’aise pour tester les dates. Avec Timecop, ça devient un jeu d’enfant.

Pour voir un souci possible, prenons la classe suivante qui représente un article:

article.rb
1
2
3
4
5
6
7
8
class Article
  def initialize(name)
    @name = name
    @created_at = Time.now
  end

  attr_reader :name, :created_at
end

Dans le monde réel, ce serait surement un ActiveRecord, mais pour l’exemple on se contentera bien de cette classe ;)

Maintenant testons la création d’un article:

tc_article.rb
1
2
3
4
5
6
7
8
9
10
require_relative "article"
require "test/unit"

class TestArticle < Test::Unit::TestCase
  def test_creation
    article = Article.new('Foo')
    assert_equal 'Foo', article.name
    assert_equal Time.now, article.created_at
  end
end

Et voilà le souci, à quelques nano-secondes près ça pète:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ruby tc_article.rb
Run options:

# Running tests:

[1/1] TestArticle#test_creation = 0.00 s
  1) Failure:
TestArticle#test_creation [tc_article.rb:8]:
<2014-04-01 21:05:10 +0200> (204201[ns]) expected but was
<2014-04-01 21:05:10 +0200> (176685[ns]).

Finished tests in 0.009979s, 100.2062 tests/s, 200.4125 assertions/s.
1 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Timecop est la meilleure solution que j’ai vu jusqu’ici pour régler ce type de problème. La gem propose tout simplement (entre autres) de geler le temps:

tc_article.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
require_relative "article"
require "test/unit"
require "timecop"

class TestArticle < Test::Unit::TestCase
  def test_creation
    Timecop.freeze do
      article = Article.new('Foo')
      assert_equal 'Foo', article.name
      assert_equal Time.now, article.created_at
    end
  end
end

Et voilà le résultat:

1
2
3
4
5
6
7
ruby tc_article.rb
Run options:

# Running tests:

Finished tests in 0.010756s, 92.9747 tests/s, 185.9494 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips

J’aimerais bien savoir quelles solutions vous avez adoptés pour régler ce genre de soucis…

À demain.

Articles connexes

Commentaires