How to test timers?

2,565 views
Skip to first unread message

swheeler

unread,
Sep 14, 2010, 5:26:05 PM9/14/10
to Jasmine
Congratulations on the 1.0.0 release of an excellent testing
framework.

As a complete beginner, I'm wondering how to test timers. For example,
if my use case is to periodically change some text within an element,
how would I go about testing this?

Any pointers or examples would be appreciated.

Many thanks.

josh

unread,
Sep 14, 2010, 7:58:01 PM9/14/10
to Jasmine
Jasmine guys, mega-congrats on 1.0! I too have a noob question having
to do with timers. Probably a _really_ noob question: what is
jasmine.Clock for? I'm using a lot of waitsFor's, and wondering
whether it's something I should be using.

Thanks again for making this great testing framework!

Davis Frank

unread,
Sep 14, 2010, 8:30:40 PM9/14/10
to jasmi...@googlegroups.com
Jasmine.Clock is a mock Clock. 

When installed, it steals calls to setTimeout & setInterval, saves the parameters away, and effectively freezes time.  

When you call jasmine.Clock.tick(300), you are advancing a mock clock by 300ms.  Any calls that should take place in 300ms are then called.

You can use the mock clock for those times when you stop time during setup, force time forward in controlled chunks, and then assert that your expectations pass.

More detailed examples are coming soon.

--dwf

--
You received this message because you are subscribed to the Google Groups "Jasmine" group.
To post to this group, send email to jasmi...@googlegroups.com.
To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/jasmine-js?hl=en.


Christian Williams

unread,
Sep 14, 2010, 9:26:04 PM9/14/10
to jasmi...@googlegroups.com
Here's a simple example:

// Production code:

var status = "Loading...";

function showCountdown() {
  setTimeout(function() { status = "3 seconds to go..."; }, 1000);
  setTimeout(function() { status = "2 seconds to go..."; }, 2000);
  setTimeout(function() { status = "1 seconds to go..."; }, 3000);
  setTimeout(function() { status = "Ready!"; }, 4000);
}


// Test code:

describe("Countdown", function() {
  var player;
  var song;

  beforeEach(function() {
    jasmine.Clock.useMock();
  });

  it("should count down from 3", function() {
    showCountdown();

    expect(status).toEqual("Loading...");

    jasmine.Clock.tick(500);
    expect(status).toEqual("Loading..."); // the initial 1000ms delay still hasn't passed...

    jasmine.Clock.tick(500);
    expect(status).toEqual("3 seconds to go...");

    jasmine.Clock.tick(1000);
    expect(status).toEqual("2 seconds to go...");

    jasmine.Clock.tick(1000);
    expect(status).toEqual("1 seconds to go...");

    jasmine.Clock.tick(1000);
    expect(status).toEqual("Ready!");
  });
});

--Xian

Christian Williams

unread,
Sep 14, 2010, 9:58:08 PM9/14/10
to jasmi...@googlegroups.com
One big advantage of using Jasmine's mock clock is that your specs will run really fast. If we wrote the spec using waits(), it would take about 4 seconds to finish. Using jasmine.Clock, it takes less than a millisecond on my box.

Also, you're begging for flaky tests if you rely on waits() and wall clock timing.

--X [typos courtesy of my iPhone]

swheeler

unread,
Sep 15, 2010, 3:36:21 AM9/15/10
to Jasmine
Exactly what I was looking for. I had tried using the waits but it
just didn't seem right waiting several seconds for the test to
finish.

Thanks for the very speedy and helpful reply.

On Sep 15, 2:58 am, Christian Williams <antixian...@gmail.com> wrote:
> One big advantage of using Jasmine's mock clock is that your specs will run really fast. If we wrote the spec using waits(), it would take about 4 seconds to finish. Using jasmine.Clock, it takes less than a millisecond on my box.
>
> Also, you're begging for flaky tests if you rely on waits() and wall clock timing.
>
> --X [typos courtesy of my iPhone]
>
> > On Tue, Sep 14, 2010 at 5:30 PM, Davis Frank <dwfr...@pivotallabs.com> wrote:
> > Jasmine.Clock is a mock Clock.
>
> > When installed, it steals calls to setTimeout & setInterval, saves the parameters away, and effectively freezes time.  
>
> > When you call jasmine.Clock.tick(300), you are advancing a mock clock by 300ms.  Any calls that should take place in 300ms are then called.
>
> > You can use the mock clock for those times when you stop time during setup, force time forward in controlled chunks, and then assert that your expectations pass.
>
> > More detailed examples are coming soon.
>
> > --dwf
>
> > On Tue, Sep 14, 2010 at 4:58 PM, josh <weinstein.j...@gmail.com> wrote:
> > Jasmine guys, mega-congrats on 1.0! I too have a noob question having
> > to do with timers. Probably a _really_ noob question: what is
> > jasmine.Clock for? I'm using a lot of waitsFor's, and wondering
> > whether it's something I should be using.
>
> > Thanks again for making this great testing framework!
>
> > On Sep 14, 5:26 pm, swheeler <swheeler.em...@googlemail.com> wrote:
> > > Congratulations on the 1.0.0 release of an excellent testing
> > > framework.
>
> > > As a complete beginner, I'm wondering how to test timers. For example,
> > > if my use case is to periodically change some text within an element,
> > > how would I go about testing this?
>
> > > Any pointers or examples would be appreciated.
>
> > > Many thanks.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Jasmine" group.
> > To post to this group, send email to jasmi...@googlegroups.com.
> > To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/jasmine-js?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Jasmine" group.
> > To post to this group, send email to jasmi...@googlegroups.com.
> > To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/jasmine-js?hl=en.

Ryan Sullivan

unread,
Sep 15, 2010, 4:42:12 PM9/15/10
to Jasmine
Is there a way to use this for capturing the current time? Basically I
have some code that captures a time, and then on specific events
captures a new time, and get the difference. So basically I want to
test:

var startTime = new Date().getTime();

$('someLink').observe('click', function(e){
var durration = new Date().getTime() - startTime;
}

The only way that I have found to test this with jasmine is mock out
the startTime to be 0, then capture the current time right before
triggering the event, and asserting the durrations is equal to the
current time. This can sometimes fail if the is any delay in the
running of the event.

Rajan Agaskar

unread,
Sep 15, 2010, 4:57:13 PM9/15/10
to jasmi...@googlegroups.com
You can change your stub in between actions. IE

spyOn(Date, "getTime").andReturn(0);
... load your code/apply your behavior, etc ...
Date.getTime.andReturn(2);
$('someLink').click();
expect(duration).toEqual(2);

it's also possible to use a fake to do this, but it this case it might
be overkill:

var spyCount = 0;
spyOn(Date, "getTime").andCallFake(function() {
spyCount++;
return spyCount;
});
... load your code/apply your behavior, etc ...
$('someLink').click();
expect(duration).toEqual(1);

Ryan Sullivan

unread,
Sep 15, 2010, 5:55:04 PM9/15/10
to Jasmine
Spying on the new Date().getTime() is not working. I am getting a
"getTime() method does not exist" error.

Rajan Agaskar

unread,
Sep 15, 2010, 6:06:14 PM9/15/10
to jasmi...@googlegroups.com
Ryan:

Sorry, this was from memory. getTime requires a date instance, because
it's going to provide you with the timestamp from that particular date
object. When you don't pass in anything to Date() it uses the current
time, which is why new Date().getTime() is giving you the current
timestamp. You've got a couple options here. Use Date.now() to get
the current time and spyOn(Date, 'now') (not sure what the
cross-browser is like on Date.now).

Another way to approach it if you still want to use Date().getTime()
is to wrap it with your own class, ie:

function MyDate() {
};
MyDate.currentTime = function() {
return Date().getTime();
}

Then you can spyOn(MyDate, "getTime");

Thanks

Rajan

Christian Williams

unread,
Sep 15, 2010, 7:36:35 PM9/15/10
to jasmi...@googlegroups.com
You can also probably spyOn(Date.prototype, 'getTime') -- but I haven't tried it.


--X [typos courtesy of my iPhone]

josh

unread,
Sep 15, 2010, 8:01:00 PM9/15/10
to Jasmine
Christian, Davis, enormously helpful. Thank you so much!

On Sep 14, 9:58 pm, Christian Williams <antixian...@gmail.com> wrote:
> One big advantage of using Jasmine's mock clock is that your specs will run really fast. If we wrote the spec using waits(), it would take about 4 seconds to finish. Using jasmine.Clock, it takes less than a millisecond on my box.
>
> Also, you're begging for flaky tests if you rely on waits() and wall clock timing.
>
> --X [typos courtesy of my iPhone]
>
> > On Tue, Sep 14, 2010 at 5:30 PM, Davis Frank <dwfr...@pivotallabs.com> wrote:
> > Jasmine.Clock is a mock Clock.
>
> > When installed, it steals calls to setTimeout & setInterval, saves the parameters away, and effectively freezes time.  
>
> > When you call jasmine.Clock.tick(300), you are advancing a mock clock by 300ms.  Any calls that should take place in 300ms are then called.
>
> > You can use the mock clock for those times when you stop time during setup, force time forward in controlled chunks, and then assert that your expectations pass.
>
> > More detailed examples are coming soon.
>
> > --dwf
>
> > On Tue, Sep 14, 2010 at 4:58 PM, josh <weinstein.j...@gmail.com> wrote:
> > Jasmine guys, mega-congrats on 1.0! I too have a noob question having
> > to do with timers. Probably a _really_ noob question: what is
> > jasmine.Clock for? I'm using a lot of waitsFor's, and wondering
> > whether it's something I should be using.
>
> > Thanks again for making this great testing framework!
>
> > On Sep 14, 5:26 pm, swheeler <swheeler.em...@googlemail.com> wrote:
> > > Congratulations on the 1.0.0 release of an excellent testing
> > > framework.
>
> > > As a complete beginner, I'm wondering how to test timers. For example,
> > > if my use case is to periodically change some text within an element,
> > > how would I go about testing this?
>
> > > Any pointers or examples would be appreciated.
>
> > > Many thanks.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Jasmine" group.
> > To post to this group, send email to jasmi...@googlegroups.com.
> > To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/jasmine-js?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Jasmine" group.
> > To post to this group, send email to jasmi...@googlegroups.com.
> > To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/jasmine-js?hl=en.

Ryan Sullivan

unread,
Sep 23, 2010, 5:00:21 PM9/23/10
to Jasmine
Thanks Christian, that worked perfectly. Basically my code looks like

spyOn(Date.prototype, 'getTime').andReturn(0);
var startTime = new Date().getTime();
Date.prototype.getTime.andReturn(10);
var durration = new Date().getTime() - startTime;
expect(durration).toEqual(10);

On Sep 15, 4:36 pm, Christian Williams <antixian...@gmail.com> wrote:
> You can also probably spyOn(Date.prototype, 'getTime') -- but I haven't tried it.
>
> --X [typos courtesy of my iPhone]
>
> On Sep 15, 2010, at 15:06, Rajan Agaskar <ra...@pivotallabs.com> wrote:
>
>
>
>
>
>
>
> > Ryan:
>
> > Sorry, this was from memory. getTime requires a date instance, because
> > it's going to provide you with the timestamp from that particular date
> > object. When you don't pass in anything to Date() it uses the current
> > time, which is why new Date().getTime() is giving you the current
> > timestamp.  You've got a couple options here. Use Date.now() to get
> > the current time and spyOn(Date, 'now') (not sure what the
> > cross-browser is like on Date.now).
>
> > Another way to approach it if you still want to use Date().getTime()
> > is to wrap it with your own class, ie:
>
> > function MyDate() {
> > };
> > MyDate.currentTime = function() {
> > return Date().getTime();
> > }
>
> > Then you can spyOn(MyDate, "getTime");
>
> > Thanks
>
> > Rajan
>
Reply all
Reply to author
Forward
0 new messages