/
atom.xml
96 lines (76 loc) · 3.8 KB
/
atom.xml
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Category: determinism | machty's thoughtz]]></title>
<link href="http://machty.github.com/blog/categories/determinism/atom.xml" rel="self"/>
<link href="http://machty.github.com/"/>
<updated>2014-05-25T12:46:17-04:00</updated>
<id>http://machty.github.com/</id>
<author>
<name><![CDATA[Alex Matchneer]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Stubbing Date::valueOf for Benefit of Make Great Good Determinism]]></title>
<link href="http://machty.github.com/blog/2013/03/24/stubbing-date-valueof-for-benefit-of-make-great-good-determinism/"/>
<updated>2013-03-24T13:20:00-04:00</updated>
<id>http://machty.github.com/blog/2013/03/24/stubbing-date-valueof-for-benefit-of-make-great-good-determinism</id>
<content type="html"><![CDATA[<p>Quick thing: if you ever find yourself in the situation of writing
JavaScript test cases that involve <code>setTimeout</code> or some other timer
logic where the order of timers firing is the subject of testing, you
might find this trick handy to get rid of brittle, non-deterministic
test cases.</p>
<p>In short, you can stub out the <code>Date</code> class's <code>valueOf</code> method to return
a value you expect for the duration of the test case.</p>
<!-- more -->
<h2>The Problem</h2>
<p>I recently did some work on Ember.js's run loop, particularly improving
a few oddities about <code>Ember.run.later</code>, and adding better coverage to
their run loop test suite. But we were noticing that one of my test
cases would very occasionally fail, most often when the testing
workstation was under heavy computational load. The problem, boiled down
to its essence, was that I'd made the poor assumption that consecutive
calls to <code>+ new Date()</code>, a shorthand for returning the number of
milliseconds from 1970, would return the same value.</p>
<p><code>javascript
+ new Date(); // 123456788
+ new Date(); // 123456788
+ new Date(); // 123456788
+ new Date(); // 123456789 <-- boom
</code></p>
<p>Duh, right? Time does have a weird OCD habit of elapsing, but I needed,
for the assumptions of
<a href="https://github.com/emberjs/ember.js/blob/master/packages/ember-metal/tests/run_loop/later_test.js#L114">this particular test</a>,
the JavaScript clock to return the same value for consecutive calls to
<code>+ new Date</code>.</p>
<h2><code>Date::valueOf</code></h2>
<p>Turns out that the function ultimately called when using the <code>+ new Date</code>
shorthand is the <code>valueOf</code> function on the <code>Date</code> class. That's where
the numeric millisecond return value comes from.</p>
<p>The solution to the test case's brittleness was to force all the
consecutively-run timer-dependent code to all get the same numeric
millisecond value from their own internal calls to <code>+ new Date</code>. To do
this, I stubbed the <code>valueOf</code> function as follows:</p>
<p>```javascript
var now = + new Date(); // 123456788
var originalDateValueOf = Date.prototype.valueOf;
Date.prototype.valueOf = function() { return now };
+ new Date(); // 123456788
+ new Date(); // 123456788
+ new Date(); // 123456788
+ new Date(); // 123456788
+ new Date(); // 123456788
+ new Date(); // 123456788</p>
<p>// ... it will continue to return this value until
// I return <code>valueOf</code> back to its original native function.
Date.prototype.valueOf = originalDateValueOf;</p>
<ul>
<li>new Date(); // 123456789
```</li>
</ul>
<p>So, there you have it when you need it; stubbed determinism when futzing
with JavaScript timers.
<a href="https://github.com/emberjs/ember.js/pull/2341/files">Here's</a> how it
looked in the fixed Ember.js run loop test case.</p>
]]></content>
</entry>
</feed>