Loading... Loading latest track...

TDD and JavaScript with Jasmine

Tonight I had an hour-long slot at Trondheim XP and Agile Meetup. The subject was using TDD and JavaScript. I used the JasmineBDD framework to write my unit tests.

Demo on using TDD on JavaScript

I purposefully kept the slideshow to a minimum. I wanted it to be demo-heavy. I felt it would be easier to explain how to use TDD to unit test your JavaScript by showing it being done instead of talking about it.

All of the code I wrote is in my Samples github repository, specifically the code is right here.

I wanted to make certain points clear:

  • It isn't hard.
  • Once you get into the swing of it, using TDD on your JavaScript feels very smooth - the workflow is great. To prove this, I even did the first demo without using my mouse.
  • Our JavaScript today is doing increasingly complex stuff. Node.js even gives us the ability to run JavaScript on the server. Due to the complexity and importance of our JavaScript code nowadays, the importance to unit-test that code is also increasingly important.
  • Unit testing is made harder by code that has dependencies. On server-side code, dependencies might be databases, file systems or network communications. With (client-side) JavaScript, dependencies are typically two things: 1) the HTML/DOM, and 2) AJAX calls. My second and third demo's showed that those dependencies can be controlled and even faked. Firstly, you can set-up the DOM prior to running your tests with HTML test fixtures, and AJAX calls can be mocked with JavaScript spy objects.

Demo 1: implement the FizzBuzz kata

Using TDD from the word go, I implemented FizzBuzz. I created a standalone JavaScript module, and unit tested it until it was finished. This was an intro to Jasmine and TDDing your JavaScript.

Demo 2: writing a jQuery plugin

This demo showed the important technique of setting up the HTML / DOM prior to running a test, then running code that manipulates that HTML, and finally making assertions against the resulting HTML. Both the production code, and unit tests, made use of jQuery.

Demo 3: faking AJAX calls

The third and final demo showed the importance of JavaScript test spies. In JavaScript testing frameworks, spies assist us in all areas related to mocking/faking behaviours. True unit tests don't communicate over networks, but ideally we would like to test all of our own JavaScript code just before making an AJAX call, and the code that runs after the AJAX call is complete. This was achieved with Jasmine's test spies.

I've had nothing but fun while doing TDD and JavaScript over the last few months, and Jasmine has been a big part of that. Hopefully I spread the word tonight and encouraged others to check it out.

A guide to Twitter that even your dad will understand

My dad just asked me to explain to him how Twitter works. He wanted a short intro explaining what all of the # and @ symbols mean, and how to get "those short URL's". His opinion of Twitter is like many peoples: "I'm not interested in what people are eating for lunch or when they are going to the bathroom". I used to think the same, but that's because I didn't understand it and how to make it a useful tool. Twitter has become useful for me to keep up to date with technology, other software developers, for me to share info, help others and get help from others. It is useful for sharing interesting links with other people. I use it (almost) exclusively for programming and technology. I don't use it for personal stuff. I use Facebook for that. If someone uses Twitter to tell the world pointless drivel about what clothes they are wearing, then I don't follow those people and hence can't see their tweets.

The first thing I recommend is using a Twitter client for Mac/Windows. I use TweetDeck. Without a proper Twitter client, you can never get the most of Twitter. The website is limited, and so are some of the mobile clients, but the desktop clients bring Twitter to life.

You can see from the screenshot above that there are four columns visible, and they all show me different things. In order from left to right, here is what each column shows me:

  1. All tweets from all of the people I am following.
  2. All tweets where people have mentioned me.
  3. All direct messages to me (private messages).
  4. Finally, the last column shows all tweets where people have mentioned a specific keyword I am interested in: the "MonoTouch" keyword.

Followers

When you find a friend, celebrity or just an interesting person, and want to hear more of what they say, you should "follow" them. When you follow a person, they are now on the list of people you follow, and their tweets will show up when you go to Twitter or, for me, in the first column of my TweetDeck. But just because you follow a person and can see all of their tweets, that doesn't mean they follow you and can see yours. If it's a friend of yours, they will probably check which people are following them, see your username and follow you back. If it's a famous celebrity or just some stranger, they might not follow you back.

An @ mention

The second column in my TweetDeck are my "mentions". My Twitter username is alex_york, but if someone who I don't follow said "hello, alex_york" I would never know about it. If they said "hello, @alex_york" then regardless of who they are, where they are, or if I am following them or not, their tweet would show up in that second column. That's how strangers can talk to each other, and that's the whole beauty of Twitter. I could say "hello, @JohnCleese, have you seen Manuel lately?" and he would see my message. He might not reply to it though! In short, it's how you get someone's attention.

A #hashtag

The last column in my TweetDeck is where I follow a keyword that I am interested in: the "MonoTouch" keyword. On Twitter, these keywords are known as "hashtags" because the tag/keyword is preceded by the # symbol. If I were to tweet "I love writing iPhone apps using MonoTouch" then only my followers could see it, but if I said "I love writing iPhone apps using #MonoTouch" then many people around the world might be watching the #MonoTouch hashtag and suddenly my tweet would have a much wider audience. Use a hashtag in your tweet when you want to reach a wider audience than just your followers, and keep a track of hashtags that you are interested in. There are no definitive list of hashtags, they can be anything you like, such as #ClimateChange or #iPad.

Hashtags are really interesting when it comes to timely information. The moment that Apple announced the iPad, on Twitter it was fun to watch what everyone was saying about it by following the #iPad hashtag. When Tottenham Hotspur play, I noticed that a lot of people were talking about the game using the #COYS hashtag (come on you spurs!).

Short URL's

Finally, because you can only have 140 characters in a tweet, when you want to share a link with someone, you will want to shorten it down. Some popular URL shortening services are TinyURL and bit.ly. You can go to their websites and do it manually. But that's no fun! Luckily, TweetDeck will shorten URL's for you automatically. There is a button that you can click to enable the auto-shortening of URLs.

Once enabled, you just paste a long URL in there and a few seconds later it will replace it with a short one. Easy! Your link is now ready to be shared on twitter leaving you lots of space to tell people what the link is.

Happy tweeting ;-)

Syntax highlighting in blog posts - Prettify

Over the weekend I switched the way that my blog does code syntax highlighting.  Before, I copied my C# code manually into the tool over at Manoli.net which puts <span> tags and CSS classes around my code to format it. Then I manually used a HTML encoding tool, and put it into my blog posts. The reasons why this isn't great are obvious but I will spell them out anyway:

  • It's slow (for me to go through all those manual steps).
  • The HTML is larger and messier.

I have switched to client-side JavaScript highlighting. I use the Prettify project over on Google Code. I also considered Alex Gorbatchev's Syntax Highlighter which I heard was very good, but in the end went for Prettify. There are pro's and con's of moving towards a JavaScript highlighter, but the pro's far outweigh the con's in my scenario.

The con's are:

  • It's slower (for the reader - there is a noticeable lag).

The pro's are:

  • It's far quicker for me to post code samples.
  • I know that my posts are aimed at developers so they will have fast computers, modern browsers, and won't notice the client-side lag so much.
  • The code looks better in the browser.
  • The code looks better in the "view HTML source" option in your browser.

On a side note, I don't like posting code samples as images. It's harder for the reader to copy and paste, it's harder for search engines to index, and it's not accessible.

A while ago I wrote a pretty simple ASP.NET control to show the last song you listened to (via Last.fm) on your own website.  You can see mine at the top of this page, just underneath the header.

Some of you will have noticed a performance hit on the page load time by looking at the code. I accessed the Last.fm AudioScrobbler XML service with a single line of code:

XDocument recentTracksXml =
XDocument.Load(
"http://ws.audioscrobbler.com/1.0/user/televisionfoot/recenttracks.xml");

The problem with this is that I don't know how long it will take to go and fetch this XML file (it's not a service I have control of). Showing the last song I listened to is hardly critical to my website, and I don't want to increase the page load time if the service is slow. The problem, of course, is that I'm not calling this service asynchronously.

The ideal scenario would be to render the page first (as quickly as possible), and then go and fetch the XML asynchronously from the client side while the reader is looking at my website. There is a very easy way to do this: enter AJAX with jQuery.

Firstly, I wrote a web service that will fetch me the last track I listened to via Last.fm's AudioScrobbler service. I made the web service return a chunk of HTML, nice and easy to insert directly into the DOM. The web service method looks something like this:

[WebMethod]
public string GetMostRecentTrack()
{
XDocument mostRecentTracksXml =
XDocument.Load(
"http://ws.audioscrobbler.com/1.0/user/televisionfoot/recenttracks.xml");

XElement mostRecentTrackXml = mostRecentTracksXml.Root.Elements("track").First();

return string.Format("<p>Last listened to {0} by {1}</p>",
(string) mostRecentTrackXml.Element("name"),
(string) mostRecentTrackXml.Element("artist"));
}

The key thing is that I call this service using jQuery's $(document).ready event - which of course fires after the page has finished loading. This way, the user gets the page as quick as possible, and I fetch the additional data (the latest track I listened to) asynchronously and display it when it's ready. This speeds up the page loading time, and improves the overall user experience. The jQuery looks similar to the following:

<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type: "POST",
url: 'LastFmService.asmx/GetMostRecentTrack',
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("div.MostRecentTrackContainer").append(msg.d);
},
error: function(msg) {
$("div.MostRecentTrackContainer").append('Error - try again later.');
}
});
});
</script>

To really add the finishing touches to this bit of code, I actually do a few other things that I don't show here in this blog post:

  • I cache the most recent track data for 10 minutes once it has been fetched. I only bother to do the client side AJAX call if I don't already have cached data available on the server.
  • If I do perform the AJAX client-side call, initially I show an AJAX style animated gif, and then switch to the most recent track text once it is available.
  • When I switch from the animated loading gif to the recent track text, I use jQuery's fadeOut() and fadeIn() animation effects, to really add the finishing touches!

This is what it looks like if a user hits my page and nothing is cached:

The end resuult of all of this is giving the user a bit of up-to-date information about the author of this site with no performance hit on page loading times and to top it off some pretty awesome client side animation effects.

I use last.fm and let it's audioscrobbler services keep a track of whatever music I listen to. As you can see, just below the navigation bar on this website I use its API to display the last track I listened to.

Here's what it looks like when it's in action:

It's incredibly easy to add this onto your website too, if you're an ASP.NET developer. Here's how.

Create a new User Control in your website, and call it MostRecentTrack.ascx. In the codebehind file, copy and paste the following:

protected XElement MostRecentTrack { get; set; }

protected void Page_Load(object sender, EventArgs e)
{
    GetLatestTrack();

    if (MostRecentTrack == null)
        LatestTrackHolder.Visible = false;
}


private void GetLatestTrack()
{
    MostRecentTrack = Cache["MostRecentTrack"] as XElement;
    if (MostRecentTrack != null) return;

    string xmlLocation =
        string.Format("http://ws.audioscrobbler.com/1.0/user/{0}/recenttracks.xml",
                      LastFmUsername.Text);

    try
    {
        MostRecentTrack = XDocument.Load(xmlLocation).Descendants("track").First();
        Cache.Insert("MostRecentTrack",
                     MostRecentTrack,
                     null,
                     DateTime.MaxValue,
                     TimeSpan.FromMinutes(10));
    }
    catch
    {
        // Catch everything so that any failure doesn't bring the website down
        MostRecentTrack = null;
    }
}

In the HTML section of your control, put the following code:

<asp:PlaceHolder ID="LatestTrackHolder" runat="server">
    <p class="LatestTrack">
        Last listened to <%= (string) MostRecentTrack.Element("name") %>
        by <%= (string) MostRecentTrack.Element("artist") %>
        (on <%= (string) MostRecentTrack.Element("date") %>)
    </p>
    <asp:Literal ID="LastFmUsername" runat="server"
                 Visible="false"
                 Text="YOUR_USERNAME_HERE" />
</asp:PlaceHolder>

This code uses System.Linq and System.Xml.Linq so don't forget to add the relevant references. Also, don't forget to put your real last.fm username in the hidden Literal in your HTML code. When you've created your control, add it to your page like this:

<%@ Register Src="~/MyUserControls/MostRecentTrack.ascx"
    TagName="MostRecentTrack" TagPrefix="lastFm" %>

<lastFm:MostRecentTrack runat="server" />

I've got it below my navigation menu on my master page, so it shows up on every page.