Picture by Glenn Carstens-Peters from Unsplash

Why should you write tests?

Coming to web development from a design background I understand the need to test the part of the site or web app that the user interacts with which involves testing things like; browser compatibility, usability, regression, and accessibility. However, I wasn’t really well diverse in the realm of automated code testing. Terms like ‘unit testing’, ‘integration testing’ and ‘100% test coverage’ flew over my head. I didn’t see the need to essentially write two times the code to do a test that you could do manually.

As my role (and what is required from a front end dev) has evolved, I’ve had to delve more into the Javascript side of things and I’ve seen the benefits of writing tests. There are multiple types of tests one could write and knowing the benefits and disadvantages of them are important for all developers. If you’re from a design background like me and want to get a better understanding of testing, or a seasoned developer who wants a refresher on testing types, this article is perfect for you.

This post will focus testing for applications that run on the web, not general software applications, so only testing methodologies and techniques that are web related will be mentioned.

1. Why test?

There are many benefits to writing automated tests for web applications here are just a few;

  • You’re more productive because you don’t have to spend the time manually testing the code yourself.
  • You can make changes to the code without worrying if something is broken (as long as the tests pass).
  • Tests provide documentation for what your code is actually meant to do.

This isn’t an advocate for test driven development (TDD) as I actually practice behaviour driven development (BDD), but you can subscribe to either and still write tests, or even a little bit of both.

2. Black Box & White Box testing

Starting off with the thing that’s most easiest to visualise. Probably not phrases you’ll hear developers commonly use when it comes to testing but it’s a good way to differentiate between the two main types.

a. Black box

Testing without knowing the internal workings of an application. Essentially you pass an input into a black box and check if the output is what you expected.

b. White Box

The opposite of black box, testing the code of the software. White is meant to imply the box is see-through, so really it should have been transparent box testing but I guess white is easier to say.

3. Unit > Integration > Functional

There are many types of tests a web application can have, but these are the three main automated ones that most if not all should.

a. Unit tests

Most popular white box test amongst developers which involves testing a unit of code; a function, method or class while it’s isolated from other parts of the code. This tests if that part of the code is working as it should, and since it’s not connected to other parts if external bits of information are required either a Mock or Stub is created.

  • Mock: A fake method or object that simulates the behaviour of a real one. For example, say you want to test if an external API you use will replace a set of letters with its numerical value in the alphabet, you can recreate that method as a mock, pass a string, and test its output.
  • Stub: Object (usually written by hand) that isn’t dynamic, and is simply used provide data. For example, if a method being tested requires a name, address, height, and gender form an API to work but it doesn’t have to be specific, a stub could contain all this information in the test file itself and each time the test is run, it collects that information, eliminating the need to fetch from the API.

Bear in mind these are general definitions and different testing frameworks can have different variations on these features. Frameworks for Javascript (JS) unit testing include; Jasmine, Mocha, Tape, Jest and many others.

b. Integration tests

Most modern web apps not only have components/classes that interact with each other, but also an external API, a database or have a dependency on a third party tool. Integration tests make sure all these connections are in good working order. As unit testing replaces the need to test anything external with mocks and stubs, integration tests are the only way to do it.

Depending on what type of integration test is required the framework used here will most likely be identical to the one used for unit testing.

c. Functional tests

Also known as End-To-End tests (E2E) these tests are mostly black box testing. This involves testing what the user will actually interact with, so the inputs they will use, the buttons they click, and what they see on the screen. In order for this to be achieved a fake browser is manipulated by the testing framework. Functional tests also tend to check how the site performs under different network connections and hardware.

Some developers put functional tests under integration as these need to check the external services and component relationships in order for the app to work as desired, but I like to keep them separate. JS functional testing frameworks include PhantomJS; Jasmine, Protractor, Nightwatch, CasperJS, Nemo, and many others.

4. Working out Test Coverage

The term ‘Test Coverage’ actually encapsulates the coverage of all three tests described above. When you hear a developer say something like ‘100% test coverage’, they are most likely referring to _Code Coverage_. There are multiple ways to work out code coverage, but two main ones, branch and statement coverage. There are also tools to held calculate coverage, but I haven’t personally used any before so I don’t know how good they are.

a. Branch Coverage

Branches are the possible options of a decision point, so if statements, loops, switches and so on. Branch coverage involves testing all the possible branches in a piece of code. So an if statement without an else if will have two branches to test. If one branch has tests, that equates to 50% code coverage and if both branches have tests, that’s 100. This Udacity video does a good job of explaining it.

b. Statement Coverage

Although branch coverage covers more scenarios that statement coverage, this is the preferred coverage calculation method of most developers. Statement coverage checks if each link of what’s being tested is touched by the test. So again for an if statement without an else if if a test is written for the if and one for the else, then all lines of the code have been touched which equates to 100% test coverage. However, if this same if statement does not have an else written, that means writing one test for the if will hit all lines of code, but the invisible else has not been tested, so it’s not really 100% test coverage. That’s why branch is better. This Udacity video does a good job of explaining it.

Conclusion

So to answer the question of this article, should you write tests? Well, I guess that’s down the person who makes decisions in your workplace of the type of product you’re working on, but the way the industry is going it is expected for most front-end devs to have some testing experience (mainly unit testing). But whatever you decide to do, I hope this post has helped educate you in some way on what testing in and what type of testing to go into, if or when you decide to do it.

Sources

I’m sad to say I didn’t have all this knowledge lodged in my brain somewhere, I had to do a bunch of research to come up with it and here are the articles, sites, and videos that helped me the most.

https://code.tutsplus.com/articles/the-beginners-guide-to-unit-testing-what-is-unit-testing--wp-25728
https://www.guru99.com/
https://www.youtube.com/watch?v=9PSrhH2gtkU
https://pusher.com/sessions/meetup/london-node-user-group/fullstack-integration-testing-that-doesnt-suck
https://stackoverflow.com/questions/28605496/what-is-the-difference-between-smoke-testing-and-sanity-testing
https://www.sitepoint.com/javascript-testing-unit-functional-integration/
https://www.youtube.com/watch?v=qFaBHHg6RQU