Unittesting dependant tests - javascript

I've searched the site and some literature and couldn't get to a clear answer. I'm trying to learn unittesting while constructing a new webpage that simply works as a whiteboard to which you can add post-its.
I have a Canvas object which represents the whiteboard, and a ticket object to represent the post-its. I have (for now) global function to retrieve the one and only canvas, which i test like this:
this.testRetrieveCanvas = function()
{
var canvas = getCanvas();
this.assertTrue( canvas != null );
}
this.testCanvasType = function()
{
var canvas = getCanvas();
this.assertTrue( canvas instanceof Canvas );
}
this.testIfCanvasIsReused = function()
{
var canvas = getCanvas();
this.assertEquals( canvas, getCanvas() );
}
So, i test for three things:
Does the method return a canvas?
Is it an acutal canvas?
Does the method give me the same canvas always?
No problems so far. But a little later, i'm testing "adding the ticket to the canvas":
this.testAddTicketToCanvas = function()
{
var ticket = factory.createTicket("yellow");
var canvas = getCanvas();
canvas.addTicket( ticket );
this.assertTrue( canvas.contains( ticket ) );
};
As you can see, i'm using the getCanvas() function inside my test. Is this a dependent test now? I mean, the first three tests have to pass, if i want this test to be able to run without doubts. If it is dependent, how would i fix this?

Strictly speaking, you should override getCanvas() to return a preconstructed (i.e. the original constructor isn't called) partial mock of canvas. With that said, if canvas' constructor is an empty function and the getCanvas method has no business logic involved, you shouldn't have a problem.
I'd be more wary of the last two statements used together. canvas.addTicket( ticket ); is ok, since it's the function being tested. but then you're asserting that you have added the ticket using a method from the same object. What if this method isn't implemented yet, or returns false, or worse true? What if your addTicket method has secondary effects that could make it add the ticket to the list but change a flag that makes contains() throw an exception, or return false, or true? What if contains has certain business logic that makes it return false for the ticket your sending it, but true for the same ticket in production environment (i.e. your test ticket hasn't been properly initialized, is missing a state, has been marked as excluded from the environment's business flow), what if it has no logic now, but two months into the project the logic changes so that your test fails but all else works (a new state is added, and objects without this state are deemed non existant, except for clients a, b and c). I could go on.
My point is without the code we can't specifically answer your question, only give you pointers and general answers like the one above. If you really don't want to post code, then take into consideration all of these scenarios, and all the other scenarios you can think of, and if under these scenarios testing your code this way won't break code nor tests now and for the foreseeable future, then you're ok.

The short answer to your question is, no.
If your code does not violate any unit testing
principles as long as you adhere to these rules.
Usually, with those questions there is a huge discussion about mocking certain parts of your tests e.g. your getCanvas() function. I agree that there is reason behind this discussion and that if you want to proceed with testing or TDD in general you should dive deeper into this topic. (Please refer to this excellent article from Martin Fowler).
However, for the question if this is a valid unit test, I think it is not relevant as long as you adhere to the unit test rules.

Related

Automatically detect test coupling in Protractor (randomizing test execution order)

The Problem:
We have a rather large test codebase. From time to time, instead of executing all the tests, we execute them individually or in packs. But, sometimes, we see the unexpected test failures because of the tests being interconnected, coupled. For example, one test assumes there is some data created by a previous test - running this kind of test individually will fail.
The Question:
Is it possible to automatically detect which Protractor tests are coupled in the project?
Our current idea is to somehow randomize the test execution order or randomly pick up a pack of tests from all the available tests and check if there are no failures. Hence, the other question: is it possible to change/randomize the Protractor test discovery and change the order of test execution?
Inspired by the Ned Batchelder's "Finding test coupling" blogpost and the Python nose test runner's nose-randomly plugin:
Randomness in testing can be quite powerful to discover hidden flaws
in the tests themselves, as well as giving a little more coverage to
your system.
By randomly ordering the tests, the risk of surprising inter-test
dependencies is reduced - a technique used in many places, for example
Google’s C++ test runner googletest.
You can run tests randomly (at the file level) by setting the random property in your config . You can also set your salt/seed so it's reproducibly random.
/**
* If true, run specs in semi-random order
*/
random?: boolean,
/**
* Set the randomization seed if randomization is turned on
*/
seed?: string,
You could also turn on shardTestFiles (parallel test runs), which should also be very telling in how coupled your tests are.
Did you try shuffling "it" blocks like below:
var shuffle = function (items) {
var item, randomIndex;
for(var i = 0; i < items.length; i++){
randomIndex= (Math.random() * items.length) | 0;
item = items[i];
items[i] = items[randomIndex];
items[randomIndex] = item;
}
}
describe('Suite', function() {
it("should a", function () {
console.log("execute a");
});
it("should b", function () {
console.log("execute b");
});
it("should c", function () {
console.log("execute c");
});
shuffle(this.children); // shuffle the 'it' blocks
});
Source: Can protractor tests be run in a random order?
One problem is you likely have no idea how tests might be coupled. If one test referenced some variables from another test, you might be able to find those automatically but that's only one way tests might be coupled and probably not a likely scenario.
My first thought was to just run them individually and see which ones fail. The problem is that if you aren't cleaning state between tests, you might change the order (randomizing them, as you suggested) but if test 50 expects the data that test 20 set up but in the new order, test 20 still runs before test 50... test 50 will still pass. You will find some but probably not all until you run all of them in a random order several times.
You don't describe your application but my second thought was if there was a way to get back to a clean slate between tests, you should be able to find the tests that rely on other tests to set up data. I'm kinda surprised you aren't doing that already but if there's a long setup process that has to run to install a clean slate, etc. that might be an issue. Depending on your system, you might be able to snapshot a VM after a clean install and restore it to "quickly" get back to clean or you may be able to roll back SQL tables, etc. It really depends on your system and without more details on the system, it's hard to offer advice.
Another option is to go to those that wrote or maintain the tests and have them self-identify the tests they own that are coupled and fix them. This likely won't find them all but it might be a semi-quick start.
Oh... I just thought of one more thing. If you could reverse the order of test execution, that should be better than randomizing the execution. With reverse order, NO test would run after it's former predecessor and you should be able to find them all in one go.

Whack-A-Mole game with huge bug! Can I get some help fixing it?

I am writing a Whack-A-Mole game for class using HTML5, CSS3 and JavaScript. I have run into a very interesting bug where, at seemingly random intervals, my moles with stop changing their "onBoard" variables and, as a result, will stop being assigned to the board. Something similar has also happened with the holes, but not as often in my testing. All of this is completely independent of user interaction.
You guys and gals are my absolute last hope before I scrap the project and start completely from scratch. This has frustrated me to no end. Here is the Codepen and my github if you prefer to have the images.
Since Codepen links apparently require accompanying code, here is the function where I believe the problem is occuring.
// Run the game
function run() {
var interval = (Math.floor(Math.random() * 7) * 1000);
if(firstRound) {
renderHole(mole(), hole(), lifeSpan());
firstRound = false;
}
setTimeout(function() {
renderHole(mole(), hole(), lifeSpan());
run();
}, interval);
}
What I believe is happening is this. The function runs at random intervals, between 0-6 seconds. If the function runs too quickly, the data that is passed to my renderHole() function gets overwritten with the new data, thus causing the previous hole and mole to never be taken off the board (variable wise at least).
EDIT: It turns out that my issue came from my not having returns on my recursive function calls. Having come from a different language, I was not aware that, in JavaScript, functions return "undefined" if nothing else is indicated. I am, however, marking GameAlchemist's answer as the correct one due to the fact that my original code was convoluted and confusing, as well as redundant in places. Thank you all for your help!
You have done here and there in your code some design mistakes that, one after another, makes the code hard to read and follow, and quite impossible to debug.
the mole() function might return a mole... or not... or create a timeout to call itself later.. what will be done with the result when mole calls itself again ? nothing, so it will just be marked as onBoard never to be seen again.
--->>> Have a clear definition and a single responsibility for mole(): for instance 'returns an available non-displayed mole character or null'. And that's all, no count, no marking of the objects, just KISS (Keep It Simple S...) : it should always return a value and never trigger a timeout.
Quite the same goes for hole() : return a free hole or null, no marking, no timeout set.
render should be simplified : get a mole, get a hole, if either couldn't be found bye bye. If a mole+hole was found, just setup the new mole/hole couple + event handler (in a separate function). Your main run function will ensure to try again and again to spawn moles.

Why is ReactJS not performant like raw JS for simple, stupid proof of concept?

Years ago, I heard about a nice 404 page and implemented a copy.
In working with ReactJS, the same idea is intended to be implemented, but it is slow and jerky in its motion, and after a while Chrome gives it an "unresponsive script" warning, pinpointed to line 1226, "var position = index % repeated_tokens.length;", with a few hundred milliseconds' delay between successive calls. The script consistently goes beyond an unresponsive page to bringing a computer to its knees.
Obviously, they're not the same implementation, although the ReactJS version is derived from the "I am not using jQuery yet" version. But beyond that, why is it bogging? Am I making a deep stack of closures? Why is the ReactJS port slower than the bare JavaScript original?
In both cases the work is driven by minor arithmetic and there is nothing particularly interesting about the code or what it is doing.
--UPDATE--
I see I've gotten a downvote and three close votes...
This appears to have gotten response from people who are (a) saying something sensible and (b) contradicting what Pete Hunt and other people have said.
What is claimed, among other things, by Hunt and Facebook's ReactJS video, is that the synthetic DOM is lightning-fast, enough to pull 60 frames per second on a non-JIT iPhone. And they've left an optimization hook to say "Ignore this portion of the DOM in your fast comparison," which I've used elsewhere to disclaim jurisdiction of a non-ReactJS widget.
#EdBallot's suggestion that it's "an extreme (and unnecessary) amount of work to create and render an element, and do a single document.getElementById. Now I'm factoring out that last bit; DOM manipulation is slow. But the responses here are hard to reconcile with what Facebook has been saying about performant ReactJS. There is a "Crunch all you want; we'll make more" attitude about (theoretically) throwing away the DOM and making a new one, which is lightning-fast because it's done in memory without talking to the real DOM.
In many cases I want something more surgical and can attempt to change the smallest area possible, but the letter and spirit of ReactJS videos I've seen is squarely in the spirit of "Crunch all you want; we'll make more."
Off to trying suggested edits to see what they will do...
I didn't look at all the code, but for starters, this is rather inefficient
var update = function() {
React.render(React.createElement(Pragmatometer, null),
document.getElementById('main'));
for(var instance in CKEDITOR.instances) {
CKEDITOR.instances[instance].updateElement();
}
save('Scratchpad', document.getElementById('scratchpad').value);
};
var update_interval = setInterval(update, 100);
It is doing an extreme (and unnecessary) amount of work and it is being done every 100ms. Among other things, it is calling:
React.createElement
React.render
document.getElementById
Probably with the amount of JS objects being created and released, your update function plus garbage collection is taking longer than 100ms, effectively taking the computer to its knees and lower.
At the very least, I'd recommend caching as much as you can outside of the interval callback. Also no need to call React.render multiple times. Once it is rendered into the dom, use setProps or forceUpdate to cause it to render changes.
Here's an example of what I mean:
var mainComponent = React.createElement(Pragmatometer, null);
React.render(mainComponent,
document.getElementById('main'));
var update = function() {
mainComponent.forceUpdate();
for(var instance in CKEDITOR.instances) {
CKEDITOR.instances[instance].updateElement();
}
save('Scratchpad', document.getElementById('scratchpad').value);
};
var update_interval = setInterval(update, 100);
Beyond that, I'd also recommend moving the setInterval code into whatever React component is rendering that stuff (the Scratchpad component?).
A final comment: one of the downsides of using setInterval is that it doesn't wait for the callback function to complete before queuing up the next callback. An alternative is to use setTimeout with the callback setting up the next setTimeout, like this
var update = function() {
// do some stuff
// update is done to setup the next timeout
setTimeout(update, 100);
};
setTimeout(update, 100);

play a single beep (beep.js)

i'm trying to create a "generative score" using beep.js based on some map data i have. i am using new Beep.Voice as placeholder for notes associated to specific types of data (7 voices total). as data is displayed, a voice should be played. i'm doing things pretty "brute force" so far and i'd like it to be cleaner:
// in the data processing function
voice = voices[datavoice]
voice.play()
setTimeout(function(){killVoice(voice)}, 20)
// and the killvoice:
function killVoice(voice) {
voice.pause()
}
i'd like to just "play" the voice, assuming it would have a duration of, say, 20ms (basically just beep on data). i saw the duration property of voices but couldn't make them work.
the code is here (uses grunt/node/coffeescript):
https://github.com/mgiraldo/inspectorviz/blob/master/app/scripts/main.coffee
this is how it looks like so far:
https://vimeo.com/126519613
The reason Beep.Voice.duration is undocumented in the READ ME is because it’s not finished yet! ;) There’s a line in the source code that literally says “Right now these do nothing; just here as a stand-in for the future.” This applies to .duration, .attack, etc. There’s a pull request to implement some of this functionality here but I’ve had to make some significant structural changes since that request was submitted; will need to take a closer look soon once I’ve finished fixing some larger structural issues. (It’s in the pipeline, I promise!)
Your approach in the meantime seems right on the money. I’ve reduced it a bit here and made it 200 milliseconds—rather than 20—so I could here it ring a bit more:
var voice = new Beep.Voice('4D♭')
voice.play()
setTimeout( function(){ voice.pause() }, 200 )
I saw you were using some pretty low notes in your sample code, like '1A♭' for example. If you’re just testing this out on normal laptop speakers—a position I am often myself in—you might find the tone is too low for your speakers; you’ll either hear a tick or dead silence. So don’t worry: it’s not a bug, just a hardware issue :)
Forget everything I said ;)
Inspired by your inquiry—and Sam’s old pull request—I’ve just completed a big ADSR push which includes support for Voice durations. So now with the latest Beep.js getting a quick “chiptune-y” chirp can be done like this:
var voice = new Beep.Voice( '4D♭' )
.setOscillatorType( 'square' )
.setAttackDuration( 0 )
.setDecayDuration( 0 )
.setSustainDuration( 0.002 )
.setReleaseDuration( 0 )
.play()
I’ve even included an ADSR ASCII-art diagram in the new Beep.Voice.js file for easy referencing. I hope this helps!

Box2dWeb call function when objects collide

I'm fairly new to javascript and box2d, i was wondering if someone knows how i can call a custom function when two objects collide. I tried using some examples that uses the b2ContactListener without any succes. I've placed an object above another and let the standard Box2d physics do it's thing.
I recieve two console outputs, the first is null and the second is Ball with the following code:
var listener = new Box2D.Dynamics.b2ContactListener;
listener.BeginContact = function(contact) {
console.log(contact.GetFixtureA().GetBody().GetUserData());
console.log(contact.GetFixtureB().GetBody().GetUserData());
};.
The two objects that need to collide are a b2_dynamicbody (ball) and a b2PolygonShape. (rectangle). Using bodyDef.userData = "Ball"; in my Ball.js and bodyDef.userData = "Mouse"; in my Mouse.js i try to identify if they are hit. Instead only the ball is displayed.
Next to that i'm sure this is not the correct way for detecting collision :P I hope i've explained it well enough, could somebody steer me in the right direction?
Ok I solved it myself, apparently I had to add my custom event to the world I create with box2d. So, the issue was solved by me reading big chunks of box2d documentation/manual which can be found here:
I started with adding a String as UserData() to every object which can collide and has to do something else next to just colliding. Using the following code:
bodyDef.userData = "Car";
note: every object has to have it's own unique string.
Then I created a new contact listener (formulated in my question above) and listened for fixtures colliding with each other. When that happens, I 'save' the fixtures UserData() in variables which I can then use to look what objects collide with each other.
var contactListener = new Box2D.Dynamics.b2ContactListener;
contactListener.BeginContact = function(contact) {
var fixA = contact.GetFixtureA().GetBody().GetUserData();
var fixB = contact.GetFixtureB().GetBody().GetUserData();
// if else statement here...
};
world.SetContactListener(contactListener);
Finally, I added the last statement world.SetContactListener(contactListener); to add the event to the world, making it possible for it to listen to collisions, which I forgot to add and thus was my problem.
Hope someone finds this usefull!

Categories