timecop 0.3.5 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.markdown +100 -0
- data/Rakefile +10 -37
- data/VERSION.yml +2 -2
- data/lib/timecop/time_extensions.rb +2 -1
- data/lib/timecop/time_stack_item.rb +31 -15
- data/lib/timecop/timecop.rb +43 -17
- data/test/run_tests.sh +3 -10
- data/test/test_helper.rb +5 -1
- data/test/{test_time_stack_item.rb → time_stack_item_test.rb} +29 -13
- data/test/{test_timecop.rb → timecop_test.rb} +95 -34
- data/test/{test_timecop_without_date_but_with_time.rb → timecop_without_date_but_with_time_test.rb} +0 -0
- data/test/{test_timecop_without_date.rb → timecop_without_date_test.rb} +3 -3
- metadata +40 -54
- data/README.rdoc +0 -68
data/LICENSE
CHANGED
data/README.markdown
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# timecop
|
2
|
+
|
3
|
+
- Source[http://github.com/jtrupiano/timecop]
|
4
|
+
- Documentation[http://johntrupiano.rubyforge.org/timecop]
|
5
|
+
|
6
|
+
## DESCRIPTION
|
7
|
+
|
8
|
+
A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.
|
9
|
+
|
10
|
+
## INSTALL
|
11
|
+
|
12
|
+
gem install timecop
|
13
|
+
|
14
|
+
## FEATURES
|
15
|
+
|
16
|
+
- Freeze time to a specific point.
|
17
|
+
- Travel back to a specific point in time, but allow time to continue moving forward from there.
|
18
|
+
- No dependencies, can be used with _any_ ruby project
|
19
|
+
- Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
|
20
|
+
- Time instance
|
21
|
+
- DateTime instance
|
22
|
+
- Date instance
|
23
|
+
- individual arguments (year, month, day, hour, minute, second)
|
24
|
+
- a single integer argument that is interpreted as an offset in seconds from Time.now
|
25
|
+
- Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
|
26
|
+
- Works with regular Ruby projects, and Ruby on Rails projects
|
27
|
+
|
28
|
+
## USAGE
|
29
|
+
|
30
|
+
Run a time-sensitive test
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
joe = User.find(1)
|
34
|
+
joe.purchase_home()
|
35
|
+
assert !joe.mortgage_due?
|
36
|
+
# move ahead a month and assert that the mortgage is due
|
37
|
+
Timecop.freeze(Date.today + 30) do
|
38
|
+
assert joe.mortgage_due?
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Set the time for the test environment of a rails app -- this is particularly
|
43
|
+
helpful if your whole application is time-sensitive. It allows you to build
|
44
|
+
your test data at a single point in time, and to move in/out of that time as
|
45
|
+
appropriate (within your tests)
|
46
|
+
|
47
|
+
in config/environments/test.rb
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
config.after_initialize do
|
51
|
+
# Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
|
52
|
+
t = Time.local(2008, 9, 1, 10, 5, 0)
|
53
|
+
Timecop.travel(t)
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
### The difference between Timecop.freeze and Timecop.travel
|
58
|
+
|
59
|
+
freeze is used to statically mock the concept of now. As your program executes,
|
60
|
+
Time.now will not change unless you make subsequent calls into the Timecop API.
|
61
|
+
travel, on the other hand, computes an offset between what we currently think
|
62
|
+
Time.now is (recall that we support nested traveling) and the time passed in.
|
63
|
+
It uses this offset to simulate the passage of time. To demonstrate, consider
|
64
|
+
the following code snippets:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
new_time = Time.local(2008, 9, 1, 12, 0, 0)
|
68
|
+
Timecop.freeze(new_time)
|
69
|
+
sleep(10)
|
70
|
+
new_time == Time.now # ==> true
|
71
|
+
|
72
|
+
Timecop.return # "turn off" Timecop
|
73
|
+
Timecop.travel(new_time)
|
74
|
+
sleep(10)
|
75
|
+
new_time == Time.now # ==> false
|
76
|
+
```
|
77
|
+
|
78
|
+
## REFERENCES
|
79
|
+
|
80
|
+
* {0.3.4 release}[http://blog.smartlogicsolutions.com/2009/12/07/timecop-0-3-4-released/]
|
81
|
+
* {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
|
82
|
+
* {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
|
83
|
+
* {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
|
84
|
+
|
85
|
+
## Contribute
|
86
|
+
|
87
|
+
timecop is maintained by [travisjeffery](http://github.com/travisjeffery), who
|
88
|
+
you can also hit up on [Twitter](http://twitter.com/travisjeffery).
|
89
|
+
|
90
|
+
Here's the most direct way to get your work merged into the project.
|
91
|
+
|
92
|
+
- Fork the project
|
93
|
+
- Clone down your fork
|
94
|
+
- Create a feature branch
|
95
|
+
- Hack away and add tests, not necessarily in that order
|
96
|
+
- Make sure everything still passes by running tests
|
97
|
+
- If necessary, rebase your commits into logical chunks without errors
|
98
|
+
- Push the branch up to your fork
|
99
|
+
- Send a pull request for your branch
|
100
|
+
|
data/Rakefile
CHANGED
@@ -1,42 +1,10 @@
|
|
1
|
-
require '
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
2
3
|
require 'rake/testtask'
|
3
|
-
require '
|
4
|
+
require 'rdoc/task'
|
4
5
|
|
5
|
-
|
6
|
+
$LOAD_PATH.unshift("lib")
|
6
7
|
|
7
|
-
begin
|
8
|
-
require 'jeweler'
|
9
|
-
Jeweler::Tasks.new do |s|
|
10
|
-
s.name = "timecop"
|
11
|
-
s.rubyforge_project = 'johntrupiano' # if different than lowercase project name
|
12
|
-
s.description = %q(A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.)
|
13
|
-
s.summary = s.description # More details later??
|
14
|
-
s.email = "jtrupiano@gmail.com"
|
15
|
-
s.homepage = "http://github.com/jtrupiano/timecop"
|
16
|
-
s.authors = ["John Trupiano"]
|
17
|
-
s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
|
18
|
-
end
|
19
|
-
Jeweler::GemcutterTasks.new
|
20
|
-
Jeweler::RubyforgeTasks.new do |rubyforge|
|
21
|
-
rubyforge.doc_task = "rdoc"
|
22
|
-
rubyforge.remote_doc_path = "timecop"
|
23
|
-
end
|
24
|
-
rescue LoadError
|
25
|
-
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
26
|
-
end
|
27
|
-
|
28
|
-
# Override the test task and instruct them how to actually run the tests.
|
29
|
-
Rake.application.send(:eval, "@tasks.delete('test')")
|
30
|
-
desc "Does not execute tests. Manually run shell script ./run_tests.sh to execute tests."
|
31
|
-
task :test do
|
32
|
-
puts <<-MSG
|
33
|
-
In order to run the test suite, run: cd test && ./run_tests.sh
|
34
|
-
The tests need to be run with different libraries loaded, which rules out using Rake
|
35
|
-
to automate them.
|
36
|
-
MSG
|
37
|
-
end
|
38
|
-
|
39
|
-
require 'rake/rdoctask'
|
40
8
|
Rake::RDocTask.new do |rdoc|
|
41
9
|
if File.exist?('VERSION')
|
42
10
|
version = File.read('VERSION')
|
@@ -52,4 +20,9 @@ Rake::RDocTask.new do |rdoc|
|
|
52
20
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
21
|
end
|
54
22
|
|
55
|
-
task :
|
23
|
+
task :test do
|
24
|
+
system "cd test && ./run_tests.sh"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Default: run tests'
|
28
|
+
task :default => [:test]
|
data/VERSION.yml
CHANGED
@@ -17,6 +17,7 @@ class Time #:nodoc:
|
|
17
17
|
|
18
18
|
# Alias now to now_with_mock_time
|
19
19
|
alias_method :now, :now_with_mock_time
|
20
|
+
alias_method :new, :now
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
@@ -69,4 +70,4 @@ if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now)
|
|
69
70
|
alias_method :now, :now_with_mock_time
|
70
71
|
end
|
71
72
|
end
|
72
|
-
end
|
73
|
+
end
|
@@ -10,7 +10,7 @@ class Timecop
|
|
10
10
|
@mock_type = mock_type
|
11
11
|
@time = parse_time(*args)
|
12
12
|
@travel_offset = compute_travel_offset
|
13
|
-
@dst_adjustment = compute_dst_adjustment
|
13
|
+
@dst_adjustment = compute_dst_adjustment(@time)
|
14
14
|
end
|
15
15
|
|
16
16
|
def year
|
@@ -60,7 +60,9 @@ class Timecop
|
|
60
60
|
def datetime
|
61
61
|
# DateTime doesn't know about DST, so let's remove its presence
|
62
62
|
our_offset = utc_offset + dst_adjustment
|
63
|
-
|
63
|
+
fractions_of_a_second = time.to_f % 1
|
64
|
+
DateTime.new(year, month, day, hour, min, sec + fractions_of_a_second,
|
65
|
+
utc_offset_to_rational(our_offset))
|
64
66
|
end
|
65
67
|
|
66
68
|
def dst_adjustment
|
@@ -77,28 +79,42 @@ class Timecop
|
|
77
79
|
end
|
78
80
|
|
79
81
|
def parse_time(*args)
|
82
|
+
time_klass = Time
|
83
|
+
time_klass = Time.zone if Time.respond_to? :zone
|
80
84
|
arg = args.shift
|
81
85
|
if arg.is_a?(Time)
|
82
|
-
arg.
|
86
|
+
if arg.respond_to?(:in_time_zone)
|
87
|
+
arg.in_time_zone
|
88
|
+
else
|
89
|
+
arg.getlocal
|
90
|
+
end
|
83
91
|
elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime)
|
84
|
-
|
85
|
-
|
92
|
+
expected_time = time_klass.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec)
|
93
|
+
expected_time += expected_time.utc_offset - rational_to_utc_offset(arg.offset)
|
94
|
+
expected_time + compute_dst_adjustment(expected_time)
|
86
95
|
elsif Object.const_defined?(:Date) && arg.is_a?(Date)
|
87
|
-
|
96
|
+
time_klass.local(arg.year, arg.month, arg.day, 0, 0, 0)
|
88
97
|
elsif args.empty? && arg.kind_of?(Integer)
|
89
98
|
Time.now + arg
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
99
|
+
elsif arg.nil?
|
100
|
+
Time.now
|
101
|
+
else
|
102
|
+
if Time.respond_to?(:parse)
|
103
|
+
Time.parse(arg)
|
104
|
+
else
|
105
|
+
# we'll just assume it's a list of y/m/d/h/m/s
|
106
|
+
year = arg || 2000
|
107
|
+
month = args.shift || 1
|
108
|
+
day = args.shift || 1
|
109
|
+
hour = args.shift || 0
|
110
|
+
minute = args.shift || 0
|
111
|
+
second = args.shift || 0
|
112
|
+
time_klass.local(year, month, day, hour, minute, second)
|
113
|
+
end
|
98
114
|
end
|
99
115
|
end
|
100
116
|
|
101
|
-
def compute_dst_adjustment
|
117
|
+
def compute_dst_adjustment(time)
|
102
118
|
return 0 if !(time.dst? ^ Time.now.dst?)
|
103
119
|
return -1 * 60 * 60 if time.dst?
|
104
120
|
return 60 * 60
|
data/lib/timecop/timecop.rb
CHANGED
@@ -6,13 +6,13 @@ require 'timecop/time_stack_item'
|
|
6
6
|
# * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
|
7
7
|
# * Allows us to "freeze" time in our Ruby applications.
|
8
8
|
# * Optionally allows time travel to simulate a running clock, such time is not technically frozen.
|
9
|
-
#
|
10
|
-
# This is very useful when your app's functionality is dependent on time (e.g.
|
9
|
+
#
|
10
|
+
# This is very useful when your app's functionality is dependent on time (e.g.
|
11
11
|
# anything that might expire). This will allow us to alter the return value of
|
12
12
|
# Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
|
13
13
|
class Timecop
|
14
14
|
include Singleton
|
15
|
-
|
15
|
+
|
16
16
|
# Allows you to run a block of code and "fake" a time throughout the execution of that block.
|
17
17
|
# This is particularly useful for writing test methods where the passage of time is critical to the business
|
18
18
|
# logic being tested. For example:
|
@@ -32,16 +32,16 @@ class Timecop
|
|
32
32
|
# 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
|
33
33
|
#
|
34
34
|
# When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
|
35
|
-
# previous values after the block has finished executing. This allows us to nest multiple
|
35
|
+
# previous values after the block has finished executing. This allows us to nest multiple
|
36
36
|
# calls to Timecop.travel and have each block maintain it's concept of "now."
|
37
37
|
#
|
38
38
|
# * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
|
39
39
|
# benchmark or other timing calls are executed, which implicitly expect Time to actually move
|
40
40
|
# forward.
|
41
41
|
#
|
42
|
-
# * Rails Users: Be especially careful when setting this in your development environment in a
|
43
|
-
# rails project. Generators will load your environment, including the migration generator,
|
44
|
-
# which will lead to files being generated with the timestamp set by the Timecop.freeze call
|
42
|
+
# * Rails Users: Be especially careful when setting this in your development environment in a
|
43
|
+
# rails project. Generators will load your environment, including the migration generator,
|
44
|
+
# which will lead to files being generated with the timestamp set by the Timecop.freeze call
|
45
45
|
# in your dev environment
|
46
46
|
#
|
47
47
|
# Returns the frozen time.
|
@@ -49,7 +49,7 @@ class Timecop
|
|
49
49
|
instance().send(:travel, :freeze, *args, &block)
|
50
50
|
Time.now
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# Allows you to run a block of code and "fake" a time throughout the execution of that block.
|
54
54
|
# See Timecop#freeze for a sample of how to use (same exact usage syntax)
|
55
55
|
#
|
@@ -61,7 +61,15 @@ class Timecop
|
|
61
61
|
instance().send(:travel, :travel, *args, &block)
|
62
62
|
Time.now
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
|
+
def self.baseline
|
66
|
+
instance().send(:baseline)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.baseline=(baseline)
|
70
|
+
instance().send(:baseline=, baseline)
|
71
|
+
end
|
72
|
+
|
65
73
|
# Reverts back to system's Time.now, Date.today and DateTime.now (if it exists).
|
66
74
|
#
|
67
75
|
# Returns Time.now, which is now the real current time.
|
@@ -69,35 +77,53 @@ class Timecop
|
|
69
77
|
instance().send(:unmock!)
|
70
78
|
Time.now
|
71
79
|
end
|
72
|
-
|
80
|
+
|
81
|
+
def self.return_to_baseline
|
82
|
+
instance().send(:return_to_baseline)
|
83
|
+
Time.now
|
84
|
+
end
|
85
|
+
|
73
86
|
def self.top_stack_item #:nodoc:
|
74
87
|
instance().instance_variable_get(:@_stack).last
|
75
88
|
end
|
76
89
|
|
77
90
|
protected
|
78
|
-
|
91
|
+
|
92
|
+
def baseline=(baseline)
|
93
|
+
@baseline = baseline
|
94
|
+
@_stack << TimeStackItem.new(:travel, baseline)
|
95
|
+
end
|
96
|
+
|
79
97
|
def initialize #:nodoc:
|
80
98
|
@_stack = []
|
81
99
|
end
|
82
|
-
|
100
|
+
|
83
101
|
def travel(mock_type, *args, &block) #:nodoc:
|
84
102
|
stack_item = TimeStackItem.new(mock_type, *args)
|
85
|
-
|
103
|
+
|
86
104
|
# store this time traveling on our stack...
|
87
105
|
@_stack << stack_item
|
88
|
-
|
106
|
+
|
89
107
|
if block_given?
|
90
108
|
begin
|
91
|
-
yield
|
109
|
+
yield stack_item.time
|
92
110
|
ensure
|
93
111
|
# pull it off the stack...
|
94
112
|
@_stack.pop
|
95
113
|
end
|
96
114
|
end
|
97
115
|
end
|
98
|
-
|
116
|
+
|
99
117
|
def unmock! #:nodoc:
|
118
|
+
@baseline = nil
|
100
119
|
@_stack = []
|
101
120
|
end
|
102
|
-
|
121
|
+
|
122
|
+
def return_to_baseline
|
123
|
+
if @baseline
|
124
|
+
@_stack = [@_stack.shift]
|
125
|
+
else
|
126
|
+
unmock!
|
127
|
+
end
|
128
|
+
end
|
103
129
|
end
|
data/test/run_tests.sh
CHANGED
@@ -1,13 +1,6 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
|
3
|
-
|
4
|
-
ruby -I../lib
|
3
|
+
for f in *_test.rb; do
|
4
|
+
${RUBY:-ruby} -I../lib:. $f
|
5
|
+
done
|
5
6
|
|
6
|
-
echo "\033[1;81m Running test_timecop_without_date...\033[0m"
|
7
|
-
ruby -I../lib test_timecop_without_date.rb || (echo "FAILED!!!!!!!!!!!!")
|
8
|
-
|
9
|
-
echo "\033[1;81m Running test_timecop_without_date_but_with_time...\033[0m"
|
10
|
-
ruby -I../lib test_timecop_without_date_but_with_time.rb || (echo "FAILED!!!!!!!!!!!!")
|
11
|
-
|
12
|
-
echo "\033[1;81m Running test_timecop...\033[0m"
|
13
|
-
ruby -I../lib test_timecop.rb || (echo "FAILED!!!!!!!!!!!!")
|
data/test/test_helper.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
1
3
|
require 'test/unit'
|
4
|
+
require 'mocha'
|
2
5
|
|
3
6
|
class Test::Unit::TestCase
|
7
|
+
|
4
8
|
private
|
5
9
|
# Tests to see that two times are within the given distance,
|
6
10
|
# in seconds, from each other.
|
@@ -43,4 +47,4 @@ class Test::Unit::TestCase
|
|
43
47
|
assert_equal dt1, dt2, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}"
|
44
48
|
end
|
45
49
|
|
46
|
-
end
|
50
|
+
end
|
@@ -97,8 +97,7 @@ class TestTimeStackItem < Test::Unit::TestCase
|
|
97
97
|
Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400"))
|
98
98
|
t = DateTime.parse("2009-10-11 00:00:00 -0400")
|
99
99
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
100
|
-
|
101
|
-
assert tsi.time.dst?, "precondition"
|
100
|
+
return if !(Time.now.dst? && tsi.time.dst?)
|
102
101
|
assert_equal 0, tsi.send(:dst_adjustment)
|
103
102
|
end
|
104
103
|
|
@@ -106,8 +105,7 @@ class TestTimeStackItem < Test::Unit::TestCase
|
|
106
105
|
Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400"))
|
107
106
|
t = DateTime.parse("2009-12-11 00:00:00 -0400")
|
108
107
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
109
|
-
|
110
|
-
assert !tsi.time.dst?, "precondition"
|
108
|
+
return if Time.now.dst? || tsi.time.dst?
|
111
109
|
assert_equal 0, tsi.send(:dst_adjustment)
|
112
110
|
end
|
113
111
|
|
@@ -115,8 +113,7 @@ class TestTimeStackItem < Test::Unit::TestCase
|
|
115
113
|
Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400"))
|
116
114
|
t = DateTime.parse("2009-12-11 00:00:00 -0400")
|
117
115
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
118
|
-
|
119
|
-
assert !tsi.time.dst?, "precondition"
|
116
|
+
return if !Time.now.dst? || tsi.time.dst?
|
120
117
|
assert_equal 60 * 60, tsi.send(:dst_adjustment)
|
121
118
|
end
|
122
119
|
|
@@ -124,27 +121,24 @@ class TestTimeStackItem < Test::Unit::TestCase
|
|
124
121
|
Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400"))
|
125
122
|
t = DateTime.parse("2009-10-11 00:00:00 -0400")
|
126
123
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
127
|
-
|
128
|
-
assert tsi.time.dst?, "precondition"
|
124
|
+
return if Time.now.dst? || !tsi.time.dst?
|
129
125
|
assert_equal -1 * 60 * 60, tsi.send(:dst_adjustment)
|
130
126
|
end
|
131
127
|
|
132
|
-
# Ensure
|
128
|
+
# Ensure DateTimes handle changing DST properly
|
133
129
|
def test_datetime_for_dst_to_non_dst
|
134
130
|
Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
|
135
131
|
t = DateTime.parse("2009-10-11 00:00:00 -0400")
|
136
132
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
137
133
|
assert_date_times_equal t, tsi.datetime
|
138
|
-
# verify Date also 'moves backward' an hour to change the day
|
139
|
-
assert_equal Date.new(2009, 10, 10), tsi.date
|
140
134
|
end
|
141
135
|
|
142
136
|
def test_datetime_for_non_dst_to_dst
|
143
137
|
Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400"))
|
144
138
|
t = DateTime.parse("2009-11-30 23:38:00 -0500")
|
145
139
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
140
|
+
return if !tsi.time.dst?
|
146
141
|
assert_date_times_equal t, tsi.datetime
|
147
|
-
# verify Date also 'moves forward' an hour to change the day
|
148
142
|
assert_equal Date.new(2009, 12, 1), tsi.date
|
149
143
|
end
|
150
144
|
|
@@ -164,4 +158,26 @@ class TestTimeStackItem < Test::Unit::TestCase
|
|
164
158
|
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
165
159
|
assert_equal nil, tsi.send(:travel_offset)
|
166
160
|
end
|
167
|
-
|
161
|
+
|
162
|
+
def test_parse_string_date_with_active_support
|
163
|
+
date = '2012-01-02'
|
164
|
+
Time.expects(:parse).with(date).returns(Time.local(2012, 01, 02))
|
165
|
+
Timecop.freeze(date)
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_integration_with_rails_time_zone
|
169
|
+
time = Time.now
|
170
|
+
def time.in_time_zone
|
171
|
+
self - 3600
|
172
|
+
end
|
173
|
+
t = time - 3600
|
174
|
+
stack_item = Timecop::TimeStackItem.new(:freeze, time)
|
175
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
176
|
+
assert_equal y, stack_item.year
|
177
|
+
assert_equal m, stack_item.month
|
178
|
+
assert_equal d, stack_item.day
|
179
|
+
assert_equal h, stack_item.hour
|
180
|
+
assert_equal min, stack_item.min
|
181
|
+
assert_equal s, stack_item.sec
|
182
|
+
end
|
183
|
+
end
|
@@ -3,20 +3,20 @@ require 'test_helper'
|
|
3
3
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
|
4
4
|
|
5
5
|
class TestTimecop < Test::Unit::TestCase
|
6
|
-
|
6
|
+
|
7
7
|
def setup
|
8
|
-
|
8
|
+
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# just in case...let's really make sure that Timecop is disabled between tests...
|
12
12
|
def teardown
|
13
13
|
Timecop.return
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def test_freeze_changes_and_resets_time
|
17
17
|
# depending on how we're invoked (individually or via the rake test suite)
|
18
18
|
assert !Time.respond_to?(:zone) || Time.zone.nil?
|
19
|
-
|
19
|
+
|
20
20
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
21
21
|
assert_not_equal t, Time.now
|
22
22
|
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
@@ -24,6 +24,12 @@ class TestTimecop < Test::Unit::TestCase
|
|
24
24
|
end
|
25
25
|
assert_not_equal t, Time.now
|
26
26
|
end
|
27
|
+
|
28
|
+
def test_freeze_yields_mocked_time
|
29
|
+
Timecop.freeze(2008, 10, 10, 10, 10, 10) do |frozen_time|
|
30
|
+
assert_equal frozen_time, Time.now
|
31
|
+
end
|
32
|
+
end
|
27
33
|
|
28
34
|
def test_freeze_then_return_unsets_mock_time
|
29
35
|
Timecop.freeze(1)
|
@@ -36,22 +42,27 @@ class TestTimecop < Test::Unit::TestCase
|
|
36
42
|
Timecop.return
|
37
43
|
assert_nil Time.send(:mock_time)
|
38
44
|
end
|
39
|
-
|
45
|
+
|
40
46
|
def test_freeze_with_block_unsets_mock_time
|
41
47
|
assert_nil Time.send(:mock_time), "test is invalid"
|
42
48
|
Timecop.freeze(1) do; end
|
43
49
|
assert_nil Time.send(:mock_time)
|
44
50
|
end
|
45
|
-
|
51
|
+
|
46
52
|
def test_travel_with_block_unsets_mock_time
|
47
53
|
assert_nil Time.send(:mock_time), "test is invalid"
|
48
54
|
Timecop.travel(1) do; end
|
49
55
|
assert_nil Time.send(:mock_time)
|
50
56
|
end
|
51
|
-
|
57
|
+
|
58
|
+
def test_travel_does_not_reduce_precision_of_datetime
|
59
|
+
Timecop.travel(1)
|
60
|
+
assert_not_equal DateTime.now, DateTime.now
|
61
|
+
end
|
62
|
+
|
52
63
|
def test_recursive_freeze
|
53
64
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
54
|
-
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
65
|
+
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
55
66
|
assert_equal t, Time.now
|
56
67
|
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
57
68
|
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
@@ -61,10 +72,10 @@ class TestTimecop < Test::Unit::TestCase
|
|
61
72
|
end
|
62
73
|
assert_not_equal t, Time.now
|
63
74
|
end
|
64
|
-
|
75
|
+
|
65
76
|
def test_freeze_with_time_instance_works_as_expected
|
66
77
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
67
|
-
Timecop.freeze(t) do
|
78
|
+
Timecop.freeze(t) do
|
68
79
|
assert_equal t, Time.now
|
69
80
|
assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
|
70
81
|
assert_equal Date.new(2008, 10, 10), Date.today
|
@@ -73,7 +84,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
73
84
|
assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
|
74
85
|
assert_not_equal Date.new(2008, 10, 10), Date.today
|
75
86
|
end
|
76
|
-
|
87
|
+
|
77
88
|
def test_freeze_with_datetime_on_specific_timezone_during_dst
|
78
89
|
each_timezone do
|
79
90
|
# Start from a time that is subject to DST
|
@@ -87,7 +98,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
87
98
|
Timecop.return
|
88
99
|
end
|
89
100
|
end
|
90
|
-
|
101
|
+
|
91
102
|
def test_freeze_with_datetime_on_specific_timezone_not_during_dst
|
92
103
|
each_timezone do
|
93
104
|
# Start from a time that is not subject to DST
|
@@ -99,7 +110,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
99
110
|
end
|
100
111
|
end
|
101
112
|
end
|
102
|
-
|
113
|
+
|
103
114
|
def test_freeze_with_datetime_from_a_non_dst_time_to_a_dst_time
|
104
115
|
each_timezone do
|
105
116
|
# Start from a time that is not subject to DST
|
@@ -109,7 +120,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
109
120
|
Timecop.freeze(t) do
|
110
121
|
assert_date_times_equal t, DateTime.now
|
111
122
|
end
|
112
|
-
end
|
123
|
+
end
|
113
124
|
end
|
114
125
|
|
115
126
|
def test_freeze_with_datetime_from_a_dst_time_to_a_non_dst_time
|
@@ -121,9 +132,9 @@ class TestTimecop < Test::Unit::TestCase
|
|
121
132
|
Timecop.freeze(t) do
|
122
133
|
assert_date_times_equal t, DateTime.now
|
123
134
|
end
|
124
|
-
end
|
135
|
+
end
|
125
136
|
end
|
126
|
-
|
137
|
+
|
127
138
|
def test_freeze_with_date_instance_works_as_expected
|
128
139
|
d = Date.new(2008, 10, 10)
|
129
140
|
Timecop.freeze(d) do
|
@@ -133,9 +144,9 @@ class TestTimecop < Test::Unit::TestCase
|
|
133
144
|
end
|
134
145
|
assert_not_equal d, Date.today
|
135
146
|
assert_not_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now
|
136
|
-
assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
|
147
|
+
assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
|
137
148
|
end
|
138
|
-
|
149
|
+
|
139
150
|
def test_freeze_with_integer_instance_works_as_expected
|
140
151
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
141
152
|
Timecop.freeze(t) do
|
@@ -165,7 +176,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
165
176
|
assert_nil Time.send(:mock_time)
|
166
177
|
end
|
167
178
|
end
|
168
|
-
|
179
|
+
|
169
180
|
def test_freeze_freezes_time
|
170
181
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
171
182
|
now = Time.now
|
@@ -179,7 +190,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
179
190
|
assert_equal new_dt, DateTime.now
|
180
191
|
end
|
181
192
|
end
|
182
|
-
|
193
|
+
|
183
194
|
def test_travel_keeps_time_moving
|
184
195
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
185
196
|
now = Time.now
|
@@ -190,7 +201,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
190
201
|
assert_times_effectively_not_equal new_now, Time.now, 0.25, "Looks like time is not moving"
|
191
202
|
end
|
192
203
|
end
|
193
|
-
|
204
|
+
|
194
205
|
def test_mocked_date_time_now_is_local
|
195
206
|
each_timezone do
|
196
207
|
t = DateTime.parse("2009-10-11 00:38:00 +0200")
|
@@ -199,7 +210,7 @@ class TestTimecop < Test::Unit::TestCase
|
|
199
210
|
end
|
200
211
|
end
|
201
212
|
end
|
202
|
-
|
213
|
+
|
203
214
|
def test_freeze_with_utc_time
|
204
215
|
each_timezone do
|
205
216
|
t = Time.utc(2008, 10, 10, 10, 10, 10)
|
@@ -224,10 +235,10 @@ class TestTimecop < Test::Unit::TestCase
|
|
224
235
|
assert !Time.now.utc?, "Failed to thwart destructive methods."
|
225
236
|
end
|
226
237
|
end
|
227
|
-
|
238
|
+
|
228
239
|
def test_recursive_travel_maintains_each_context
|
229
240
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
230
|
-
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
241
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
231
242
|
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
232
243
|
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
233
244
|
Timecop.travel(2008, 9, 9, 9, 9, 9) do
|
@@ -238,10 +249,18 @@ class TestTimecop < Test::Unit::TestCase
|
|
238
249
|
end
|
239
250
|
assert_nil Time.send(:mock_time)
|
240
251
|
end
|
252
|
+
|
253
|
+
def test_recursive_travel_yields_correct_time
|
254
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
255
|
+
Timecop.travel(2008, 9, 9, 9, 9, 9) do |inner_freeze|
|
256
|
+
assert_times_effectively_equal inner_freeze, Time.now, 1, "Failed to yield current time back to block"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
241
260
|
|
242
261
|
def test_recursive_travel_then_freeze
|
243
262
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
244
|
-
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
263
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
245
264
|
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
246
265
|
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
247
266
|
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
@@ -251,10 +270,10 @@ class TestTimecop < Test::Unit::TestCase
|
|
251
270
|
end
|
252
271
|
assert_nil Time.send(:mock_time)
|
253
272
|
end
|
254
|
-
|
273
|
+
|
255
274
|
def test_recursive_freeze_then_travel
|
256
275
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
257
|
-
Timecop.freeze(t) do
|
276
|
+
Timecop.freeze(t) do
|
258
277
|
assert_equal t, Time.now
|
259
278
|
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
260
279
|
Timecop.travel(t2) do
|
@@ -263,27 +282,27 @@ class TestTimecop < Test::Unit::TestCase
|
|
263
282
|
end
|
264
283
|
assert_equal t, Time.now
|
265
284
|
end
|
266
|
-
assert_nil Time.send(:mock_time)
|
285
|
+
assert_nil Time.send(:mock_time)
|
267
286
|
end
|
268
|
-
|
287
|
+
|
269
288
|
def test_return_values_are_Time_instances
|
270
289
|
assert Timecop.freeze.is_a?(Time)
|
271
290
|
assert Timecop.travel.is_a?(Time)
|
272
291
|
assert Timecop.return.is_a?(Time)
|
273
292
|
end
|
274
|
-
|
293
|
+
|
275
294
|
def test_travel_time_returns_passed_value
|
276
295
|
t_future = Time.local(2030, 10, 10, 10, 10, 10)
|
277
296
|
t_travel = Timecop.travel t_future
|
278
297
|
assert times_effectively_equal(t_future, t_travel)
|
279
298
|
end
|
280
|
-
|
299
|
+
|
281
300
|
def test_freeze_time_returns_passed_value
|
282
301
|
t_future = Time.local(2030, 10, 10, 10, 10, 10)
|
283
302
|
t_frozen = Timecop.freeze t_future
|
284
303
|
assert times_effectively_equal(t_future, t_frozen)
|
285
304
|
end
|
286
|
-
|
305
|
+
|
287
306
|
def test_return_time_returns_actual_time
|
288
307
|
t_real = Time.now
|
289
308
|
Timecop.freeze Time.local(2030, 10, 10, 10, 10, 10)
|
@@ -291,4 +310,46 @@ class TestTimecop < Test::Unit::TestCase
|
|
291
310
|
assert times_effectively_equal(t_real, t_return)
|
292
311
|
end
|
293
312
|
|
294
|
-
|
313
|
+
def test_freeze_without_params
|
314
|
+
Timecop.freeze 1 do
|
315
|
+
current_time = Time.now
|
316
|
+
Timecop.freeze do
|
317
|
+
assert_equal Time.now, current_time
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_return_to_baseline_without_a_baseline_set_returns_to_current_time
|
323
|
+
time_before_travel = Time.now
|
324
|
+
Timecop.travel Time.now - 60
|
325
|
+
Timecop.return_to_baseline
|
326
|
+
assert times_effectively_equal(time_before_travel, Time.now)
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_return_to_baseline_with_a_baseline_set_returns_to_baseline
|
330
|
+
baseline = Time.local(1945, 10, 10, 10, 10, 10)
|
331
|
+
Timecop.baseline = baseline
|
332
|
+
Timecop.travel Time.now - 60
|
333
|
+
time_now = Timecop.return_to_baseline
|
334
|
+
assert times_effectively_equal(baseline, time_now),
|
335
|
+
"expected to return to #{baseline}, but returned to #{time_now}"
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_return_eliminates_baseline
|
339
|
+
time_before_travel = Time.now
|
340
|
+
Timecop.baseline = Time.local(1937, 9, 9, 9, 9, 9)
|
341
|
+
Timecop.return
|
342
|
+
assert times_effectively_equal(time_before_travel, Time.now)
|
343
|
+
|
344
|
+
Timecop.travel(Time.now - 100)
|
345
|
+
Timecop.return_to_baseline
|
346
|
+
assert times_effectively_equal(time_before_travel, Time.now)
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_mock_time_new_same_as_now
|
350
|
+
date = Time.local(2011, 01, 02)
|
351
|
+
Timecop.freeze date
|
352
|
+
assert_equal date, Time.now
|
353
|
+
assert_equal date, Time.new
|
354
|
+
end
|
355
|
+
end
|
data/test/{test_timecop_without_date_but_with_time.rb → timecop_without_date_but_with_time_test.rb}
RENAMED
File without changes
|
@@ -5,8 +5,8 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
|
|
5
5
|
class TestTimecopWithoutDate < Test::Unit::TestCase
|
6
6
|
|
7
7
|
def setup
|
8
|
-
|
9
|
-
|
8
|
+
Object.send(:remove_const, :Date) if Object.const_defined?(:Date)
|
9
|
+
Object.send(:remove_const, :DateTime) if Object.const_defined?(:DateTime)
|
10
10
|
end
|
11
11
|
|
12
12
|
# just in case...let's really make sure that Timecop is disabled between tests...
|
@@ -116,4 +116,4 @@ class TestTimecopWithoutDate < Test::Unit::TestCase
|
|
116
116
|
assert_nil Time.send(:mock_time)
|
117
117
|
end
|
118
118
|
|
119
|
-
end
|
119
|
+
end
|
metadata
CHANGED
@@ -1,37 +1,30 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: timecop
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 3
|
9
|
-
- 5
|
10
|
-
version: 0.3.5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.1
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
8
|
+
- Travis Jeffery
|
13
9
|
- John Trupiano
|
14
10
|
autorequire:
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2010-06-07 00:00:00 -04:00
|
19
|
-
default_executable:
|
13
|
+
date: 2012-06-27 00:00:00.000000000Z
|
20
14
|
dependencies: []
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
description: A gem providing "time travel" and "time freezing" capabilities, making
|
16
|
+
it dead simple to test time-dependent code. It provides a unified method to mock
|
17
|
+
Time.now, Date.today, and DateTime.now in a single call.
|
18
|
+
email: travisjeffery@gmail.com
|
24
19
|
executables: []
|
25
|
-
|
26
20
|
extensions: []
|
27
|
-
|
28
|
-
extra_rdoc_files:
|
21
|
+
extra_rdoc_files:
|
29
22
|
- LICENSE
|
30
|
-
- README.
|
31
|
-
files:
|
23
|
+
- README.markdown
|
24
|
+
files:
|
32
25
|
- History.rdoc
|
33
26
|
- LICENSE
|
34
|
-
- README.
|
27
|
+
- README.markdown
|
35
28
|
- Rakefile
|
36
29
|
- VERSION.yml
|
37
30
|
- lib/timecop.rb
|
@@ -40,47 +33,40 @@ files:
|
|
40
33
|
- lib/timecop/timecop.rb
|
41
34
|
- test/run_tests.sh
|
42
35
|
- test/test_helper.rb
|
43
|
-
- test/
|
44
|
-
- test/
|
45
|
-
- test/
|
46
|
-
- test/
|
47
|
-
has_rdoc: true
|
36
|
+
- test/time_stack_item_test.rb
|
37
|
+
- test/timecop_test.rb
|
38
|
+
- test/timecop_without_date_test.rb
|
39
|
+
- test/timecop_without_date_but_with_time_test.rb
|
48
40
|
homepage: http://github.com/jtrupiano/timecop
|
49
41
|
licenses: []
|
50
|
-
|
51
42
|
post_install_message:
|
52
|
-
rdoc_options:
|
43
|
+
rdoc_options:
|
53
44
|
- --charset=UTF-8
|
54
|
-
require_paths:
|
45
|
+
require_paths:
|
55
46
|
- lib
|
56
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
48
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
|
63
|
-
- 0
|
64
|
-
version: "0"
|
65
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
54
|
none: false
|
67
|
-
requirements:
|
68
|
-
- -
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
|
71
|
-
segments:
|
72
|
-
- 0
|
73
|
-
version: "0"
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
74
59
|
requirements: []
|
75
|
-
|
76
60
|
rubyforge_project: johntrupiano
|
77
|
-
rubygems_version: 1.
|
61
|
+
rubygems_version: 1.8.10
|
78
62
|
signing_key:
|
79
63
|
specification_version: 3
|
80
|
-
summary: A gem providing "time travel" and "time freezing" capabilities, making it
|
81
|
-
|
64
|
+
summary: A gem providing "time travel" and "time freezing" capabilities, making it
|
65
|
+
dead simple to test time-dependent code. It provides a unified method to mock Time.now,
|
66
|
+
Date.today, and DateTime.now in a single call.
|
67
|
+
test_files:
|
82
68
|
- test/test_helper.rb
|
83
|
-
- test/
|
84
|
-
- test/
|
85
|
-
- test/
|
86
|
-
- test/
|
69
|
+
- test/time_stack_item_test.rb
|
70
|
+
- test/timecop_test.rb
|
71
|
+
- test/timecop_without_date_test.rb
|
72
|
+
- test/timecop_without_date_but_with_time_test.rb
|
data/README.rdoc
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
= timecop
|
2
|
-
|
3
|
-
* Source[http://github.com/jtrupiano/timecop]
|
4
|
-
* Documentation[http://johntrupiano.rubyforge.org/timecop]
|
5
|
-
|
6
|
-
== DESCRIPTION
|
7
|
-
|
8
|
-
A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.
|
9
|
-
|
10
|
-
== INSTALL
|
11
|
-
|
12
|
-
gem install timecop
|
13
|
-
|
14
|
-
== FEATURES
|
15
|
-
|
16
|
-
* Freeze time to a specific point.
|
17
|
-
* Travel back to a specific point in time, but allow time to continue moving forward from there.
|
18
|
-
* No dependencies, can be used with _any_ ruby project
|
19
|
-
* Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
|
20
|
-
* Time instance
|
21
|
-
* DateTime instance
|
22
|
-
* Date instance
|
23
|
-
* individual arguments (year, month, day, hour, minute, second)
|
24
|
-
* a single integer argument that is interpreted as an offset in seconds from Time.now
|
25
|
-
* Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
|
26
|
-
|
27
|
-
== USAGE
|
28
|
-
|
29
|
-
Run a time-sensitive test
|
30
|
-
|
31
|
-
joe = User.find(1)
|
32
|
-
joe.purchase_home()
|
33
|
-
assert !joe.mortgage_due?
|
34
|
-
# move ahead a month and assert that the mortgage is due
|
35
|
-
Timecop.freeze(Date.today + 30) do
|
36
|
-
assert joe.mortgage_due?
|
37
|
-
end
|
38
|
-
|
39
|
-
Set the time for the test environment of a rails app -- this is particularly helpful if your whole application is time-sensitive. It allows you to build your test data at a single point in time, and to move in/out of that time as appropriate (within your tests)
|
40
|
-
|
41
|
-
in config/environments/test.rb
|
42
|
-
|
43
|
-
config.after_initialize do
|
44
|
-
# Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
|
45
|
-
t = Time.local(2008, 9, 1, 10, 5, 0)
|
46
|
-
Timecop.travel(t)
|
47
|
-
end
|
48
|
-
|
49
|
-
=== The difference between Timecop.freeze and Timecop.travel
|
50
|
-
|
51
|
-
#freeze is used to statically mock the concept of now. As your program executes, Time.now will not change unless you make subsequent calls into the Timecop API. #travel, on the other hand, computes an offset between what we currently think Time.now is (recall that we support nested traveling) and the time passed in. It uses this offset to simulate the passage of time. To demonstrate, consider the following code snippets:
|
52
|
-
|
53
|
-
new_time = Time.local(2008, 9, 1, 12, 0, 0)
|
54
|
-
Timecop.freeze(new_time)
|
55
|
-
sleep(10)
|
56
|
-
new_time == Time.now # ==> true
|
57
|
-
|
58
|
-
Timecop.return # "turn off" Timecop
|
59
|
-
Timecop.travel(new_time)
|
60
|
-
sleep(10)
|
61
|
-
new_time == Time.now # ==> false
|
62
|
-
|
63
|
-
== REFERENCES
|
64
|
-
|
65
|
-
* {0.3.4 release}[http://blog.smartlogicsolutions.com/2009/12/07/timecop-0-3-4-released/]
|
66
|
-
* {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
|
67
|
-
* {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
|
68
|
-
* {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
|