Unit Testing

If all goes to plan, this will evolve into a series of tutorials on unit testing libraries/frameworks, the purpose of each one and how they can help you.

What is Unit Testing?

Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinised for proper operation.

What exactly does this mean? Let’s have a look at a small code example

// app.js const isValidEmail = email => {

/^[A-Za-z]+[A-Za-z0-9]*@{1}[A-Za-z]+\.co\.uk$/gi.test(email);

} const emailRegion = email => {

if (isValidEmail(email)) {

return 'UK';

}

return 'Rest of World';

}

We have two functions:

isValidEmail that will check if an email matches a .co.uk address.

that will check if an email matches a address. emailRegion that will return UK if isValidEmail returns true, else it will return Rest of World

These are fairly pointless functions, but it will help with the explanation. Lets now go back to our definition and break it down.

Our application is the file ( app.js ) and our units are our two functions ( isValidEmail and emailRegion ). So in this example, we have two units. So how do we individually and independently scrutinising them for proper operation?

Simple. Does each function (unit) do what it’s supposed to do?

Writing Unit Tests

So how do know if the functions do what they’re supposed to? By writing Unit Tests.

Lets explain this by writing some Unit Tests together; we’re not going to start introducing any frameworks or tools, we’re just going to write plain old JS.

Lets focus on our isValidEmail function. What do we know about this function? Disclaimer: this isn’t a perfect RegEx expression, but it is quick and simple enough for this example.

If a valid email is passed into the function, it should return true otherwise it should return false .

And when is an email considered valid? It must abide by these simple RegEx conditions:

It has at least one letter at the start of the email, followed by zero or more alphanumeric characters, then it must have exactly 1 @ symbol, followed by 1 or more letters and must end in co.uk .

Now lets think of some test scenarios. We want to check that it returns true and false in the correct scenarios.

True

thisisavalidemail99@domain.co.uk

thisis99valid@anotherdomain.co.uk

t9912414@hisisvalid.co.uk

False

9cantstartwithanumber@domain.co.uk

canthaveanumberinthedomain@domain99.co.uk

cantendincom@domain.com

canthaveaspecial$character@domain.com

Let’s finally write some code/tests…



if (!isValidEmail('

throw new Error('email is valid but returns False');

}

if (!isValidEmail('

throw new Error('email is valid but returns False');

}

if (!isValidEmail('

throw new Error('email is valid but returns False');

} // Should return trueif (!isValidEmail(' thisisavalidemail99@domain.co.uk ')) {throw new Error('email is valid but returns False');if (!isValidEmail(' thisis99valid@anotherdomain.co.uk ')) {throw new Error('email is valid but returns False');if (!isValidEmail(' t9912414@hisisvalid.co.uk ')) {throw new Error('email is valid but returns False');

This is not how we’d write tests in a real world scenario, we’d use a testing framework like Mocha , but we’re not focusing on that side of things in this article.

If you ran these tests against the code, you’d get an Error. This wasn’t actually planned, and I almost went back to fix the code; but realised this was a perfect mistake as it shows the benefit of testing.

So why did the function fail? Because we didn’t return the result. If we now change the code to the following and re-run the tests they won’t error.

const isValidEmail = email => /^[A-Za-z]+[A-Za-z0-9]*@{1}[A-Za-z]+\.co\.uk$/gi.test(email);

And just for completeness our checks to make sure we get False :



if (isValidEmail('

throw new Error('email is invalid but returns True');

}

if (isValidEmail('

throw new Error('email is invalid but returns True');

}

if (isValidEmail('

throw new Error('email is invalid but returns True');

}

if (isValidEmail('

throw new Error('email is invalid but returns True');

} // Should return falseif (isValidEmail(' 9cantstartwithanumber@domain.co.uk ')) {throw new Error('email is invalid but returns True');if (isValidEmail(' canthaveanumberinthedomain@domain99.co.uk ')) {throw new Error('email is invalid but returns True');if (isValidEmail(' cantendincom@domain.com ')) {throw new Error('email is invalid but returns True');if (isValidEmail(' canthaveaspecial$character@domain.com ')) {throw new Error('email is invalid but returns True');

Here’s the full source code if you want to run it yourself:

https://repl.it/repls/SatisfiedFirebrickGreatargus