javascript - Have useful "Red" and "Green" tests for a View Model with throttled observables -
with of another question , relevant qunit documentation can create unit tests deal async nature of throttled knockoutjs observables.
however, haven't yet found elegant way have both red , green tests behave nicely in both test runners use:
- the qunit browser based test runner
 - the visual studio test runner (combined chutzpah run javascript tests)
 
suppose following view model:
var person = function(firstname, surname) {     var self = this;      self.firstname = ko.observable(firstname);     self.surname = ko.observable(surname);      self.fullname = ko.computed({         write: function(val) {             var parts = val.split(" ");             self.firstname(parts[0]);             self.surname(parts[1]);         },         read: function() { return self.firstname() + " " + self.surname(); }     }).extend({throttle: 20}); };   and suppose these 2 basic tests:
test("can read full name", function(){     var john = new person("john", "doe");     strictequal(john.fullname(), "john doe"); });   test("can write full name", function(){     var person = new person();     person.fullname("john doe");     strictequal(person.firstname(), "john");     strictequal(person.surname(), "doe"); });   the latter will fail. makes sense, because asserts run instantly, whereas actual update fullname call runs later: delayed 20 ms throttle. without throttle things succeed.
no problem, linked question learned can use async test , use manual subscription make things green again:
asynctest("can write full name", function(){     var person = new person();      expect(2);      person.surname.subscribe(function(val) {         start();         strictequal(person.firstname(), "john");         strictequal(person.surname(), "doe");     });          person.fullname("john doe"); });   now, suppose break view model this:
// self.surname(parts[1]); // "bug" introduced demonstrate problem   then test runner hang. can "fix" issue resuming test after -say- 2 seconds no matter ending test this:
// after 2 secs assume test failed settimeout(function() {     start(); }, 2000);   this works in browser based test runner bugged code, has error on correct code, console:
pushfailure() assertion outside test context, ... @ qunit.start
makes sense, because start() called twice. first intuition check in settimeout callback see "trancount" (i.e. ask qunit if need start or not), qunit has no support (probably reason :d).
anyways, sum possible situations:
- green because okay.
 - red because subscription never fired.
 - red because assertion failed.
 
how structure test situations accounted , both test runners react nicely?
found @ least 1 solution problem while writing question. posting question along answer (a) in case may others and/or (b) other folks may have better solutions this.
bottom line clear settimeout return value subscription fires:
asynctest("can write full name", function(){     var person = new person();      // after 2 secs assume test failed     var timeout = settimeout(function() {         start();     }, 2000);      expect(2);      person.surname.subscribe(function(val) {         window.cleartimeout(timeout);         start();         strictequal(person.firstname(), "john");         strictequal(person.surname(), "doe");     });      person.fullname("john doe"); });   this works scenarios:
- green if well.
 - red if subscription never fires.
 - red if code has bug.
 
both red cases have nice assertion failure.
only downside solution it's bit verbose, need 4 lines of testing-plumbing. (perhaps else has answer utilizing feature of qunit purpose?)
also, 1 other downside: if increase throttle above timeout test first goes red qunit will crash bit later because start() called once more.
Comments
Post a Comment