Just lately I used to be requested on Twitter to do a tutorial on QUnit, a JavaScript Unit Testing framework, and the one utilized by jQuery. What I wished to do nevertheless, is use it with an actual undertaking, moderately than arrange some pretend undertaking. So, I’ve finished simply that. Having labored with the Instagr.am API just lately, I’ll use this sequence of tutorials to put in writing a JavaScript wrapper for the Instagram API & take a look at it with QUnit. Not like most content material on this website, that is going to be a multi-part tutorial, however I hope to nonetheless handle to attain 1-2 particular issues inside every put up. When you’ve any questions, please go away a remark & I’ll reply all questions firstly of the subsequent tutorial. I will presume you are vaguely accustomed to the concept of Unit Testing typically. On the finish of the sequence it’s best to have a working information of QUnit and how one can use it. I will additionally open supply the Instagram Wrapper we create onto Github. As this sequence is especially specializing in testing, I wont spotlight how I do the whole lot by way of querying the Instagram API however I’ll level out particular bits that I feel are helpful.
What we’ll obtain in the present day
Arrange a QUnit testing suite
Write our first QUnit assessments
Question the Instagram API to get data on a particular Instagram Picture
Learn to take a look at Async calls in QUnit
Step one is to arrange our listing. I wish to set mine up like so:
/app
instagramwrapper.js
/take a look at
instagramwrapper_tests.js
/qunitsrc
assessments.html
The very first thing we have to do is embrace all of the QUnit supply. QUnit wants 3 issues:
We have to embrace the QUnit JS Supply
We will hyperlink to the QUnit stylesheet to make the output look good
It wants a particular HTML construction.
You could find obtain hyperlinks for the JS & CSS information right here. You might embrace them direct however I wish to obtain them & add them regionally, placing them into the qunitsrc listing.
<hyperlink rel=“stylesheet“ href=“qunitsrc/qunit.css“ kind=“textual content/css“ media=“display screen“>
<script kind=“textual content/javascript“ src=“qunitsrc/qunit.js“></script>
<script kind=“textual content/javascript“ src=“app/instagramwrapper.js“></script>
<script kind=“textual content/javascript“ src=“take a look at/instagramwrapper_tests.js“></script>
And the HTML construction we want:
<h1 id=“qunit-header“>QUnit Check Suite</h1>
<h2 id=“qunit-banner“></h2>
<div id=“qunit-testrunner-toolbar“></div>
<h2 id=“qunit-userAgent“></h2>
<ol id=“qunit-tests“></ol>
Most of these are pretty explanatory. If not, don’t fret, as soon as we run an precise take a look at it ought to change into extra obvious. Earlier than we write our precise code, lets arrange a take a look at take a look at simply to verify it really works. Load up instagramwrapper_tests.js (I will consult with this as simply “the assessments file” any more) and put in:
perform saysHi(title) {
return “Hello, ” + title;
};
take a look at(‘saysHi()’, perform() {
equal(sayHi(“Jack”), “Hello, Jack”, “perform outputs string accurately”)
});
You possibly can see I outline a easy perform after which run assessments on it, anticipating sayHi(“Jack”) to equal “Hello, Jack”. When you run it nevertheless, we get a failure:
saysHi() (1, 0, 1)
Died on take a look at #1: sayHi is just not outlined
Supply: at Object.<nameless> (http://instagram.jsp/take a look at/instagramwrapper_tests.js:6:10)
Why’s that? Nicely, seems within the equal() name I referenced sayHi, however it’s truly saysHi.
Run it once more, and it passes!
Now, for our first actual take a look at, lets check out the Instagram API. Say I’ve an Instagram URL, equivalent to http://instagr.am/p/JYAdvJr0K9/ (which occurred to be the primary URL I discovered in my Twitter feed). And I wish to get the precise URL to it. After we’re testing, we first write assessments, see them fail, after which make them move. Earlier than we dive in, I will simply do some arrange in the principle implementation file:
(perform() {
var instagramwrapper = {
oembed: {
web_url: “”,
}
};
window.instagramwrapper = instagramwrapper;
})();
The explanation for the oembed namespace is that the little bit of the API we’ll be utilizing is named as such. So, time to put in writing some assessments. I will write a pair simply to examine we have set issues up accurately, after which we will get into particular assessments for this bit. Here is my preliminary assessments:
take a look at(‘Set Up Checks’, perform() {
okay(instagramwrapper, “instagram wrapper is exists and isn’t undefined”);
});
take a look at(‘oembed’, perform() {
okay(instagramwrapper.oembed, “oembed namespace exists”);
instagramwrapper.oembed.web_url = “http://instagr.am/p/JYAdvJr0K9/”;
equal(instagramwrapper.oembed.web_url, “http://instagr.am/p/JYAdvJr0K9/”, “Can set the web_url accurately”);
});
All these assessments move, however one factor was irritating me, and that’s that by default QUnit would not present all of the assessments, however simply the heading:
I wished to alter this, so I delved into the QUnit JS supply and on line 192 I discovered:
if (dangerous === 0) {
ol.fashion.show = “none”;
}
I merely commented out that center line and now it exhibits the complete particulars:
Clearly that is extra a private choice, so if you wish to do it, be at liberty, but when not, that is tremendous too.
Now I wish to write some code to get the media URL that’s returned from this API finish level: http://api.instagram.com/oembed?url=http://instagr.am/p/BUG/. I might write the Ajax name in a get_url() perform however as this question returns a set of knowledge, I will write a perform to take a callback that has the information handed into it, and let the consumer then seize what they want. I will even be utilizing jQuery right here for the Ajax calls. We might do them in cross browser JS, however that is an enormous ache & past the scope of this tutorial.
Usually at this stage I would say to put in writing the take a look at, however we’ve an issue. How can we take a look at asynchronously?
The plain reply is to make the Ajax take a look at non-async, however that is not answer. Fortunately, QUnit helps us out right here with its asyncTest() technique.
QUnit has cease() and begin() strategies which inform the framework to cease its assessments, so it will possibly watch for a Ajax name to run after which begin the requests once more. The asyncTest() technique simply does the cease() bit for us. So most asynchronous assessments look a bit like:
asyncTest(“some Ajax name”, perform() {
someAjaxCall(perform(resp) {
//callback
begin(); //inform QUnit to run assessments once more
});
});
And contained in the callback, earlier than you name begin(), is the place you run your assertions that depend on the Ajax end result. I’ve written some assessments throughout the callback that ought to validate the whole lot works accurately. I then name begin() to inform QUnit it will possibly run the remainder of its assessments once more.
take a look at(‘oembed’, perform() {
okay(instagramwrapper.oembed, “oembed namespace exists”);
instagramwrapper.oembed.web_url = “http://instagr.am/p/JYAdvJr0K9/”;
equal(instagramwrapper.oembed.web_url, “http://instagr.am/p/JYAdvJr0K9/”, “Can set the web_url accurately”);
});
asyncTest(“oembed AJAX”, perform() {
instagramwrapper.oembed.web_url = “http://instagr.am/p/JYAdvJr0K9/”;
instagramwrapper.oembed.question(perform(res) {
okay(res, “AJAX name acquired a end result”);
okay(res.url, “URL exists in response”);
equal(res.url, “http://distilleryimage5.instagram.com/9436051c85b011e18cf91231380fd29b_7.jpg”, “URL returned is appropriate”);
equal(res.title, “Drainpipe”, “The title returned is appropriate”);
begin();
});
});
Working these assessments (with none implementation, rememeber!) offers you some errors. Now we take the subsequent TDD step. Repair these errors, one after the other. The primary will complain about question() being undefined, so add the perform, refresh & proceed on. You may hit a little bit of an issue right here. The assessments will simply run eternally, as that begin() by no means will get known as. It is because the perform question() exists, however it does nothing. So QUnit would not get an error that question() is undefined, so it calls it however then by no means will get that begin() name once more. What we will do to stop this situation is so as to add a setTimeout after my assertions that may run after 1000 milliseconds, telling QUnit to proceed anyway:
setTimeout(perform() {
begin();
}, 1000);
That provides us the error:
Anticipated no less than one assertion, however none had been run – name anticipate(0) to simply accept zero assertions.
One other function is that we will inform QUnit what number of assertions we anticipate, so it is aware of when that does not occur & can inform us. In our case, we anticipate 4. Two calls to okay(), and two to equal(). We move this in because the second parameter to asyncTest():
asyncTest(“oembed AJAX”, 4, perform() {
At this level QUnit provides us the error:
Anticipated 4 assertions, however 0 had been run
I am not going to indicate you how one can clear up all these points as most are straight ahead from right here on in, it is a easy Ajax name. Here is my implementation:
question: perform(cb) {
var ajxreq = $.Ajax({
url: “http://api.instagram.com/oembed?url=” + this.web_url,
dataType: ‘jsonp’
});
ajxreq.success(perform(resp) {
cb(resp);
});
}
The code works by taking a callback, that it’s going to mechanically move our knowledge into.
Run the assessments, and I am greeted with all greens, pretty!
That brings us to the top of the primary tutorial. On this we have achieved an incredible deal, studying how QUnit works, how one can run async assessments in QUnit and dealing with the Instagram API too. Not dangerous in any respect! Subsequent time we’ll proceed writing & testing, however at a bit extra of a quicker tempo, now you’ve got acquired the cling of QUnit. You may get all of the code from the Github Repo. Every tutorial is by itself department, for this one you need the department tutorial1. The grasp department will comprise the present updated code, whereas the tutorial branches will solely comprise the code from every tutorial and no extra. Any questions, please go away a remark and I’ll reply them partially 2.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!