Jon Kruger -
  • About Me
  • Blog
  • Resume
  • Values
  • Presentations
About Me
Blog
Resume
Values
Presentations
  • About Me
  • Blog
  • Resume
  • Values
  • Presentations
Jon Kruger
Uncategorized

Speaking about Unit Testing Javascript on Thursday at CONDG!

I’ll be speaking at the Central Ohio .NET Developers Group this Thursday, Feb. 26 at 6pm… I’ll be talking about Unit Testing JavaScript using Test Driven Development.  We’ll go through what TDD is and how it can help you and show you how to write JavaScript tests against a sample application using QUnit.  Hope to see you there! (Oh, and there’s free pizza too!)

CONDG meets at the Microsoft building at Polaris… the address is 8800 Lyra Dr., Columbus, OH 43240.

February 21, 2009by Jon Kruger
TDD, unit testing

Your personal TDD accountability partner!

The next time you are getting lazy about not writing your tests first and you need someone to keep you in line, you have someone that you can turn to!

February 15, 2009by Jon Kruger
JavaScript, unit testing

Running QUnit tests using continuous integration

On my current project we will be using QUnit to writing tests for our JavaScript.  What would be really nice is if our CI build could run JavaScript unit tests.

Well, it can!  It only takes a few magic potions and sacrificing a few small animals.

Luckily someone had done this before and blogged about it so I pretty much just had to follow instructions.  Here’s the long and short of it:

  • We had to get WatiN, which will be used to create an instance of Internet Explorer that will run our HTML page with the QUnit tests in it.
  • We had to get the IterativeTest addin for NUnit.  This will create one NUnit test for each QUnit test.

In the code, I added an IterativeTest (a test decorated with the [IterativeTest] attribute) that will run all of the QUnit tests.  Since we all use ReSharper and ReSharper doesn’t recognize the [IterativeTest] attribute, I also added a normal NUnit [Test] that will run all of the QUnit tests inside one test and fail if any of the QUnit tests fail.  So we should have all of our bases covered.

February 11, 2009by Jon Kruger
Uncategorized

Tips for becoming a faster developer

One of the common complaints that I’ve been hearing about our industry is that our industry lacks quality in general.  The evidence of this is this never ending cycle of rewriting software over and over because it is unmaintainable, buggy, etc.  Many people would say that this is sometimes a result of developers throwing code together quickly without taking the time to think out their design, write unit tests, or manually test their code. 

Thankfully the pendulum seems to be swinging and people are starting to expect higher quality from themselves and from the people that they work with.  More and more people are jumping on the TDD bandwagon (at least the people I work with are). 

However, speed is still very important — that is, the amount of time that it takes a developer to complete a task or the amount of time that it takes for a team to complete a project.  The fact of the matter is that we all have deadlines for our projects (well, maybe not if you’re working on open source projects).  Hopefully those deadlines are realistic, but they are deadlines that we have to meet.  So quality is definitely important, but speed cannot be ignored.

It seems to me that there is a stigma against developers who say that they work fast.  It seems that if you walk into an interview for a developer position and you say something like, “I’m capable of getting a lot of work done in a short amount of time,” you might as well keep looking because the interviewer will often times assume that you write crappy code and don’t care about quality.

But what if you are able to work quickly and not compromise on quality?  That would be the best of both worlds!  Just like we should all strive to write better quality software, we should also strive to get it done in as quickly as possible (without compromising on quality, of course).  Here are some ways that you can do this:

Become a keyboard ninja

They put those keyboard shortcuts in Visual Studio for a reason, you know.  If you’re writing .NET code you’re probably spending most of your day using Visual Studio (or another IDE if you’re using another language).  So why wouldn’t you take time to learn the keyboard shortcuts?  If you are using ReSharper (and you all should be), there are even more keyboard shortcuts to help you.

When I got my first job, I worked some guys whose goal was to never use the mouse.  These guys knew the keyboard shortcuts for everything, and they sure could get around fast.  Watch somebody who uses the mouse a lot, and watch how long it takes to stop typing, grab the mouse, drag and click, and go back to the keyboard.  It totally takes you out of your rhythm.

If you want to learn to use the mouse less, it really isn’t that hard.  Go print out the keyboard shortcuts for Visual Studio or ReSharper and tape them up at your desk.  Then anytime you reach for the mouse to do something in a menu or a toolbar, look on your cheat sheet and find the keyboard shortcut.  Highlight it on your sheet so that it’s easy to find next time.  You’ll be a keyboard ninja in no time.

Create easy-to-use frameworks

I’ve been on projects where it was really difficult to do simple tasks because the application’s framework put so much burden on the developer because it was way too over-complicated.  Sometimes things have to be complicated, but many times they don’t have to be.  When I’m designing frameworks, I will spend more time on writing framework code if it will make life easier for the developer using it.  Frameworks should help developers get things done, not hinder them.  The success of your project may hinge on this.

Use code generation tools

If you find that you’re doing a repetitive task over and over again, take the time to set up some code generation templates to help you generate that code.  There are many ways to do this:

  • Code generation tools like MyGeneration
  • Visual Studio code snippets
  • ReSharper Live Templates (code snippets on steroids)
  • Visual Studio file templates

Don’t get stuck writing plumbing code over and over again.  Usually there is some repeatable pattern that you can recreate using a some kind of code generation tools.  Every developer should be at least somewhat familiar with these kinds of things.

Control distractions

There are lots of things that can distract you while you’re writing code, like meetings, emails, IM, Twitter, etc.  Sometimes you can’t always control these (e.g. meetings) but the rest are under your control.  The world is not going to end if you can’t check your email, send IMs, follow Twitter, etc. for a day.  I’m not saying that you should always shut those off.  I’m just saying that we all need to be careful that they don’t become a distraction.  It’s really easy to get caught up in discussions on Twitter, but remember, you’re being paid to produce, not discuss things on Twitter.  (If you are getting paid to participate in discussions on Twitter, then lucky you!)

Buy ReSharper

I think I’ve already mentioned ReSharper several times now.  It’s only $199 for a personal license.  I don’t know how I wrote code for so long without it.  My company bought a license for everyone on my team and it was the best money they ever spent.  Some of the refactoring tools and keyboard shortcuts are really useful if you’re doing TDD and creating a lot of interfaces.

February 1, 2009by Jon Kruger
.NET, Design, Fluent NHibernate, LINQ, NHibernate, WCF

Helping everyday developers succeed

Software development is hard. You have to know how to use so many different tools and you have to try and keep up with it all.

Lately I’ve been hearing some griping about certain tools that people feel are trading good software design principles for ease of use. Many of these tools usually have some kind of drag-and-drop designer functionality that is designed to help you get things done faster. The griping comes from the fact that these tools can cause developers to make poor design decisions because the drag-and-drop tool led them in the wrong direction. I can’t say that I disagree with these complaints.

There are two sides of every coin, so let’s swing the pendulum the other way. Many open source libraries that I’ve seen take a different approach to design and the people that write them say that they’re not writing them for the novice user and that you will have to be familiar with advanced design patterns in order to use these tools. I think this is a good thing because software development is complicated and it’s OK to have make a library more complicated so that it fits in with good design patterns (like the need for an IoC container in FubuMVC).

Sometimes I wonder if we could do more to make these complicated tools easier to use. Take ORMs for example. Most people out there would agree that NHibernate is the most fully-functional ORM that we have. Yet I was on a project a couple years ago where developers floundered around trying to get their NHibernate mapping files to work (usually because of stupid stuff like typos, not making the .hbm.xml files Embedded Resources, not fully qualifying an assembly name, not making something virtual, etc.). Eventually we got better at it and we learned the tricks, but we wasted a ton of time trying to fix stupid mapping file issues.

For the next project I was on, we chose LINQ to SQL over NHibernate (this was in early 2008 when LINQ to SQL had just come out). I had an existing database with my tables in it, so I dragged them all into the LINQ to SQL designer and started writing business logic. It was amazing! It all just worked!

Now that led me into other pitfalls because now I had to map my objects 1:1 with my database tables, and crap from the database concerns cluttered up my model and caused a lot of grief. But even with that, we got work done much faster with LINQ to SQL than with NHibernate. Does this mean that LINQ to SQL is “better” than NHibernate? I wouldn’t say that, yet I was able to be more successful with LINQ to SQL. This is an important thing to note.

Open source tools like NHibernate are usually written by really smart people. Really smart people have no trouble figuring out complicated stuff. Sure, they may experience the same pain at first, but they pick it up quickly. All of the other really smart people that they talk to understand it too.

Not everyone is really really smart, unfortunately. I hear a lot of people harp on NHibernate and say it’s way too hard to use, that it’s not worth it, that there has to be a better way, etc. Most of these opinions come from a bad experience that they had with NHibernate.

I can’t discount these opinions that people may have. While these same people may agree that NHibernate is the most fully-featured ORM out there, for them it is not the ORM that will make them the most successful. I know a lot of people in this camp and they are not stupid people and they aren’t too lazy to learn NHibernate. It’s just that NHibernate did not lead them into the pit of success.

The fact is that most developers that are going to be using tools like NHibernate are your common, average, everyday developer — not bad developers by any stretch of the imagination, but they’re not as smart as the really smart people. I’m certainly not saying that we should sacrifice functionality and good design patterns to make things easier to use. I just think that more effort should be spent on making sure that average developers can figure out how to use something correctly, whether through documentation, good examples, or coming up with easier ways to do things. Really smart people don’t need these things to be successful with these tools, but the average developer will benefit immensely.

For me, this is what Fluent NHibernate did for NHibernate – it abstracted away a lot of what was difficult about NHibernate. Recently I’ve been able to use it on a project and it totally turned the tables. Now I get the power of NHibernate but I can use conventions to auto-wire my mappings, and the mappings are all in code instead of in XML. For me this is a huge deal. Now I get the power of NHibernate and I’m not stuck doing all of the crap that slowed me down before.

Another example of this is the reams and reams of documentation that the Microsoft patterns & practices team has written up for writing secure applications with WCF. WCF is very complex and powerful, but Microsoft did not leave us hanging and wrote up what to do in almost every scenario imaginable. They didn’t just give us a tool, they gave us what we needed to be successful with it.

We need more stuff like this.

January 22, 2009by Jon Kruger
Quality

Why does our industry have such a low standard of quality?

As I was writing my post on aspiring to be a Software Craftsman, I was thinking about why we have such a low standard of quality in our industry. Clearly there is a problem when there are so many software projects out there that are rewrites of previous projects, and businesses are hamstrung by software that is too difficult to change.

I’m very much an optimist most of the time, honest! But I can’t help notice all kinds of things that don’t sit well with me.

Poor university training

I had 5 classes in my 4 years of college that were relevant to software development. I graduated in 2002. They started us out on C++, which was a fair choice in 1998. I was not able to take a database course until my senior year. During my last semester they finally introduced an intro to Java course which I was able to take. No courses on .NET, no courses in PHP, no courses in software design, no courses on techniques that could’ve made me successful (like unit testing).

The software industry is constantly changing, and many university programs are not keeping up. When you graduate you know just enough to be dangerous but not enough to really know what you’re doing. 4 years is a long time, you should be able to learn a lot during that time.

Post-college training is not encouraged

If you want to learn about software development, there is always a user group you can go to, a conference you can attend, thousands of blogs you can read, podcasts to listen to, and on and on. There is a wealth of information out there, but the average developer is not taking advantage of it. Some of these people don’t care to learn. But I think that most people care about doing a good job. The problem is that their employer does not encourage it. If someone doesn’t want to spend their time outside of work reading blogs and attending conferences, that’s their choice. There is nothing wrong with leaving your work at work and spending time with your family or doing other things. But most employers don’t offer enough training during work hours, whether that is organizing lunch and learns, paying for their devs to go to CodeMash, bringing in guest speakers, etc. It costs a lot of money to build software. Shouldn’t employers be willing to spend a little more money to train their employers so that they can build better quality software?

People don’t know what they don’t know

There are a lot of developers out there don’t know software design techniques and concepts like unit testing, what SOLID stands for, why you should use an IoC container, and why you should design with interfaces. I would guess that a majority of these developers would love to know this stuff, but they don’t know that they don’t know it. A year ago I had never used Rhino Mocks, and I didn’t know what SOLID stood for or what an IoC container was. I thought I was a good developer, and I was in charge of a fairly large project, but I didn’t know that I didn’t know these things. Now that I’ve learned all that stuff I am a much better developer than I was a year ago. But now I’m wondering what other important stuff I don’t know.

My point is that I’m sure that it would really help developers if there was some way that they could go through some kind of training that would teach advanced software development topics like the ones that I mentioned. I see a lot of junior developers take Microsoft certification tests. It is unlikely that Microsoft certification tests will teach you any of the concepts that I mentioned. You will, on the other hand, memorize a lot of stuff that you can find on Google. I’m not saying that studying for and taking those tests won’t teach you anything, but they’re not going to teach you how to write quality software.

Low business expectations

Many IT managers and executives have very low expectations for their software. Having to rewrite software is widely accepted as normal these days. Wouldn’t it be so much better and cheaper to change your existing software when you need it to do something different?

The problem is that so much of our software is too difficult to change due to bad design, lack of testing, and many other factors. Many businesses do very little to address the root problem — that their developers don’t have the adequate training or don’t have the ability to write good software that can last.

Many IT managers believe that the best that they can do is this disposable software, so they decide that they might as well pay less money if they’re going to get low quality, so they turn to offshoring. Either way, they’re still getting the same low quality software and they’re wasting money rewriting their software every several years.

Short term thinking

Many business get sucked into short term thinking. I’m sure there are many ways that this can work, but here’s one way I can see this happening.

  • Executives want to show results because they’re worried about their stock price. They demand results this year.
  • IT Manager is under pressure to deliver something this year, possibly with a limited budget.
  • Developers are under pressure to deliver something and have really tight deadlines.
  • Developers throw something together and finish the project. IT Managers show it to executives who like what they see. Executives show it at a trade show and shareholders are happy.
  • Two years later the software does not meet the needs of the business because the app is unmaintainable and they start budgeting money to bring in consultants to rewrite it.

It would’ve made much more sense to invest more time and money into the project the first time so that it wouldn’t have to be rewritten two years later. But because the business needs to show progress to the shareholders they won’t do it this way. This is a tough situation, and I can understand why executives make some of these decisions, but it doesn’t seem to make sense to me.

Little or no accountability

If you’re a developer and you write bad code, you probably aren’t going to lose your job unless there is a recession, you do a really really bad job, or just quit showing up for work. If a civil engineer builds a bridge that fails after 5 years, I guarantee you he won’t be working on bridges anymore, at least not at the same company. There is very little pressure in the software industry to write quality software.

In closing…

I don’t know what the solution to this problem is because it is a problem on so many fronts. But I do have control over what’s around me. I can aspire to become a software craftsman — someone who designs and writes quality software. I can hold myself accountable and make sure that I have high standards. And I can try and teach other people to do the same.

January 14, 2009by Jon Kruger
Quality

Are you a Software Craftsman?

There has a bunch of talk recently on blogs and in the open spaces at CodeMash about what other industries or professions we can compare software development to. The point of this was to look at these other industries and see what we can learn from them and how their practices can be applied to software development, particularly in the area of quality.

The title “software engineer” is frequently used to describe software developers. Let’s look at what an engineer in another discipline, civil engineering, might go through in their career.

Building a bridge leaves very little margin for error. Numerous people are involved in the construction of a bridge, including civil engineers, who will design the bridge, ensure that it will be safe, be able to handle winds and earthquakes, and on and on.

How did the civil engineer get to this point? He or she probably spent 4 years in college, then at some point had to study to take the PE exam, and probably went through extra study and training to learn the intricacies of bridge construction. That’s a good amount of training.

Quality is of the utmost importance to a civil engineer for obvious reasons – when you drive across a bridge, you expect to make it to the other side. If a civil engineer builds a bridge that fails, he is going to be in big trouble for that mistake, possibly to the point that he loses his job (if the offense is egregious enough).

In our discussions, the title that we preferred over “software engineer” is “software craftsman”. What’s the difference?

A craftsman might go through a different kind of training, and the work is slightly different. Take a carpenter for example. A carpenter will probably go through some sort of schooling, and then do an apprenticeship with a master carpenter. If he is good enough, eventually the apprentice will learn enough to become a master carpenter himself.

Let’s say that our master carpenter is building kitchen cabinets. There are certain basic design principles that he will follow, and he will be as precise and accurate as possible. You expect your cabinets to stay attached to the wall, you expect the doors to be on straight, and you expect the shelves to hold 20 plates and 15 bowls without collapsing. At the same time, there is an aesthetic element to kitchen cabinets, which is the criteria that you probably look at the most when you go to the store to buy kitchen cabinets.

Let’s compare the software development industry to these two disciplines. The average software developer goes to school for 4 years. Personally I think that university Computer Science programs are a joke (at least in the U.S., can’t speak for other countries). In my 4 years at the U. of Toledo I think I had 5 classes that taught me something relevant to real world software development. The words “unit test” were never uttered in my classrooms <shudder>.

Once the developer graduates from college, he immediately gets a job in the workplace and starts working on projects. In my case, I had 5 relevant classes in my 4 years, which equates to about one semester. This developer may receive little or no formal training after this for the rest of his career. Over the course of his career, this developer will write sub-standard quality code, but he’ll continue to get his standard raise every year and might even become a manager someday. Trust me, I have seen it happen.

Are we surprised at the quality of the software that is being written based on this analysis? A civil engineer builds a bridge that collapses, and he will probably not build another bridge again. If a carpenter builds cabinets using shoddy materials that don’t hold up, and no one will buy his cabinets. A software developer writes poor quality code, and he’s on the new team a few years later that is rewriting the legacy app in a different language.

There are so many problems here that I don’t even know where to start. You may not know everything about software development, and that’s fine. But there is no excuse for our lack of quality in our industry.

Let’s look at one area — testing.

Many developers would agree that unit testing and test driven development are good ideas. Even people who aren’t good at testing or TDD would say that. If you’re one of those people, learn how to do it! Ideally, find someone you know that knows how to do it and pair program with them for a week and you’ll be on your way. If you do know how to test, stop cheating and write your tests!

We’ve all caught ourselves cheating. We know that we should write tests but for whatever reason we don’t do it. That’s not holding yourself accountable. You are sacrificing quality, period.

Are you an aspiring Software Craftsman?

A software craftsman has a higher standard. A software craftsman cares about his craft and takes pride in doing quality work that will stand the test of time. A software craftsman does not cut corners or do shoddy work just to cross something off their to do list. Is that your standard?

January 14, 2009by Jon Kruger
JavaScript, TDD, unit testing

Code & slides from Unit Testing JavaScript talk

Here are the slides and code from the Unit Testing JavaScript talk. Or if you one of those people you can get it all from the Subversion repository at http://minisudoku.googlecode.com/svn/trunk/.

(UPDATE 2/25/09: these links point to the latest versions of the slides and the code, which now include examples using both JSSpec and QUnit.)

November 25, 2008by Jon Kruger
JavaScript, TDD, unit testing

Unit Testing JavaScript – Test Driven Development in action!

So far I’ve talked about JavaScript basics, JavaScript test frameworks, and writing testable code. Now for the real fun… let’s do some test driven development!

I know that TDD seems somewhat backwards to a lot of people, and it’s hard to undo the years and years of not writing tests. I learned from watching people doing it and learning the thought process and reprogramming my head so that I could think in a new way. So hopefully this will help you understand the thought process.

Step 1 – Get your requirements

So you’re about to start on a new feature or fix a bug. Either way, you will get requirements in some form.

In this case, we want to create a greatly slimmed down version of Sudoku. Here are the rules:

  • The puzzle will have only 4 boxes in a 2×2 grid.
  • You can enter numbers 1 through 4 in a box by selecting a box and pressing the number keys on the keyboard
  • Selecting a box and hitting the Delete key should remove the value in the box
  • You can change the numbers or remove the numbers at any time
  • Give the user a button to click that will check to see if the puzzle is valid
  • Give the user a button that will give the user a new puzzle. A new puzzle will have 2 of the numbers already filled out.
  • A puzzle is valid if:
    • Each box has a number 1 through 4
    • Each box has a different number

OK, so what do you do now? Most people would start hammering out some JavaScript classes. But we’re not going to do that, because we’re not done with the design phase yet.

What do I mean by that? Well, one of the big reasons that we write tests first is to help us design our code. Sure, you could write tests after you write the actual code. But if you do it that way, you will spend lots of time refactoring code (that you don’t have tests around yet) in order to make it testable. That’s wasted time, so we’ll do our design up front by outlining our tests, writing the tests, and then writing the code.

Step 2 – Refine the requirements

Let’s look at the first bullet point in our requirements:
The puzzle will have only 4 boxes in a 2×2 grid.

Business requirements aren’t always written out as individual acceptance criteria, so let’s split this line into individual requirements and write them out.

  • The puzzle should have 4 boxes
  • The boxes should be in a 2×2 grid

Step 3 – Write out the test methods

Now that we have that, let’s translate that into tests:


describe('When creating a new Puzzle',
{
'The Puzzle should have 4 Boxes': function()
{
}

'The boxes should be in a 2x2 grid': function()
{
}
});

Step 4 – Stub out implementation classes

Now we have two tests. These tests will help us design our code. Let’s see what we can learn from these tests:

  • We need a Puzzle object
  • We need a Box object
  • The Puzzle should have a collection of Boxes
  • We need a way to ask the Puzzle for a box at a given coordinate in the grid

Let’s write these classes and methods, but we won’t implement the methods yet.


function Puzzle()
{
var boxes = new Array();

this.getAllBoxes = function()
{
}

this.getBox = function(columnIndex, rowIndex)
{
}
}

function Box(columnIndex, rowIndex)
{
this.getColumnIndex = function()
{
return columnIndex;
}

this.getRowIndex = function()
{
return rowIndex;
}
}

Step 5 – Write test code

Now that we have our objects, we can write the code inside our test methods (I’m using JSSpec as my testing framework):


describe('When creating a new Puzzle',
{
before_each: function()
{
puzzle = new Puzzle();
},

'The Puzzle should have 4 Boxes': function()
{
value_of(puzzle.getAllBoxes().length).should_be(4);
},

'The boxes should be in a 2x2 grid': function()
{
for (var columnIndex = 0; columnIndex < 2; columnIndex++) { for (var rowIndex = 0; rowIndex < 2; rowIndex++) { var box = puzzle.getBox(columnIndex, rowIndex); value_of(box.getColumnIndex()).should_be(columnIndex); value_of(box.getRowIndex()).should_be(rowIndex); } } } });

We've written our tests. Now let's run them and watch them fail. The reason we do this is because if these tests pass now, then they're probably not written correctly and we don't want false positives.

Failing tests

Yep, they're failing, just as I expected.

Step 6 - Write implementation code

Now, yes now, you finally can write your implementation code. I know that some of you have been chomping at the bit to get to this point. So here we go.


function Puzzle()
{
var boxes = new Array();

for (var columnIndex = 0; columnIndex < 2; columnIndex++) { for (var rowIndex = 0; rowIndex < 2; rowIndex++) { var box = new Box(columnIndex, rowIndex); if (boxes[columnIndex] == undefined) boxes[columnIndex] = new Array(); boxes[columnIndex][rowIndex] = box; } } this.getAllBoxes = function() { var list = new Array(); for (var column = 0; column < boxes.length; column++) { for (var row = 0; row < boxes[column].length; row++) list.push(boxes[column][row]); } return list; } this.getBox = function(columnIndex, rowIndex) { return boxes[columnIndex][rowIndex]; } } function Box(columnIndex, rowIndex) { this.getColumnIndex = function() { return columnIndex; } this.getRowIndex = function() { return rowIndex; } }

Let's run the tests and see if the code works.

Success!

Sweet goodness. But I've only implemented one of the requirements. No problem, I'll just go back to step 1 again and go through the process with the next requirement and repeat until I'm done with all of the requirements.

Let's take a look at what we have now.

  • We have code that we know is working correctly
  • We have tests to prove that the code is working correctly, both now and from now on
  • We have tests that describe what the code is supposed to do. Our tests are documenting our code!
  • We have well designed classes
  • Our classes do only what they're supposed to do -- we didn't waste time writing things that we don't need
  • We have peace of mind!!

Let me talk about this peace of mind. This is something that I can describe to you but you can't understand it until you experience it. I am 99% sure that the code that I wrote is working now and will continue to work in the future. I can refactor my code or make changes and I know that it will be working correctly when I'm done. I can guarantee you that the only way that my code has bugs is if there is some requirement that I didn't know about. Can you say that about your code?

What happens when it's a day or two before you put something into production and they find a nasty bug that absolutely has to be fixed before you go live? (Certainly not the ideal situation, but it happens all the time.) Wouldn't you love to have a suite of tests to run so that you can be less likely to break something else when you fix the bug? (And remember, bugs are much more costly and difficult to fix when they're in production.)

Have you ever been in that endless cycle of fixing a bug only to break something else, and then when you fix that bug you break something else, and on an on?

This is why I write tests. And this is why I will never go back.

How to get started with TDD

People ask me how to get started doing TDD. The best way is to just do it. The next time you have a simple feature or a simple bug to fix, write your tests first. It takes awhile to get into the mindset, but once you do it a few times it starts to make a lot more sense. If you know someone else who is good at TDD, testing, mocking, etc., pair program with them for a day and watch how they work. You'll need to get better at separation of concerns, programming to interfaces, and the like. Maybe that will be my next post. :)

Completed sample project

I went through the entire exercise with the MiniSudoku project. You can download the finished product here. (UPDATE 2/25/09: this link contains examples using both JSSpec and QUnit.)

Good luck!

November 25, 2008by Jon Kruger
JavaScript, TDD, unit testing

Unit Testing JavaScript – Writing testable code

Last time we talked about JavaScript test frameworks. But a test framework is no good if you don’t write testable code.

Writing testable JavaScript

As is the case with .NET code, one of the most important parts of testing is writing code that you can actually test. Let’s look at some untestable JavaScript code and what we can do to make it testable.


// Untestable JavaScript :(
function MyClass
{
this.showMessage = function(message)
{
$("#messageTextBox").text(message);
}

this.anotherShowMessage = function(message)
{
document.getElementById("anotherMessageTextBox").innerText = message;
}
}

This code is untestable because it directly references UI elements in a page by name. When you run unit tests using pretty much any JavaScript testing framework, you create a separate page to run your tests from. That means that your UI elements will not be on that page, so any code that references these elements by name will not be testable.

Here’s how you would make this testable:


// Testable JavaScript!
function MyClass()
{
var element;

this.getElement = function()
{
return element;
}

this.setElement = function(newElement)
{
element = newElement;
}

this.showMessage = function(message)
{
element.innerText = message;
}
}

// unit test
describe('When showing a message',
{
'The message should be displayed in the element': function()
{
var myClass = new MyClass();
myClass.setElement(new function() { this.innerText = null; });

myClass.showMessage('I love testing!');

value_of(myClass.getElement().innerText).should_be('I love testing!');
}
});

Notice how MyClass still has the notion of a UI element, but now the UI element is injected by whoever is using the class. And since JavaScript is a dynamic language, this is easy to test because we don’t need an actual UI element in our unit test, we just need an object that has an “innerText” variable on it. Creating said object is as easy as doing this:

var myFakeUIElement = new function() { this.innerText = null; }

This is what I can do in my test. I tell MyClass that its element is my fake UI element, I call showMessage(), and then I verify that the innerText variable of my fake UI element got set.

Another example:


// Untestable JavaScript :(
function MyClass()
{
this.showMessage = function(message)
{
alert(message);
}
}

I think this one is pretty obvious. If you try and test this method, you’re going to have an alert box popping up on the screen in the middle of your tests. Not going to work. Try this instead:


// Testable JavaScript
function MyClass()
{
this.showMessage = function(message)
{
this.showAlertBox(message);
}

this.showAlertBox = function(message)
{
alert(message);
}
}

describe('When showing a message',
{
'The message should be displayed in an alert box': function()
{
var alertMessage;
var myClass = new MyClass();
myClass.showAlertBox = function(message) { alertMessage = message; }

myClass.showMessage('I love testing!');

value_of(alertMessage).should_be('I love testing!');
}
});

Here I separated my concerns again — I created a separate method that only shows the alert box. I can “mock” this method by simply redefining it to whatever I want (in this case I’m just storing what was passed into it). Now I can test that when I call MyClass.showMessage(), I can verify that it called the method that would show an alert box.

Time for more sadness:


// Untestable JavaScript :(
function MyClass()
{
this.result = null;
this.loadCustomerData = function(customerId)
{
$.ajax({
type: "POST",
url: "CustomerService.asmx/LoadCustomer",
data: "customerId=" + customerId,
success: function(msg)
{
this.result = msg.d; // return value from web service
}
});
}
}

This is an asynchronous Ajax call using jQuery. The problem here is that because this is actually making an asychronous Ajax call, the method will return and our test code will run before the callback executes.

There are two ways to solve this:

Solution 1:

// Testable JavaScript
function MyClass()
{
this.result = null;
this.loadCustomerData = function(customerId)
{
$.ajax({
async: false,
type: "POST",
url: "CustomerService.asmx/LoadCustomer",
data: "customerId=" + customerId,
success: function(msg)
{
this.result = msg.d; // return value from web service
}
});
}
}

describe('When loading a Customer',
{
'The customer name should be returned': function()
{
var alertMessage;
var myClass = new MyClass();
myClass.loadCustomerData(1);
value_of(myClass.result).should_be('Jon');
}
});

What changed here? I added “async: false” to the $.ajax() call. Now jQuery will run this method synchronously and I will be able to test it.

Caveat: This violates the basic rules of “what is a unit test” because an external dependency is involved (in this case, my .asmx web service). You can decide for yourself whether this is bad or not. In my case, the test still runs lightning fast because all it does it return some random numbers and it never hits a database, so it doesn’t bother me too much. But if you have a more complicated web service that you’re running and it takes a long time to return data, you may not want to do it this way. Here’s another way to fix this:

Solution 2:

function MyClass()
{
this.result = null;
this.loadCustomerData = function(customerId)
{
var myClass = this;
this.makeAjaxCall(
"POST",
"CustomerService.asmx/LoadCustomer",
"customerId=" + customerId,
function(ajaxResult) { myClass.result = ajaxResult; });
}

this.makeAjaxCall = function(type, url, data, successCallback)
{
var result;
$.ajax({
type: type,
url: url,
data: data,
success: function(msg)
{
successCallback(msg.d); // return value from web service
}
});
return result;
}
}

describe('When loading a Customer',
{
'The customer name should be returned': function()
{
var ajaxType;
var ajaxUrl;
var ajaxData;
var ajaxSuccessCallback;

var alertMessage;
var myClass = new MyClass();
myClass.makeAjaxCall = function(type, url, data, successCallback)
{
ajaxType = type;
ajaxUrl = url;
ajaxData = data;
ajaxSuccessCallback = successCallback;
};

myClass.loadCustomerData(1);
value_of(ajaxType).should_be('POST');
value_of(ajaxUrl).should_be('CustomerService.asmx/LoadCustomer');
value_of(ajaxData).should_be('customerId=1');

ajaxSuccessCallback('somevalue');
value_of(myClass.result).should_be('somevalue');
}
});

Slightly more complicated doing it this way, but if the situation warrants it, it’s worth it.

Next stop: we’ll do some test driven development and see this stuff in action!

November 25, 2008by Jon Kruger
Page 20 of 23« First...10«19202122»...Last »

About Me

I am a technical leader and software developer in Columbus, OH, currently working as a Director of Engineering at Upstart. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...