Photo credit: Jamez Picard, unsplash.com

How frontend unit testing turned from a fling to a real thing for me

Just now. Just like that.

It’s hard to get around the word “testing” if you’re on your way to become a professional programmer. Of course I read about it and even spend a few hours writing tests and solving artificial problems with test driven development. But I didn’t have the opportunity to apply my acquired knowledge in my day to day coding life. It just isn’t a thing at my job. We don’t write tests (yet, I want to change that) and so for a long time, all I knew about testing was more on an academic level.

How the fling started

Pet projects to the rescue!

I’m lucky to work on a few pet projects with experienced programmers. The most important thing I learn from my these projects are new or different workflows, best practices and patterns. In a project I’m currently working on I finally wrote real tests in a real environment. Hell, I had a lot of fun!

By all means, I’m still a bloody beginner when it comes to unit testing. But now I finally saw and felt all the benefits I only read about before. And yeah, I fell in love a bit!

Since a few days I’m working on a text about testing in the frontend with an example from said pet project. It helps me learn more about testing. At the same time I try to build a simple workflow to test my code for an non-testing environment, so I’ll be able to deliver more stable solutions. My new found feelings for testing are there, but I’m not really sure if and how they will work in my job.

Real world catching up — TIFU

Today, I received a bug ticket. For a simple Javascript feature I wrote a few months ago. I saw the description of the ticket, took one look into the code and I was furious at myself. I could see my error right away and it was a stupid one.

Background: The script should take an integer and give back a number formatted in the € currency format — a dot as thousands separator if needed and “Euro” at the end.

That’s what my script looked like:

function formatSum(sum) {
var sumNum = sum.toString().split('');
var sumFormatted = [];
  for (var i = 0; i < sumNum.length; i++) {
var currNum = sumNum[i];
    if (i != 0 && i % 3 == 0) {
sumFormatted.push('.');
}
    sumFormatted.push(currNum);
}
  if (sumFormatted.length > 0) {
sumFormatted.push(' Euro');
}
  return sumFormatted.join('');
}

I wrote this almost 4 months ago and really, I’m not proud. Nobody noticed the error for quite a time, because the function was used to format integers delivered by an API and — coincidentally — they all had six digits for a while.

  • My first thought: Damn, you’re stupid.
  • My second thought: Damn, you’re so f*** stupid, you only checked your script on the live site. You didn’t test your damn code properly!
  • My third thought: Huh. You’re smarter now than back then.

Me and testing: Getting serious

Here’s what I did to fix the bug: I wrote tests. I didn’t touch the script, I didn’t changed a single thing. I opened my editor and I. Wrote. The. Fucking. Tests.

function assertEqual(actual, expected) {
if (expected === actual) {
console.info('[SUCCESS] Is ' + expected);
} else {
console.error('[ERROR] Expected ' + actual + ' to be ' + expected);
}
}
function tests() {
console.log('Test results');
  assertEqual(formatSum(1), '1 Euro');
assertEqual(formatSum(12), '12 Euro');
assertEqual(formatSum(123), '123 Euro');
assertEqual(formatSum(1234), '1.234 Euro');
assertEqual(formatSum(12345), '12.345 Euro');
assertEqual(formatSum(123456), '123.456 Euro');
assertEqual(formatSum(1234567), '1.234.567 Euro');
}

I ran the tests.

I used an old grunt setup I did a while ago to practice TDD.

The bug ticket reported a false format with a 5 digit number and the test reproduced this — 123.45 Euro instead of 12.345 Euro

I corrected my script.

function formatSum(sum) {
var sumNum = sum.toString().split('').reverse();
var sumFormatted = [];
 for (var i = 0; i < sumNum.length; i++) {
var currNum = sumNum[i];
if (i != 0 && i % 3 == 0) {
sumFormatted.push('.');
}
sumFormatted.push(currNum);
}
if (sumFormatted.length > 0) {
sumFormatted.reverse();
sumFormatted.push(' Euro');
}
return sumFormatted.join('');
}

Note: I didn’t touch it otherwise. I didn’t refactor it, I didn’t make it better, I didn’t make it prettier — I just fixed my error.

I ran my test again.

Now that’s a view I like.

All done. I could push that change. It cost me about 10 minutes to curse me for a bit, write my tests and correct my script. That’s it! Now, there are tests for my function. I could refactor ist, write a new one — anything. While testing it.

What I learned today

  • I really like testing. We are, like, serious now!
  • There are so damn many things I have to learn about testing and I’m really looking forward to it.
  • I don’t have to wait for anyone or anything to write tests. Yeah, it would be best to work with a 100% code coverage and test allllll the things — but even one little test can improve my code and make me a better programer in the long run. And hey, I’m a perfectionist, I strive for improvement ;)
  • Testing doesn’t have to be time consuming and therefor expensive! On the contrary: If I had written proper tests in the first place, the second bug ticket would never have happened.
  • I write better code today than three months ago.
  • Committing (sometimes even writing) code without tests feels a bit like driving without seatbelt now.