Cinnamon logo
Cinnamon logo
Cinnamon logo
Cinnamon logo
Close

Home

Projects

Services

About Us

Careers

Blog

Contact Us

A Gentle Intro to JavaScript Testing

Vjeko P.

2021-05-27

6min

Development

This is not one of those tutorial-sized articles about testing that try to explain everything at once but a gentle intro into the world of testing.

34.png

Share this blog:

twitter logo
facebook logo
linkedin logo
link logo

Why should you test your front end code - you might ask at this point? The probable answer to that question is that client wants tests. The more technical answers is that tests help you write more consistent code that works as intended. It makes your codebase robust and less buggy, helps you maintain the codebase and makes the introduction of new developers to the codebase a much simpler and seamless experience.

How?

Preferred practice of writing test is what’s being called Test driven development or TDD, but I don’t care either way how you do it, the important thing is to write them. I think the following wiki definition will be clear enough, and will also explain why this approach will not work every time and for every project.

Test-driven development (TDD)  is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the code is improved so that the tests pass. This is opposed to software development that allows code to be added that is not proven to meet requirements.

My goal here is to simply start you on this path so we will keep things simple and will write simple basic tests for simple basic functions.

Types of test?

Unit tests, acceptance tests, integration tests, end to end tests, component tests, service tests… There’s probably more and some of them can be hard to define, but we will stick with the three types that I think fairly well sum up the testing scenario for the modern web app developer. Unit, integration and end to end test or E2E tests.

There can be a bit of confusion when trying to define each of the types as people have different opinions, so I will keep things simple in that regard and copy some definitions from the wiki and expand a bit with code and more explanation.

How to begin?

You need tools to write tests, tools like test runners, assertion libraries and testing frameworks. There’s plenty of those around and you probably heard some of the names like Jest, Mocha, Chai, Cypress.

It can be hard to choose one so we won’t be doing that at all and will actually write our own test runner and assertion library. It will be a very simple one but will give you a greater overview of how testing actually works.

Help?

Relax, take a deep breath and just copy and paste.

We have a simple function called sum and all it does is it takes two numbers and returns their sum. Let’s say we want to unit test that function.

How would we write a library that tests that function and what we have to do to test that function? So we expect that function to return us the sum of values we passed in. So we will have a result and an expectation.

const result=sum(4, 2)
expected=6 

Now we just have to compare those values and see if they fail or pass our test.

 If (value !==expected){
     throw new Error(´${result} is not equal´)
 } else{
     console.log(´${result} OK´)
 }

This is the core of every unit test, expecting the result to be correct. Every testing lib has its own expect method, so, let’s write our own.

const result=sum(6, 9)
 expected=12
 expect(result).toBe(expected)


 function expect (value){
     return{
         toBe(expected){
             if (value !==expected){
                 throw new Error(´${value} is not equal to ${expected}´)
             }
         }
     }
 }

Let’s write a function called test that takes a title so we know what this test is for and a callback function that will actually contain the test.

 function test (tile, callback){
     try{
         callback()
         console.log(´OK, ${title}´)
     } catch{
         console.error(´Fail, ${title}´)
     }
 }
 

 test(‘sum function returns proper value ’, ()=>{
     const result=sum (11, 4)
     expected=15
     expect(result).toBe(expected)
 })

Our test function is a pretty basic test runner while our expect function is an equally basic assertion library, but hopefully gives you much more insight into why and how testing actually works. These were also some very basic unit tests, it’s time to move to …

E2E testing

So far we’ve learned about the basics of testing and we covered one type of test - unit test, where we test single isolated parts of code. In this section we will discuss the opposite part of the testing spectrum called End to end or E2E testing for short.

The End to End testing is an approach in which we test a fully working application. By doing so, we can test whether our app behaves correctly in a certain scenario from start to finish. By performing tests using many different parts of our application working together, we can test real-life situations. This is very helpful when we want to make sure that our application meets the requirements.

You can think of the E2E test as robot AI that mimics user interaction with your application. Let’s say you have a login form where you have to input your email and password, and then click on a sign in button. From there if your inputs have passed validation requirements you should be logged in and rerouted to /dashboard. Running this test would start the browser and automagically run the written scenario all by itself.

By now, the core idea of writing tests is starting to emerge, automation. Writing more tests helps you reduce your time spent manually testing your application.

How many E2E tests should I write, you may ask at this point. While the answer really depends on the size of the project and the number of unit and integration test previously written. Having enough unit and integration test can mean you don’t need too many E2E tests. One other reason that you should not have too many E2E tests is speed. E2E tests can be slow, having tens or hundreds of them like you would have unit and integration tests will take a lot of time. It’s hard to give a definitive number for this question so I guess the best answer would be not too many. Speed is imperative, tests should be fast so maybe just keep that in mind. Test wisely!

Integration testing

Integration testing is used to test a group of individual modules, components or piece of units. The main purpose of Integration testing is to find bugs when two or more modules are integrated. To check how two or more modules, components or a different piece of code will work together. If unit tests are defined by testing the smallest units of code in isolation, then integration tests are just the opposite. Integration tests are used to test multiple, bigger units (components) in interaction, and can sometimes even span multiple systems. The purpose of integration tests is to find bugs in the connections and dependencies between various components.

While unit tests help ensure that functions are properly written, integration tests help ensure that the system is working properly as a whole. So both unit tests and integration tests each serve their own complementary purpose, and both are essential to a comprehensive testing approach.

Almost there!

A bicycle would be a good analogy for these three types of test. Your unit test makes sure that the individual pieces are working, a wheel for example. Integration test would then ensure that the wheel and the fork are working together as they should, and the E2E is there to make sure that the whole bike gets you from A to B.

So a TLDR;

Tests are awesome, your code will be better, write them!

Share this blog:

twitter logo
facebook logo
linkedin logo
link logo

Subscribe to our newsletter

We send bi-weekly blogs on design, technology and business topics.

Job application illustration

You could use our expertise?

Let's work together.