An Introduction to testing for new web developers

Software testing is the process of verifying if a program or its building blocks work as expected.

We do software testing before making a program live.

There are two main approaches to software testing, 

Passive Testing and Active Testing.

Passive Testing is the practice of auditing the generated log files (during run time) to study the program’s behavior at run time.

In Active Testing, we interact directly with a program or the source code to confirm it functions correctly.

We do Active Testing during each phase of the development. 

Let’s see what those levels are.

Unit testing

Unit testing is a testing method to test individual functionalities of a program in isolation – to ensure each small piece is doing its job correctly.

Each unit can be tested several times with different inputs to ensure it returns the expected outputs every time.

Unit tests are in the form of small programs that test different functionalities of a program.

If a modification breaks the code, unit tests will give us instant feedback that something is off.

We write and run the tests with a testing framework.

For instance, if you’re coding in JavaScript, you can use Jasmine or Jest as your testing framework/test runner.

Applications can have hundreds or even thousands of unit tests to ensure every bit in the code is (and will be) doing its job as expected.

Code Coverage or test coverage is a metric (measured in percentage) that tells us how much of the code was exposed to the tests.

If a unit is left untouched during a test, it might carry a bug into the production. That’s the reason developers try to achieve the highest code coverage possible.

Note: Code coverage is a quantitative metric and doesn’t mean you have high-quality tests, though. 

That said, having a high code coverage doesn’t necessarily mean you have high-quality tests.

As a developer, besides your code, you’ll be writing a lot of unit tests too.

Integration testing

Unlike unit testing that examines program units in isolation, integration testing verifies individual units still function when combined.

Like unit testing, integration tests are computer programs written by developers or test engineers.

System testing

System testing is conducted on the entire application to verify it meets both functional and system requirements specified in the design phase.

For instance, testers might simulate user behavior through automated (or manual) tests to ensure the application behaves and responds correctly at run time.

Purpose of testing

In addition to categorizing tests into testing phases, we can also study them based on their purpose.

Regression testing

Regression testing is a system-level test.

Regression testing verifies the existing features are still functioning correctly after a code update.

Code-level testing, including unit testing and integration testing, help us minimize the possible defects detected during regression testing.

Smoke testing

After each code update and running the code-level tests, the developer can do smoke testing.

Smoke testing ensures changes in the code haven’t broken the app and to see if the QA team can proceed with further testing.

Test-driven development (TDD)

Test-Driven Development – a.k.a TDD – is a software development practice, where you write a test first, then write a code to pass that test!

This method helps you write better code as you set an expectation of its output before it even exists.

TDD consists of three steps:

First, you write a test to assert the expected behavior of a piece of functionality you haven’t created yet! 

The functionality won’t pass the test as it would be just an empty container running the test for the first time.

Second, you write code to create that functionality in the most basic form and re-run the test.

Third, once the functionality passes the test, if needed, rewrite the code in a more structured way.

You repeat the above steps for every functionality you want to add.

Let’s go through an example in JavaScript to see TDD in action.

Imagine we need a function that determines if a value is odd or not.

Let’s call it is_odd().

The first step is to write a unit test to test our expected output.

I’ve used Jest to write the following tests (read more about Jest).

First, let’s create an empty is_odd() function:

functions.js

javascript

export const is_odd = function (number) {}

So far the function doesn’t do or return anything; It’s just a placeholder.

Now, let’s write the test:

test.js

javascript

import { is_odd } from ‘functions’

test(‘testing if 5 is odd’, () => {
expect(is_odd(5).toBe(true))
})

test(‘testing if 4 is odd’, () => {
expect(is_odd(1).toBe(false))
})

test(‘testing if 1 is odd’, () => {
expect(is_odd(1).toBe(true))
})

In the above code, we’re testing the return value of the is_odd() function with different inputs.

We write these test cases based on our understanding of the expected output.

For example, we know that numbers five and one are odd, but four is even; We use these assertions to make sure the function behaves as we expect.

These tests will fail anyway as there’s no code written yet, meaning the output of is_odd(x) is undefined.

The next step is to write the code for the is_odd() function and re-run the tests:

functions.js

javascript

export const is_odd = function (number) {
    if (number % 2 === 0) {
        return true
    }
    
    return false
}

Now, if we re-run the tests, all tests will pass.

It means the function returned the correct answers for 5, 1, and 4. 

These tests guarantee the function will return expected values when called with other inputs.

Finally, if there’s room for refactoring the function, we rewrite it in a more structured way; if not, we let it be.

Thanks to these tests, if we make a simple mistake in this function that changes the output, the test will fail, and we’ll know about it instantly.

TDD pushes the developer into the habit of writing clean, testable, and maintainable code.

TDD might be a part of your daily routine as a web developer.

Author photo

Hey 👋 I'm a software engineer, an author, and an open-source contributor. I enjoy helping people (including myself) decode the complex side of technology. I share my findings on Twitter: @lavary_

If you read this far, you can tweet to the author to show them you care. Tweet a Thanks

In this article:

Disclaimer: This post might contain affiliate links. I might receive a commission if a purchase is made. However, it doesn’t change the cost you’ll pay.