Author Archive

Which JavaScript Recipe Is Right For You?


  

JavaScript has been called everything from great to awful to the assembly language of the Web, but we all use it. Love JavaScript or hate it: everyone admits there are serious flaws and not many other choices.

Let’s start with some fundamental negatives. JavaScript has no good answer for some really basic features of modern programming languages: private variables and functions, packages and modules, standard localization mechanisms, code completion in editors.

While JavaScript is missing a lot of features, it’s the very dynamic nature of the language that scares so many static programming believers. This is all valid JavaScript:

obj1 = {
    func1: function() {
        return "I'm function 1";
    }
};

obj1['func2'] = function() {
    return "I'm function 2";
};

obj1['fu' + 'nc' + 3] = function() {
    return "I'm function 3";
}

var f = 'func4';

obj1[f] = function() {
    return "I'm function 4";
}

alert(obj1.func2());
alert(obj1.func3());
alert(obj1.func4());

Most languages support dynamic code loading, but JavaScript encourages it. JavaScript has a lot of dark corners. Did you know that adding two arrays in JavaScript results in an empty string, or that [] + {} results in the string [object Object] but {} + [] is 0? Wat?!?

JavaScript makes it so easy to write unreadable code that it’s impossible to write large projects in JavaScript… except for Twitter, Facebook, Google, every big website you’ve ever heard of and hundreds of others.

These shortcomings cause me problems every day, but I still love JavaScript. It’s fun to code and it’s far from the assembly language of the Web. Assembly is nearly impossible to write by hand and even harder to read:

C005 B7 80 04        STA A  ACIA
C008 86 11           LDA A
C00A B7 80 04        STA A  ACIA

JavaScript is easy to write. If I have a button and want to know when someone clicks it, I write a click function:

$('#myButton').click(function() {
    alert('I was clicked');
});

Your grandmother can guess what this code does. That’s why JavaScript is a good first programming language and a great prototyping language. JavaScript programs go from a blank page to a working app ridiculously fast. They’re quick to write, don’t require a compiler and allow you to do anything you need.

These two views of JavaScript are difficult to reconcile. Is JavaScript an ill-defined loose language designed to cause premature gray hair, or a fun place to work? The answer is both.

We face this choice with every new Web project. Should we write JavaScript, or another language that generates it? This article shows you how to choose.

JavaScript Is Constantly Improving

JavaScript is the most popular client-side programming language in the world. It’s tough to find a website that doesn’t run it. It’s also come a long way with the introduction of excellent libraries like jQuery, Backbone and countless others. JavaScript wins easily for small projects, but it falters when the projects and teams get larger.

Every large JavaScript project adopts conventions to compensate for the lack of language features. They’re simple patterns like using an underscore to mark some functions as private, or adding comments before arguments to indicate the expected type.

function formatDate(/* Date */ d) {
    var day = d.getDate();
    var month = d.getMonth() + 1;
    var year = d.getFullYear();
    return date + "-" + month + "-" + year;
}

These comments help, but there’s nothing to stop you from passing a string, number or anything else to the formatDate function. You can’t enforce a coding convention and you’ll never know it’s broken until the code actually runs in your production environment and fails. Extra type checking like instanceOf makes the program fail with a better error message, but it still fails at runtime instead of getting caught by the compiler.

Tools like JSLint or JSHint find common syntax problems like using == when you should have used ===, but they don’t address the larger issues. Libraries like RequireJS provide some support for modules in JavaScript, but that’s still just a convention. With nothing to enforce these patterns, you’ll spend endless hours tracking down annoying bugs. It’s never fun to debug someone else’s JavaScript.

Programmers love coming up with new solutions to existing problems, but there aren’t many good alternatives to JavaScript.

Google Web Toolkit (GWT)

Google made the first major effort to replace JavaScript with GWT. The idea was to write Java code and compile it into JavaScript. Java provides many of the language features JavaScript is missing, and the compiler makes it possible to do a lot of checking before your code runs. With a nice debugger and a UI library added in, GWT looked like it would take over the world.

It didn’t.

GWT hasn’t failed (yet), but it hasn’t succeeded either. Java is a difficult language to write. It has a lot of complexity and requires a deep understanding of object-oriented programming. Remember, Java was invented to replace C++.

Most of Java’s complexity comes from the hard problems it solves. That’s nice if you were going to have those problems, but overkill if you weren’t.

GWT added the complexity of the Web on top of Java. It was also positioned as a way to write code for the Web without needing to worry about browsers or HTML. It produced interfaces that looked clunky and ran slowly. It also led to some bad anti-patterns.

It’s possible to write good applications in GWT, but it takes a lot of work.

Even more distressing are the clear indications that GWT isn’t the future. Google’s still maintaining it, but the community is dwindling and its dreams of world domination are long gone. Even Google never really used GWT. All of their major products (Search, Gmail, Maps, Calendar, Docs, Google+) are written in JavaScript. Well… sort of JavaScript, but we’ll get to that a little later.

I still use GWT professionally, but I question it with every new project. GWT tried to drastically change the JavaScript ecosystem and it’s tough to turn an aircraft carrier on a dime.

CoffeeScript

The CoffeeScript team didn’t redefine JavaScript, they just gave it a face-lift. CoffeeScript added new syntax to improve some of the day-to-day difficulties of JavaScript programming without drastically changing the language.

Instead of this:

$(document).ready(function() {
    alert('Hello World!');
});

CoffeeScript lets you write this:

$(document).ready ->
    alert 'Hello World!';

The general philosophy is that writing less code means you have fewer bugs. CoffeeScript simplifies the JavaScript syntax by removing the need to declare var and using white-space indenting instead of curly braces.

CoffeeScript is growing fast, loved by Ruby programmers and hated by anyone with a secret crush on curly brackets. CoffeeScript compiles into JavaScript either when the page is run, or ahead of time during a build step.

CoffeeScript makes many syntactic improvements over JavaScript, but it has two main flaws. The first is that you can’t debug directly in CoffeeScript. Browsers don’t run CoffeeScript natively so you get all errors in compiled JavaScript and have to translate them back to your source code. That means you can’t write a CoffeeScript application without a pretty deep understanding of the JavaScript it will produce.

The second major flaw of CoffeeScript is that it’s basically just JavaScript with a different syntax. CoffeeScript means writing less code, but it doesn’t fix the real problems of JavaScript as a language. It’s still the case that I love my CoffeeScript and hate everyone else’s.

Google Closure Tools

Around the same time that CoffeeScript came out, Google made another effort to improve JavaScript with the Google Closure Tools. Google tried to make GWT the next dominant Web technology, but it let Closure slip quietly out the door.

Closure includes a templating mechanism and a widget library, but the most interesting parts are the Closure Compiler and the Closure Linter.

The Closure compiler (like the YUI Compressor) takes your JavaScript and squishes it down so it takes less time to download and runs faster in production. The general idea is that you develop in standard JavaScript and compile it for release.

The Closure compiler turns this:

function sayHello() {
   alert('Hello World!');
}

$(document).ready(function() {
   sayHello();
});

into this:

$(document).ea(function(){alert("Hello World!")});

The result’s tough to read, but it runs a lot faster.

The Closure compiler supports two major modes: simple and advanced. Simple mode takes any JavaScript and compresses it by removing comments and white space, substituting variable names and making other safe changes. Simple mode has a very low chance of breaking your JavaScript, and it can find some issues when it compiles.

Advanced mode provides much better compression, but there’s a pretty good chance it will break your code unless you plan ahead. Advanced requires extra information to tell the compiler what not to remove. The very dynamic nature of JavaScript makes it tough for the compiler to follow every path in your code tree without some help.

The Closure tools also introduce JSDoc tags, which tell the compiler more about how your code works. In regular JavaScript you might define an object with three states for your application:

myProject.threeStates = {
    TRUE: 1,
    FALSE: -1,
    MAYBE: 0
};

You know that this is an enumerated type which constrains a value to one of these three options, but the compiler doesn’t know. Neither does that other developer on your team who added a fourth value dynamically. JSDoc lets you specify how this code works:

/**
 * Enum for my three states.
 * @enum {number}
 */
myProject.threeStates = {
    TRUE: 1,
    FALSE: -1,
    MAYBE: 0
};

By adding this comment you’re making it clear that this is an enumeration, that it only contains numbers and that you’re defining it as a strong type which you can use elsewhere. Combine this feature with the Closure linter that forces you to write comments like this and you’re basically redefining JavaScript. It still looks like JavaScript, but turned into a strongly-typed language.

That’s easy to see with the @type annotation:

/**
 * The name of the user
 * @type {string}
 */
var name = 'Zack';

JSDoc supports other annotations that control everything from what a function returns to who can call it. Add a module loader, and the Closure library addresses a lot of the shortcomings of JavaScript, by turning it into Java.

Closure code looks like Java with clunkier syntax. It’s strongly typed, uses a similar packaging mechanism and has a powerful compiler. That’s a good and bad thing in all the ways that Java is good and bad.

Google isn’t putting much marketing behind the Closure tools, but they’re putting a lot of engineering there. All of the major Google products use Closure. Google+ was built on Closure from the ground up.

The Closure community is growing, but there still aren’t many people outside of Google who know it well. Closure also suffers from the need to maintain backward compatibility with JavaScript. The syntax looks clunky and only more advanced JavaScript and object-oriented programmers can write it.

Some people thought the Web needed a brand-new language. So Google continued its frenemy relationship with JavaScript by creating Dart.

Dart

Dart totally replaces JavaScript with a language that’s strongly-typed, uses interfaces and looks a lot like a simplified Java.

library hi;

import 'dart:html';

main() {
  query('#status').text = 'Hi, Dart';
}

This simple “Hello World!” example shows packages, imports and methods similar to Java syntax.

Dart can compile into JavaScript, but running it natively in the browser gets you better performance and debugging. Google controls the Chrome browser and may add native support for Dart there. They already have a special version running on Windows. But it isn’t all up to Google.

Chrome depends on WebKit, which also powers Safari from Apple. Webkit is an open source project made up of about one third Google people, one third Apple people and one third other people. The Chrome team would like to change Webkit to support Dart; that would make their lives easier, and also make Safari support Dart. If that happened they could claim two major browsers support it, and pressure the others to start. The Safari team doesn’t want the Web to run on a new language owned by Google, so they’re adamant about not including Dart.

It looks like none of the other browsers will support Dart either. That leaves you compiling Dart into JavaScript and losing some of the nicer features like integrated debuggers.

Dart has many technical merits; it’s eclipsed by larger political problems.

Some very smart Googlers work on Dart and it has some nice features, but it’s still an invention of Google and isn’t standard. It wasn’t developed by a community and there are good reasons for other vendors to distrust it.

The only thing certain about Dart is that its future is unknown. A preview (version 0.1) was recently released but isn’t really usable outside of Google. Dart is a language to keep an eye on, but not a real option yet.

Opa

Opa is the new kid on the block with a 1.0 release last August. It’s a strongly-typed language with a growing community. You write Opa and compile into other languages like JavaScript, but it isn’t just client-side. Opa mixes client-side and server-side programming into a single file.

Opa supports client, server and database development with a single language. Using the same code base, it compiles into JavaScript, native executables and SQL code. They recently added support for non-relational databases like MongoDB as well.

Unlike Dart, Opa draws heavily on functional programming languages like Erlang. That makes it appeal to nerds, but the entry bar is pretty high. Opa lacks the simple syntax of CoffeeScript, and you can’t really teach yourself Opa without a strong background in other programming languages.

Though the bar is high, Opa rewards your learning investment by giving you a single environment where you don’t have to switch languages between client and server. It hasn’t grown much beyond samples and small websites, but it’s gaining ground.

What Should I Do?

The JavaScript problem is everyone’s problem; there are no good answers. It’s possible to write good JavaScript that scales to large projects, but that takes constant attention and the right culture.

There are a few other options for generating JavaScript (for example, Clojure compiles into JavaScript), but they’re still small projects without much real-world use.

Google writes most of their client-side code with the Closure tools and they’re starting to adopt more Dart. Other large websites like Twitter use JavaScript combined with other technologies like Ruby On Rails. Big open source projects like WordPress mostly stick with straight JavaScript and jQuery. Facebook uses a combination of all of them. Microsoft combines jQuery with .Net and some other server-side technologies which interact with JavaScript. They’ve also released a new static-typed JavaScript variant called TypeScript.

That just scratches the surface. The CoffeeScript project maintains a comprehensive list of languages that compile into JavaScript.

If your project is small, then just write JavaScript. jQuery is very well done; so are many other JavaScript libraries. Keep your project small and the problems stay small.

But the line between small and large is blurry. Small projects get bigger with time, and you can get into big trouble writing large JavaScript applications without a lot of process to keep you out of the bad parts. The other options are either has-beens or aren’t-yets.

A big part of this problem is the difficulty of finding a single language that keeps everyone happy. Small websites want something simple that makes it easy to get started and produce an app quickly. Large projects want the structure to keep the code base maintainable for years. The two goals are at odds and no language has ever satisfied both parties. That’s why Visual Basic and C++ are both so popular.

There’s also no reason to choose just one. GWT combines well with regular JavaScript, and you can use the Closure Compiler simple optimizations with any JavaScript project.

JavaScript will never be the best language for all applications, but browsers won’t support another one anytime soon. The key to using JavaScript well is to understand its limitations and know when not to use it. JavaScript is easy for small projects; you need planning, care and help from other libraries to work on larger ones.

Image on front page created by Ruiwen Chua.

(cp)


© Zack Grossbart for Smashing Magazine, 2012.


Twelve Commandments Of Software Localization


  

You’ve presented the new website and everyone loves it. The design is crisp, the code is bug-free, and you’re ready to release. Then someone asks, “Does it work in Japanese?â€�

You break out in a cold sweat: you have no idea. The website works in English, and you figured other languages would come later. Now you have to rework the whole app to support other languages. Your release date slips, and you spend the next two months fixing bugs, only to find that you’ve missed half of them.

Localization makes your application ready to work in any language — and it’s much easier if you do it from the beginning. Just follow these 12 simple rules and you’ll be ready to run anywhere in the world.

1. “Resource� All Of Your Strings

The first step of localization is to get user-visible strings out of your code and into resource files. Those strings include titles, product names, error messages, strings in images and any other text the user might see.

Most resource files work by giving each string a name and allowing you to specify different translation values for that string. Many languages use properties files like this:

name = Username

Or they use .pot files like this:

msgid "Username"
msgstr "Nom d'utilisateur"

Or they use XLIFF files like this:

<trans-unit id="1">
 <source xml:lang="en">Username</source>
 <target xml:lang="fr">Nom d'utilisateur</target>
</trans-unit>

The resource files are then loaded by a library that uses a combination of the language and country, known as the locale, to identify the right string.

Once you’ve placed your strings in external resource files, you can send the files to translators and get back translated files for each locale that your application supports.

2. Never Concatenate Strings

Appending one string to another almost always results in a localization bug. It’s easy to see this with modifiers such as color.

Suppose your stationery store has items such as pencils, pens and sheets of paper. Shoppers will choose what they want and then select a color. In the shopping cart you would show them items such as a red pencil or a blue pen with a function like this:

function getDescription() {
    var color = getColor();
    var item = getItem();

    return color + " " + item;
}

This code works well in English, in which the color comes first, but it breaks in French, in which “red pencilâ€� translates as “crayon rougeâ€� and “blue penâ€� is “stylo – encre bleue.â€� French speakers (but not only them) put modifiers after the words they modify. The getDescription function would never be able to support languages like this with simple string concatenation.

The solution is to specify parametrized strings that change the order of the item and color for each language. Define a resourced string that looks like this:

itemDescription = {0} {1}

It might not look like much, but this string makes the translation possible. We can use it in a new getDescription function, like this:

function getDescription() {
    var color = getColor();
    var item = getItem();

    return getLocalizedString('itemDescription', color, item);
}

Now, your translators can easily switch the order, like this:

itemDescription = {1} {0}

The getLocalizedString function here takes the name of a resource string (itemDescription) and some additional parameters (color and item) to substitute for placeholders in the resource string. Most programming languages provide a function similar to getLocalizedString. (The one notable exception is JavaScript, but we’ll talk more about that later.)

This method also works for strings with text in them, like:

invalidUser = The username {0} is already taken. Please choose another one.

3. Put All Of Your Punctuation In The Resourced String

Tacking on punctuation later is often tempting, so that you can reuse the same string, say, in a label where it needs a colon and in a tooltip where it doesn’t. But this is another example of bad string concatenation.

Here, we’re adding a simple log-in form using PHP in a WordPress environment:

<form>
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="text" name="password"></p>
</form>

We want the form to work in other languages, so let’s add the strings for localization. WordPress makes this easy with the __ function (i.e. underscore underscore):

<form>
<p><?php echo(__('Username', 'my-plugin') ?>: <input type="text" name="username"></p>
<p><?php echo(__('Password', 'my-plugin') ?>: <input type="text" name="password"></p>
</form>

Spot the bug? This is another case of string concatenation. The colon after the labels isn’t localized. This will look wrong in languages such as French and Russian, which always put spaces around colons. Punctuation is part of the string and belongs in the resource file.

<form>
<p><?php echo(__('Username:', 'my-plugin') ?> <input type="text" name="username"></p>
<p><?php echo(__('Password:', 'my-plugin') ?> <input type="text" name="password"></p>
</form>

Now the form can use Username: in English and Nom d'utilisateur : in French.

4. “Firstâ€� Names Sometimes Aren’t

My name is Zack Grossbart. Zack is my given (or first) name, and Grossbart is my last (or family) name. Everyone in my family is named Grossbart, but I’m the only Zack.

In English-speaking countries, the first name is the given name and the last name is the family name. Most Asian countries go the other way, and some cultures have only one name.

The cellist Yo-Yo Ma is a member of the Ma family. In Chinese, he writes his family name first: Ma Yo-Yo (馬��).

This gets tricky because many people change their names when moving from Asian countries to English-speaking ones. They often switch the order to fit local customs, so you can’t make any assumptions.

You must provide a way to customize the presentation of names; you can’t assume that the first name always comes first or that the last name always comes last.

WordPress handles this pretty well by asking you how you want your name to show up:

Name formatting in WordPress

It would be even better if WordPress supported a middle name and a way to specify the format per locale so that you could make your name one way in English and another in Chinese, but nothing’s perfect.

5. Never Hard-Code Date, Time Or Currency Formats

The whole world is inconsistent about date and time formats. Some people put the month first (6/21/2012), others the day first (21/6/2012). Some use 24-hour (14:00) time, and some use 12 (2:00 PM). Taiwan uses specially translated strings instead of AM and PM, and those come first (上� 2:00).

Your best bet is to store all dates and times in a standard format such as ISO time or epoch time, and to use a library like Date.js or Moment.js to format them for the given locale. These libraries can also handle converting the time to the current zone, so you can store all dates and times in a common format on the server (such as UTC) and convert them to the right time zone in the browser.

Dates and times are also tricky when displaying calendars and date pickers. Estonia starts the week on Saturday, the US starts on Sunday, the UK on Monday and the Maldives on Friday. The jQuery UI date picker includes over 50 localized files to support different calendar formats around the world.

The same is true of currencies and other number formats. Some countries use commas to separate numbers, and others use periods. Always use a library with localized files for each of the locales that you need to support.

StackOverflow covers this topic well when discussing daylight savings time and time zone best practices.

6. Use UTF-8 Almost All Of The Time

The history of computer character encodings is a long one, but the most important thing to remember is that UTF-8 is the right choice 99% of the time. The only time not to use UTF-8 is when you’re working primarily with Asian languages and absolutely need the efficiency of UTF-16.

This comes up a lot with Web applications. If the browser and the server don’t use the same character encoding, then the characters will get corrupted and your application will fill up with little squares and question marks.

Many programming languages store files using the system’s default encoding, but it won’t matter that your server is English when all of your users are browsing in Chinese. UTF-8 fixes that by standardizing the encodings across the browser and the server.

Invoke UTF-8 at the top of all of your HTML pages:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

And specify UTF-8 in the HTTP Content-Type header, like this:

Content-Type: text/html; charset=utf-8

The JSON specification requires that all JSON documents use Unicode with a default of UTF-8, so make sure to use UTF-8 whenever you’re reading or writing data.

7. Give Strings Room To Grow And Shrink

Strings change size in translation.

Repeat password example

“Repeat passwordâ€� is over 50% wider in German than in English; if there isn’t enough space, then your strings will overlap other controls. WordPress solves this problem by leaving extra space after each label for the string to grow.

Label spacing in the WordPress admin

This works well for languages whose strings are roughly of the same length, but for languages with long words, such as German and Finnish, the controls will overlap if you don’t leave enough space. You could add more space, but that would put the labels and controls pretty far apart from each other in compact languages such as Chinese, thus making them hard to use.

Label spacing in the WordPress admin in Chinese

Many designers of forms give their labels room to grow and shrink by aligning them to the right or by placing them above the controls.

Label above controls in the WordPress admin

Putting labels above the controls works well for a short form, but it makes a form with a lot of fields very tall.

There’s no perfect answer for how to make your application work in all languages; many form designers mix and match these approaches. Short labels like “User nameâ€� and “Roleâ€� won’t change much in translation and need just a little extra space. Longer paragraphs will change substantially and need room to grow wider, taller or sometimes both.

Label next to and above controls in the WordPress admin

Here, WordPress gives a little extra space for the “Biographical Info� label, but it puts the longer description below the field so that it can grow in translation.

8. Always Use A Full Locale

The full locale includes the language and country code, and it supports alternate spellings, date formats and other differences between two countries with a shared language.

Always use a full locale instead of just a language when translating, so that you know whether you’re doing someone a favor or a favour, and that they know whether to take the elevator or the lift, and that they know whether £100.00 is expensive.

9. Never Trust The Browser To Know The Right Locale

Localization is much more difficult with browsers and JavaScript because they give a different locale depending on who’s asking.

JavaScript has a property to tell you the current language, named navigator.userLanguage. All browsers support it, but it’s generally useless.

If I install Firefox in English, then my navigator.userLanguage value would say English. I can then go into my preferences and change my preferred languages. Firefox lets me select multiple languages, so I could specify my order of preference as English from the US, then any other English, then Japanese.

Language preferences in Firefox

Specifying a set of locales makes it possible for servers to find the best match between the languages that I know they support. Firefox takes these locales and sends them to the server in an HTTP header, like this:

Accept   en-us,en;q=0.7,ja;q=0.3

Firefox even uses the quality factor (that q= part) to indicate how much I prefer one locale over another.

This means that the server might return content in English or Japanese or another language if it doesn’t support either. However, even after I’ve set my preferred language in Firefox, the value of my navigator.userLanguage property will still be English and only English. The other browsers don’t do much better. This means that I might end up with the server thinking I want Japanese and with the JavaScript thinking I want English.

JavaScript has never solved this problem, and it has not one standard localization library, but dozens of different standards. The best solution is to embed a JavaScript property or some other field in your page that indicates the locale when the server processes each request. Then you can use that locale when formatting any strings, dates or numbers from JavaScript.

10. Plan For Languages That Read Left To Right And Right To Left

Most languages are written on screen from left to right, but Arabic, Hebrew and plenty of others go from right to left. HTML provides a property for the html element named dir that indicates whether the page is ltr (left to right) or rtl (right to left).

<html dir="rtl">

There’s also a direction property in CSS:

input {
    direction: rtl;
}

Setting the direction property will make the page work for the standard HTML tags, but it can’t switch a CSS element with float: left to float: right or change an absolutely positioned layout. To make more complex layouts work, you will need a new style sheet.

An easy way to determine the direction of the current language is to include a direction string in the resourced strings.

direction = rtl

Then you can use that string to load a different style sheet based on the current locale.

11. Never Sort In The Browser

JavaScript provides a sort function that arranges lists of strings alphabetically. It works by comparing each character in each string to determine whether a is greater than b or y is less than z. That’s why it makes 40 come before 5.

The browser knows that y comes before z by using a large mapping table for each character. However, the browser includes the mapping tables only in the current locale. This means that if you have a list of Japanese names, the browser wouldn’t be able to sort them properly in an English locale; it would just sort them by Unicode value, which isn’t correct.

This problem is easy to see in languages such as Polish and Vietnamese, which frequently use diacritical marks. The browser can tell that a comes before b, but it doesn’t know whether ằ comes before ã.

The only place to sort strings properly is on the server. Make sure that the server has all of the code mappings for the languages you support, and that you send lists to the browser presorted, and that you call the server whenever you want to change the sorting. Also, make sure that the server takes locale into account for sorting, including right-to-left locales.

12. Test Early And Often

Most teams don’t worry about localization until it’s too late. A big customer in Asia will complain that the website doesn’t work, and everyone will scramble to fix 100 little localization bugs that they had never thought of. Following the rules in this article will avoid many of those problems, but you will still need to test; and translations usually aren’t ready until the end of the project.

I used to translate my projects into Pig Latin, but that didn’t test Asian characters, and most browsers don’t support it. Now I create test translations with Xhosa (xh_ZA). All browsers support Xhosa, and Nelson Mandela speaks it natively, but I’ve never been asked to support it in a product.

I don’t speak Xhosa, so I create a new translation file and add xh to the beginning and end of every string. The xh makes it easy to see whether I’ve missed a string in the code. Throw in a few Japanese Kanji characters to test character encoding, and I have a messy string that tests for all of my translation issues.

Making the test translation file is easy. Just save a new properties file with xh_ZA in the file name and turn…

name = Username

… into:

name = xh�清�Username�清�xh

The resulting jumble will test that I’ve resourced every string, that I’m using the right locale, that my forms work with longer strings and that I’m using the right character set. Then I’ll just quickly scan the application for anything without the xh and fix the bugs before they become urgent issues.

Do the right thing for localization ahead of time, and you’ll save yourself a lot of trouble in the long run.

(al) (km)


© Zack Grossbart for Smashing Magazine, 2012.


JavaScript Profiling With The Chrome Developer Tools


  

Your website works. Now let’s make it work faster. Website performance is about two things: how fast the page loads, and how fast the code on it runs. Plenty of services will make your website load faster, from minimizers to CDNs, but making it run faster is up to you.

Little changes in your code can have gigantic performance impacts. A few lines here or there could mean the difference between a blazingly fast website and the dreaded “Unresponsive Script� dialog. This article shows you a few ways to find those lines of code with Chrome Developer Tools.

Establish A Baseline

We’ll look at a simple application called a color sorter, which presents a grid of rainbow colors that you can drag and drop to mix up. Each dot is a div tag with a little CSS to make it look like a circle.

The Color Sorter

Generating my rainbow colors was a little tricky, so I got a little help from “Making Annoying Rainbows in JavaScript.�

The page loads pretty fast, but it still takes a moment and blinks a little before it paints. Time to profile the page and make it faster.

Always start performance-improvement projects with a baseline understanding of how fast or slow your application already is. The baseline will let you know whether you’re making improvements and help you make tradeoffs. For this article, we’ll use Chrome Developer Tools.

The profiler is part of Chrome Developer Tools, which is always available in Chrome. Click the “Tools� menu under the little wrench to open it. Firebug has some profiling tools, too, but the WebKit browsers (Chrome and Safari) are best at profiling code and showing timelines. Chrome also offers an excellent tool for event tracing, called Speed Tracer.

To establish our baseline, we’ll start recording in the “Timeline� tab, load our page and then stop the recording. (To start recording once Chrome Developer Tools is open, click the “Timeline� tab, and then the small black circle icon for “Record� at the very bottom of the window.) Chrome is smart about not starting to record until the page starts to load. I run it three times and take the average, in case my computer runs slowly during the first test.

Performance baseline 1

My average baseline — i.e. the time between the first request for the page and the final painting of the page in the browser — is 1.25 seconds. That’s not bad, but it’s not great for such a small page.

I want to make my code run faster, but I’m not sure what’s making it slow. The profiler helps me find out.

Create A Profile

The timeline tells us how long our code took to run, but that doesn’t help us know what’s going on while it’s running. We could make changes and run the timeline again and again, but that’s just shooting in the dark. The “Profiles� tab gives us a better way to see what’s going on.

Profilers show us which functions take the most time. Let’s make our baseline profile by switching to the “Profiles� tab in Chrome Developer Tools, where three types of profiling are offered:

  1. JavaScript CPU profile
    Shows how much CPU time our JavaScript is taking.
  2. CSS selector profile
    Shows how much CPU time is spent processing CSS selectors.
  3. Heap snapshot
    Shows how memory is being used by our JavaScript objects.

We want to make our JavaScript run faster, so we’ll use the CPU profiling. We start the profile, refresh the page and then stop the profiler.

The first profile

The first thing that’s clear from the profile is that a lot is going on. The color sorter uses jQuery and jQuery UI, which are doing a lot of stuff like managing plugins and parsing regular expressions. I can also see that two of my functions are at the top of the list: decimalToHex and makeColorSorter. These two functions take a total of 13.2% of my CPU time, so they’re a good place to start making improvements.

We can click the arrow next to the function calls to open the complete function-call stack. Expanding them, I see that decimalToHex is called from makeColorSorter, and makeColorSorter is called from $(document).ready.

Here’s the code:

$(document).ready(function() {
    makeColorSorter(.05, .05, .05, 0, 2, 4, 128, 127, 121);
    makeSortable();
});

Knowing where they’re called from also makes clear that making the colors sortable isn’t my biggest performance problem. Performance issues resulting from the addition of a lot of sortables is common, but my code is taking more time to add DOM elements than to make them sortable.

I want to start making those functions faster, but first I want to isolate my changes. A lot happens when the page loads, and I want to get all of that out of my profile.

Isolate The Problem

Instead of loading the color sorter when the document is ready, I’ll make a second version that waits until I press a button to load the color sorter. This isolates it from the document loading and helps me profile just the code. I can change it back once I’m done tuning performance.

Let’s call the new function testColorSorter and bind it to a clickable button:

function testColorSorter() {
    makeColorSorter(.05, .05, .05, 0, 2, 4, 128, 127, 121);
    makeSortable();
}
<button id="clickMe" onclick="testColorSorter();">Click me</button>

Changing the application before we profile could alter the performance of the application unexpectedly. This change looks pretty safe, but I still want to run the profiler again to see whether I’ve accidentally changed anything else. I’ll create this new profile by starting the profiler, pressing the button in the app and then stopping the profile.

The second profile

The first thing to notice is that the decimalToHex function is now taking up 4.23% of the time to load; it’s what the code spends the most time on. Let’s create a new baseline to see how much the code improves in this scenario.

The second baseline

A few events occur before I press the button, but I only care about how long it took between the times the mouse was clicked and the browser painted the color sorter. The mouse button was clicked at 390 milliseconds, and the paint event happened at 726 milliseconds; 726 minus 390 equals my baseline of 336 milliseconds. Just as with the first baseline, I ran it three times and took the average time.

At this point, I know where to look and how long the code takes to run. Now we’re ready to start fixing the problem.

Make It Faster

The profiler only tells us which function is causing the problem, so we need to look into it and understand what it does.

function decimalToHex(d) {
    var hex = Number(d).toString(16);
    hex = "00".substr(0, 2 - hex.length) + hex; 

    console.log('converting ' + d + ' to ' + hex);
    return hex;
}

Each dot in the color sorter takes a background color value in hex format, such as #86F01B or #2456FE. These values represent the red, green and blue values of the color. For example, Blue dot has a background color of #2456FE, which means a red value of 36, a green value of 86 and a blue value of 254. Each value must be between 0 and 255.

The decimalToHex function converts these RGB colors to hex colors that we can use on the page.

The function is pretty simple, but I’ve left a console.log message in there, which is just some debugging code we can remove.

The decimalToHex function also adds padding to the beginning of the number. This is important because some base-10 numbers result in a single hex digit; 12 in base 10 is C in hex, but CSS requires two digits. We can make the conversion faster by making it a little less generic. I know that the numbers to be padded each have one digit, so we can rewrite the function like this:

function decimalToHex(d) {
    var hex = Number(d).toString(16);
    return hex.length === 1 ? '0' + hex : hex; }

Version three of the color sorter changes the string only when it needs the padding and doesn’t have to call substr. With this new function, our runtime is 137 milliseconds. By profiling the code again, I can see that the decimalToHex function now takes only 0.04% of the total time — putting it way down the list.

The third profile

We can also see that the function using the most CPU is e.extend.merge from jQuery. I’m not sure what that function does because the code is minimized. I could add the development version of jQuery, but I can see that the function is getting called from makeColorSorter, so let’s make that one faster next.

Minimize Content Changes

The rainbow colors in the color sorter are generated from a sine wave. The code looks at a center point in the color spectrum and creates a wave through that center point over a specified width. This changes the colors into a rainbow pattern. We can also change the colors in the rainbow by changing the frequency of the red, green and blue.

function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {

    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);

       console.log('red: ' + decimalToHex(red));
       console.log('green: ' + decimalToHex(green));
       console.log('blue: ' + decimalToHex(blue));

       var div = $('<div class="colorBlock"></div>');
       div.css('background-color', '#' + decimalToHex(red) + decimalToHex(green) + decimalToHex(blue));
       $('#colors').append(div);
       
    }
}

We could take out more console.log functions. The calls are especially bad because each is also calling the decimalToHex function, which means that decimalToHex is effectively being called twice as often as it should.

This function changes the DOM a lot. Every time the loop runs, it adds a new div to the colors div tag. This makes me wonder whether that’s what the e.extend.merge function was doing. The profiler makes it easy to tell with a simple experiment.

Instead of adding a new div each time the loop runs, I want to add all of the div tags at once. Let’s create a variable to hold them, and then add them once at the end.

function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {

    var colors = "";
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);

       colors += '<div class="colorBlock" style="background-color: #' + 
           decimalToHex(red) + decimalToHex(green) + decimalToHex(blue) + '"></div>';
    }

    $('#colors').append(colors);
}

This small change in the code means that the DOM changes once, when it adds all of the div tags. Testing that with the timeline, we see that the runtime between the click and the paint events is now 31 milliseconds. This one DOM change has brought the time for version four down by about 87%. We can also run the profiler again and see that the e.extend.merge function now takes up such a small percentage of the time that it doesn’t show up on the list.

We could make the code one notch faster by removing the decimalToHex function entirely. CSS supports RGB colors, so we don’t need to convert them to hex. Now we can write our makeColorSorter function like this:

function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {

    var colors = "";
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);

       colors += '<div class="colorBlock" style="background-color: rgb(' + 
           red + ',' + green + ',' + blue + ')"></div>';
    }

    $('#colors').append(colors);
}

Version five runs in only 26 milliseconds and uses 18 lines of code for what used to take 28 lines.

JavaScript Profiling In Your Application

Real-world applications are much more complex than this color sorter, but profiling them follows the same basic steps:

  1. Establish a baseline so that you know where you’re starting from.
  2. Isolate the problem from any other code running in the application.
  3. Make it faster in a controlled environment, with frequent timelines and profiles.

There are a few other rules to follow when tuning performance:

  1. Start with the slowest parts first so that you get the most improvement for the time spent tuning.
  2. Control the environment. If you switch computers or make any other major changes, always run a new baseline.
  3. Repeat the analysis to prevent anomalies on your computer from skewing the results.

Everyone wants their website to run faster. You have to develop new features, but new features usually make a website run slower. So, investing time in tuning the performance does pay off.

Profiling and tuning cut the final color sorter’s runtime by over 92%. How much faster could your website be?

(al) (km)


© Zack Grossbart for Smashing Magazine, 2012.


Backpack Algorithms And Public-Key Cryptography Made Easy


  

E-commerce runs on secrets. Those secrets let you update your blog, shop at Amazon and share code on GitHub. Computer security is all about keeping your secrets known only to you and the people you choose to share them with.

We’ve been sharing secrets for centuries, but the Internet runs on a special kind of secret sharing called public-key cryptography. Most secret messages depend on a shared secret—a key or password that everyone agrees on ahead of time. Public-key cryptography shares secret messages without a shared secret key and makes technologies like SSL possible.

Cryptography is a scary word: it conjures thoughts of complex equations and floating-point arithmetic. Cryptography does have a lot of math, but it’s more about keeping and sharing secrets.

A Simple Secret

Telling my best friends a secret is easy: I find a private place and whisper it in their ears. As long as no one is listening in, I’m totally secure. But the Internet is full of eavesdroppers, so we need codes.

We’ve all been inventing codes since we were children. I created this simple number code (actually a cipher) when I was 5:

a=1, b=2, c=3, d=4, e=5…

It fooled my friends, but not my parents. Simple substitution ciphers are based on a lack of knowledge. If you know how they work, then you can decode every message. The experts call this “security through obscurity.� Letter and number substitutions don’t work on the Internet, because anyone can look them up on Wikipedia. For computer security, we need codes that are still secure even if the bad guys, or your parents, know how they work.

The most secure code is still easy to use: a “one-time pad.� One-time pads have been used for centuries, so they don’t even need computers. They played a big part in World War II, when each pad of paper with the key numbers was used only once.

Let’s say I wanted to send you this secret message:

I love secrets

First, I’d turn the message into numbers using my simple cipher from when I was 5. (I’ve heard rumors that other people had this idea first, but I don’t believe it.)

One-time pad step 1

Then I’d mash my keyboard to generate a random key string for my one-time pad.

One-time pad step 2

Now I can add the two strings together. If my number is greater than 26, I would just wrap it around to the beginning. So, i(9) + e(5) = n(14), and o(15) + t(20) = i(35 - 16 = 9). The result is an encrypted string:

One-time pad diagram

Decrypting the string to get the secret back is easy. We just subtract the one-time pad: n(14) - e(5) = i(9). Follow that pattern through the entire message, and you can securely share a secret. You don’t even need a computer: just work it out with a pen and paper.

This function is called a symmetric-key algorithm, or a shared-key algorithm, since it uses the same key to encrypt and decrypt the message. Modern systems can safely use the pad more than once, but the basic idea is the same.

The one-time pad is totally secure because the bad guys don’t know how we got the encoded letter. The n could be i + e, j + d or any other combination. We can use our shared secret (the one-time pad) once to share another secret.

But there’s a fatal flaw. We need to share the one-time pad ahead of time before we can start sharing secrets. That’s a chicken-and-egg problem because we can’t share the pad without worrying that someone will snoop. If the bad guys get the one-time pad, then they would be able to read everything.

One-time pads help me share secrets with my best friends, but I can’t use them with strangers such as Amazon or Facebook. I need a way to share something publicly that doesn’t compromise my one-time pad. I need a public key.

The Public-Key Backpack

Public-key encryption focuses on a single problem: how do I prove that I know something without saying what it is? An easy concept to help us understand this is a backpack full of weights.

Backpack algorithm

I want to prove that I know which weights are in my pack, but I don’t want to tell you what they are. Instead of showing you all of the weights separately, I’ll just tell you the total. Now you can weigh the pack and see if I’m right without ever opening it.

If the pack weighs 20 kilos, then you wouldn’t know if it has one 20-kilo weight, twenty 1-kilo weights or something in between. With a large number, you can be pretty confident that I know what’s in the pack if I know the total; you don’t have to see inside. The weight of the backpack is the public part, and the individual weights are the private part.

This basic backpack enables us to share a secret without really sharing it. If we each have a backpack, then we can both share secrets.

The backpack works well enough for smaller numbers, but it isn’t useful in the real world. Backpack algorithms were a mere curiosity for decades. Then RSA changed everything.

RSA

RSA was the first public-key encryption system that worked in the real world. Invented more than 30 years ago, it coincided with the introduction of the more powerful computers that were needed to run the big numbers. RSA is still the most popular public-key encryption system in the world.

The basic premise of RSA is that factoring large numbers is difficult. Let’s choose two prime numbers: 61 and 53. I’m using the numbers from Wikipedia’s article on “RSA� in case you want more details.

Multiply these two numbers and you get 3233:

61 × 53 = 3233

The security of RSA comes from the difficulty of getting back to 61 and 53 if you only know 3233. There’s no good way to get the factors of 3233 (i.e. the numbers that multiply to make the result) without just looking for all of them. To think of this another way, the weight of our backpack is 3233 kilos, and inside are 61 weights weighing 53 kilos each. If you make the resulting number large enough, then finding the numbers that produced it would be very difficult.

Public And Private Keys

Public-key encryption diagram
Unlike the one-time pad, RSA uses the public key to encrypt information and the private key to decrypt it. This works because of the special relationship between the public and private keys when they were generated, which allows you to encrypt with one and decrypt with the other.

You can share the public key with anyone and never reveal the private key. If you want to send me a secret message, just ask for my public key and use it to encrypt the message. You can then send it to anyone you want, and you’ll know that I’m the only one who can decrypt the message and read it.

I could send you a message in the same way. I would ask for your public key, encrypt the message using it and then send it to you to decrypt. The popular program Pretty Good Privacy (PGP) worked like that. We’re secure as long as we both keep our private keys private.

Exchanging keys is made even easier by special key servers that allow you to search for people and find their public keys.

Public-key encryption also works in reverse to provide digital signatures. Let’s say I want to write a message and prove that I wrote it. I just encrypt it with my private key and post it. Then anyone who wants to check can decrypt it with my public key. If the decryption works, then it means I have the private key and I wrote the message.

RSA is relatively simple: take two numbers (the private key), apply some math, and get a third number (the public key). You can write out all of the math in a few lines, and yet RSA changed the world. Business doesn’t work on the Internet without public-key encryption.

RSA And HTTPS

We use public-key encryption every day with HTTPS. When you access Facebook, Twitter or Amazon with HTTPS, you’re using a simple encryption mechanism like the one-time pad, but you’re creating the pad with public-key encryption. Without HTTPS, anyone else at Starbucks could read your credit-card number, Facebook password or private email while sipping a latte.

Amazon has a certificate from a company named VeriSign. The certificate certifies that Amazon is Amazon, and it contains its public key. Your browser creates a special key just for that session and encrypts it using Amazon’s public key. Then it sends it over the Internet, knowing that only Amazon can decrypt the session key. Once you’ve exchanged that secret key, you can use it as the one-time pad to protect your password and credit-card number.

SSL key exchange diagram

You could keep using public-key encryption for the whole session, but because of all the math, it’s much slower than the one-time pad.

RSA And GitHub

Another place many of us use RSA is GitHub. Every time you push a change to GitHub or pull from a master branch, GitHub has to make sure you have permission to make the change. It gets its security through a secure command shell using RSA.

Remember when you set up your GitHub account and followed some commands to generate keys?

GitHub key generation

You used the SSH-Keygen tool to generate a new RSA private/public key pair. Then you went to your GitHub account page and entered your public key.

Now, when GitHub needs to authenticate you, it asks your computer to sign something with your private key and return the signed data. With your public key, GitHub can confirm that the signature is authentic and could only have been produced by someone who has the corresponding private key—even though GitHub itself doesn’t have that private key.

That’s better than a simple password because nobody can snoop it. And if GitHub ever gets hacked, your private key won’t be in danger because only you have it.

Sharing Passwords

When WordPress.org was “hacked�, it wasn’t really hacked. WordPress plugin developers, like everyone else, have accounts on other websites. They also reuse their passwords. When hackers cracked those other websites, they used the stolen passwords to log into WordPress.org and make malicious changes to plugins.

Most people use the same user name and password on multiple websites. That makes your website only as secure as everyone else’s. Public-key encryption changes that. Because you never have to share your private key, it doesn’t matter if other websites get hacked. If an attacker breaks into GitHub and gets your public key, they can’t use it to impersonate you or log in as you on other websites. Only someone with your private key can do that, which is why your private key remains safe on your computer. Using public-key cryptography makes GitHub much more secure.

GitHub Gets Hacked

GitHub was hacked recently, but not because the encryption failed. Real-world security breaches are caused by problems in implementation, not in math.

In this case, the hacker was able to exploit a hole and add his public key to the Ruby on Rails repository. Once the key was added, GitHub used it to verify the hacker’s identity and granted him access. We’re lucky this hacker was friendly and told GitHub about the issue.

Once the problem was fixed, you could keep using your private key because GitHub never had it to lose; it stayed on your machine. Public keys saved GitHub from serious problems.

The weakest link in GitHub’s security was in the mechanism that allowed clever users to add public keys to other projects without being authorized. The math was perfect, but the implementation wasn’t.

Public Keys In The Wild

Knowing the fundamentals is essential (you might say the key) to writing secure applications. The math is complex, but the basics are simple:

  • There are two main types of encryption: shared-key encryption, such as a one-time pad, and public-key encryption, which uses public and private keys.
  • Shared-key encryption is faster, but sharing the keys is difficult.
  • RSA is the most popular public-key encryption algorithm, but a few others are in general use, as well as some cool experimental systems.
  • Public-key cryptography works best in combination with other technologies.
  • Don’t ever share your private key with anyone.

When it comes time to implement public-key cryptography in your application, don’t. RSA and other algorithms are already implemented in all major languages. These libraries include extra security features such as padding and salts, and they have a lot of testing behind them.

Most security flaws come from poor implementations and misunderstanding about the libraries. You don’t have to write your own cryptography libraries, but you do have to know the fundamentals so that you can use the ones that are out there.

Illustrations in this article were provided by Robb Perry.

(al) (km)


© Zack Grossbart for Smashing Magazine, 2012.


Writing Unit Tests For WordPress Plugins


  

When my WordPress plugin had only three users, it didn’t matter much if I broke it. By the time I reached 100,000 downloads, every new update made my palms sweat.

My first goal for the WordPress Editorial Calendar was to make it do anything useful. I was new to JavaScript and PHP and didn’t really know what I could pull off. In a few days I had a proof of concept. In a few more I had a working version and was asking friends to install it. The calendar worked… sort of.

I spent three times as much time fixing bugs as I did coding. Once the plugin worked, I wrote unit tests to make sure it kept working.

The unit tests for my calendar use QUnit, but they really use just three functions: test, expect and ok. This article shows you how to integrate unit tests into your WordPress plugin, where to write unit tests and how they can help you.

QUnit Basics

Unit tests follow a basic pattern: do something, then check the results. (“Is this variable 4 when it should be 5?� “Does this line of my table show up where it’s supposed to?�)

function myTest() {
    test('My test run', function() {
        expect(2);
        ok(5 === 5, 'This test will always pass');
        ok(5 === 6, 'This test will always fail');
    });
}

This structure forces you to think of your code in simple units that return true or false. The test function starts a test run with two arguments: the title for this test run, and the function containing the tests. The expect function tells QUnit how many tests are in the run. If we call too few or too many, it causes an error.

The ok function performs the test of the expression. It takes two arguments: a boolean indicating whether the test was successful, and a message.

Test runs are added to a special list section, which shows the total number of tests, whether each test passed or failed, and how long the tests took.

A Real Unit Test

WordPress plugins complicate testing by using a combination of PHP and JavaScript. Even passing a simple value from PHP to JavaScript gets tricky.

The function below finds a WordPress preference with the get_option function and creates a JavaScript variable with the resulting value.

function getOption($myOption, $myVariable) {
    if (get_option($myOption) != "") {
        ?><script type="text/javascript">
            <?php echo($myVariable); ?> = <?php echo(get_option($myOption)); ?>;
        <php
    }
}

Now we’ll call it to get the name of the blog and set it to a variable named myBlogName.

getOption("blogname", "myBlogName");

Little helper functions like these glue your plugin together, but they always worry me. Did I access the JavaScript variable with the right name or did I mistype it? Did I use the same name twice? A simple unit test makes all of these worries go away.

function wpPrefTest() {
    test('Get access to WordPress preferences', function() {
        expect(1);
        ok(myBlogName, 'The variable (myBlogName) should be available.');
    });
}

This unit test checks whether the variable myBlogName exists. We could also look for a specific value or compare it to something else from the application.

Once you have this unit test, you’ll never need to worry about getting the blog’s name. It will always be there, and you’ll find out fast if you ever break it.

Integrating QUnit With WordPress

Testing in special development environments isn’t accurate. I wanted to add QUnit directly to my calendar, but I didn’t want to make the page’s size larger. The solution is a URL parameter and a little PHP to include QUnit only when I need it:

wp_enqueue_script( "qunit", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/qunit.js"), array( 'jquery' ) );
wp_enqueue_script( "edcal-test", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/edcal_test.js"), array( 'jquery' ) );

This tells WordPress to include the QUnit JavaScript and my unit tests from edcal_test.js. I could have just embedded the script’s reference directly on my page, but I might have run into trouble if other plugins on the same page use QUnit.

You can see the full source code here.

The next step was to make sure that these scripts load only when I need them. To do this, I wrapped the code in a check for a URL parameter:

if ($_GET['qunit']) {
    wp_enqueue_script( "qunit", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/qunit.js"), array( 'jquery' ) );
    wp_enqueue_script( "edcal-test", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/edcal_test.js"), array( 'jquery' ) );
}

This loads the scripts only if I’m running unit tests, and everything else in the plugin stays the same. You can run the unit tests at any time just by adding &qunit=true to the end of the URL. That’s a good thing because my unit tests actually change what’s going on in the blog.

You can run the Editorial Calendar’s unit tests in your browser right now. Scroll down to see the unit test results at the bottom of the page.

The PHP makes sure that my scripts get to the browser. The last step is to call them from my JavaScript. Once again, I want to call them only if we’re in unit test mode. So, I add a small function to get the parameters from the URL:

getUrlVars: function() {
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for (var i = 0; i < hashes.length; i++) {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}

And then I call my unit tests if the QUnit parameter is there:

jQuery(document).ready(function() {
    if (edcal.getUrlVars().qunit) {
        edcal_test.runTests();
    }
});

This ensures that we call the unit tests only if they’re available.

The last step is to set up a space for the unit test’s output. QUnit writes its test results into specially designated tags on your HTML page. You could embed these tags directly in your HTML output, but because they need to be there only when QUnit is active, I create the HTML in JavaScript instead.

jQuery('head').append('<link>');
css = jQuery('head').children(':last');
css.attr({
    rel: 'stylesheet',
    type: 'text/css',
    href: '../wp-content/plugins/edcal/lib/qunit.css'
});

jQuery('#wpbody-content .wrap').append('<div id="edcal-qunit"></div>');

jQuery('#edcal-qunit').append(
    '<h1 id="qunit-header">WordPress Editorial Calendar Unit Tests</h1>' +
    '<h2 id="qunit-banner"></h2>' +
    '<div id="qunit-testrunner-toolbar"></div>' +
    '<h2 id="qunit-userAgent"></h2>' +
    '<ol id="qunit-tests"></ol>' +
    '<div id="qunit-fixture">test markup</div>');

QUnit needs a list tag, a couple of divs and a style sheet.

Now we’re ready to write our first test.

The First Unit Test

The first calendar unit tests scroll the calendar up and down and make sure we see the correct number of days.

moveTests: function() {
    var curSunday = edcal.nextStartOfWeek(Date.today()).add(-1).weeks();
    edcal.moveTo(Date.today());

    test('Move to today and check visible dates', function() {
        expect(2);
        ok(edcal_test.getFirstDate().equals(curSunday.clone()),
           'firstDate should match ' + curSunday);
        ok(edcal_test.getLastDate().equals(
           curSunday.clone().add(edcal.weeksPref).weeks().add(-1).days()),
           'lastDate should match ' + curSunday);
    });
}

Our first test moves the calendar to today and checks to see if the first and last days are what we expect. We set up a variable, move the calendar and start the test by calling the test function.

In this case we want to make sure the dates are correct, so we compare the date from the calendar to the one we expect and then pass the result to the ok function. The test succeeds if they match and fails if they don’t.

This test may seem simple, but a lot is going on under the hood. We’re testing date handling, drawing and the fundamental arithmetic of the calendar.

Unit tests can do anything. The WordPress Editorial Calendar unit tests automate the plugin like a robot. They cover everything a user could do with the calendar.

What To Unit Test

I write a lot more unit tests for JavaScript than I do for compiled languages. In Java and C++, the compiler catches many of my mistakes, whereas JavaScript lets you pass a string when you meant to pass a number and lets you call a function with two arguments when it needs three.

Here’s the basic list of areas I test in JavaScript applications:

  • Tests that make sure the program does what it is meant to do
    These tests ensure the basic functionality keeps working; they do not test interactions. (The calendar lets you drag and drop posts, but writing unit tests for dragging and dropping wouldn’t make sense; instead, we would focus on what happens after the drop event.)
  • Tests that make sure the program doesn’t do what it’s not meant to do
    These tests ensure the program fails properly when it gets garbage.
  • A unit test for every major bug I’ve found
    These tests ensure that none of these bugs creep back in.

APIs and other clear boundaries in the code lend themselves well to unit tests, as do utility functions that you call from many places in the application. With the calendar, this means testing calendar movements and testing how we create and modify posts in WordPress, like this:

  1. Move the calendar and check the dates;
  2. Create a post and make sure it was created properly;
  3. Edit the post we just created and make sure it saves properly;
  4. Move the post and make sure it shows up at the correct date;
  5. Move the post from two places at the same time and make sure we get the proper warning message;
  6. Delete the post from the server and make sure it isn’t there anymore.

The penultimate test covers an error condition in which two people move the same post at the same time. Unit tests work well for this kind of error, because the error type is difficult to test and manual testing is less likely to uncover problems.

For your own application, you should have at least one unit test for every data-changing operation that users can perform. I like to add them for all of the places where a user can get data, too. It might sound like a lot of work, but you can cut down on it by writing single tests that cover multiple areas.

Asynchronous Unit Tests

Many of these combination unit tests make AJAX calls. QUnit provides a special function for handling AJAX called asyncTest. This function works just like test, but it pauses the test run at the end of the function. The QUnit framework waits until your AJAX call completes and you call the start function before restarting the test run.

The asyncTest function handles all of the tests that edit posts from the calendar, including deleting the post at the end:

asyncTest('Delete the post created for testing', function() {
    expect(1);

    edcal.deletePost(edcal_test.post.id, function(res)
    {
        equals(jQuery('#post-' + res.post.id).length, 0,
               'The post should now be deleted from the calendar.');
        start();
    });
});

When you restart the test framework you can call more tests. Calling the next test function at the end of the previous one chains them together, and it supports calling all of your tests with just a call to the first function.

These tests, which call AJAX, ensure that the integration between the JavaScript on the client side and the PHP on the back end works properly.

That’s Not a Unit Test

When I first learned to write unit tests in C++ the rule was this: a single test should only call code in a single module or CPP file. That is, a unit test should test one unit of code.

Changing posts from unit tests violates that rule. Instead of just testing JavaScript, I’m really testing JavaScript, PHP, WordPress itself and MySQL all at once. That makes it an automated integration test.

Integration tests aren’t traditional unit tests, but they work well for WordPress plugins. When I create a post, I’ll know that the AJAX code in my plugin works as well as the JavaScript code. Covering a larger portion of the application with fewer tests makes it easier to focus on what I should be testing.

What Not To Unit Test

You could write unit tests forever, but some are more useful than others. Here are some guidelines.

  • Don’t unit test the UI.
    The test has to run by itself. It can’t wait for you to click a button or look at something to make sure it appears correctly.
  • Don’t unit test performance.
    Tests take a variable amount of time on different machines and browsers. Don’t write unit tests that depend on a function being returned in a set amount of time.
  • Don’t unit test code from other projects.
    Adding unit tests for WordPress or a jQuery plugin you depend on might be tempting, but it rarely pays off. If you want to contribute unit tests to WordPress.org that’s great, but your unit tests should check that your plugin works.

The Editorial Calendar has 26 unit tests, at about 3,500 lines of code. That may not sound like much, but they’ve saved many of my releases.

Unit Tests Saved My Butt

I didn’t add unit tests until the thirteenth release of my plugin. By then, the calendar had a couple of hundred users and was growing fast. My plugin was working, and I was getting close to release 1.0.

Instead of adding new features, I took in a new framework, added special code to load it, wrote 381 lines of unit tests and integrated all of this into the plugin. It seems like a lot of work, but it saved my butt.

Right before a release, I wrote some harmless-looking PHP code like the following to get the JSON data that represented a set of posts to show up in the calendar:

function edcal_postJSON($post) {
    setup_postdata($post);
    ?>
    {
        "date" : "<?php the_time('d') ?><?php the_time('m') ?><?php the_time('Y') ?>",
        "title" : <?php echo($this->edcal_json_encode(get_the_title())); ?>,
        "author" : <?php echo($this->edcal_json_encode(get_the_author())); ?>
    },
    <?php
}

function edcal_posts() {
    header("Content-Type: application/json");

    global $post;
    $args = array(
        'posts_per_page' => -1,
        'post_status' => "publish&future&draft",
        'post_parent' => null // any parent
    );

    $myposts = query_posts($args);

    ?>[
        <?php
        $size = sizeof($myposts);
        for($i = 0; $i < $size; $i++) {
            $post = $myposts[$i];
            edcal_postJSON($post, $i < $size - 1);
        }
    ?> ]
    <?php
}

I ran the code and everything worked. I was about to release the new version but ran my unit tests first to make sure. They failed. Can you spot the bug? I didn’t.

I was returning a JSON array, but the last item in the array had a trailing comma. That’s invalid JSON. Firefox accepts it, but Safari, Chrome and IE don’t. I almost shipped a broken plugin to over half of my users.

Now I run the unit tests on all major browsers whenever I release a new version. Any time WordPress releases a new version, I run the unit tests. WordPress 3.3 broke the calendar — and I found out exactly why in 15 seconds.

Popular Plugins Are Stable Plugins

Most WordPress plugins are free and open source, but free doesn’t always mean cheap. The total cost of ownership of unstable plugins is more than people would pay. That’s a fancy way of saying that users will run from your plugin if it’s a bug fest.

My plugin became popular because of its features, but stability kept it popular. People remember one buggy release for a long time. If the Editorial Calendar deletes or corrupts posts from just one blog, thousands of people would stop using it. And they’d be justified.

Unit tests add the stability you need to support the multitude of browsers, mobile devices and dark corners involved in any JavaScript application. They’re easy to write, and they pay you back: because you find the bugs, and your users don’t.

(al)


© Zack Grossbart for Smashing Magazine, 2012.


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress