TDD or Test-Driven Development is a development approach when you write and run tests on small development integrations. Each iteration aims to develop code that will pass these tests. By following this, you can get a very high level of quality of your code, which is tested automatically. TDD also reduces the likelihood of errors in your tests, which can otherwise be difficult to track down.

The TDD process consists of stages which are presented in the image:

tests

Roles that Tests Play in Continuous Delivery



Sometimes it is difficult to find a way to test because each type of test is unique and has a unique role. You don’t choose between integration tests, functional tests, and unit tests. Use all of them because most applications will require both functional tests and unit tests, and many applications will also require integration tests.

tests

Unit testing is the testing of individual components or functions of a program that verifies that the result of the function is as expected. Unit tests are also great for preventing regression - issues that often occur. Many times there can be a particularly troublesome snippet of code that just breaks no matter how many times you fix it. By adding unit tests to check for specific errors, you can easily prevent such situations. A good set of unit tests not only prevents errors, but also improves code design, and makes sure you can re-invoice the code later without being completely broken. Popular tools for testing devices are Mocha, Jasmine and Tape.

Integration tests are similar to Unit tests. Integration testing is meant to test how component collaboration works and is used when you need to test several separate systems together. Sometimes you need to run tests to make sure that two separate systems - such as a database and a program - work properly together, and this requires an integration test. Integration tests can be written with the same tools as Unit tests.

Functional testing is also sometimes called E2E testing, ensuring that the program works as expected from the user's point of view. Functional testing is defined as testing the full functionality of a particular program. In practice with web applications, this means using a certain tool to automate the browser, which is then used to click on the pages to test the program.

At different phases of development, tests are often used in three ways:

  • During development unit tests should be used to prevent issues in the early stages and validate that each unit of the software code performs as expected.

  • In the staging environment if something goes wrong to detect issues and stop the deploy process.

  • In the production environment functional tests are performed to ensure that no critical functionality has been compromised during the deployment process.

Unit testing is a component of TDD, a pragmatic methodology that applies a careful approach to product creation through continuous testing and auditing. This testing method is also the first level of software testing that is performed before other testing methods, such as integration testing. Test units are usually isolated so that the unit does not rely on any external code or function. The main purpose of testing is to make sure that the code meets the architectural requirements and has the expected behavior.

Unit testing requires testing each module of the program code. The Unit is called the smallest part of the program that can be tested. In procedural programming, a module is considered to be a separate function or procedure. This is an important step in the development process because when you detect code defects in the early stages you will fix them much faster then when you detect bugs in later stages.

How to do Unit Testing?



Unit Testing is of two types:

  1. Manual Testing
  2. Automated Testing

Unit testing is usually automated, but can still be done manually. Manual testing in comparison with automated testing is more tedious, especially for repetitive tests, and requires more effort to create and execute test cases. The advantage is that manual testing does not require knowledge of any testing tool.

The fact is that 100% automation is impossible, and therefore some level of manual testing will always be performed.

For automated testing, you obviously use some automation tools. The automation tool can record and store your test, and it can be played as many times as you want without any further manual intervention. Automation tools imitate user behaviour and check if all goes as expected.

Automated testing requires apparently more effort and cost initially, but it saves you time and budget on later stages.

Unit Testing Automation Tools



Here are a few examples of tools and frameworks that can be used to perform JavaScript Unit Testing.

  1. JASMINE is a user behavior simulator for testing a JavaScript block that allows you to perform test cases similar to the behavior of users on your website. It is used to test both synchronous and asynchronous code. Jasmine is also useful for testing the Internet for visibility, clarity, clicks, and responsiveness of the user interface in different resolutions. It does not require a DOM and comes with a simple syntax that can be written for any test.

  2. JEST is one of the most popular frameworks. Today, Facebook uses Jest to test all JavaScript code. This is the best framework for React-based applications because it requires zero configuration. It is also the only framework suitable for NodeJS, React, VueJS, Angular and other Babel projects. No other configuration settings and libraries required.

  3. AVA is a simple framework for testing a JavaScript block. The tests are performed asynchronously and simultaneously. This gives you almost complete control over what you do. And quite simple Javascript test syntax.

  4. PUPPETEER is a Node.js library that allows you to manage your Chromium browser without the user interface. The tool is quite new. It is mainly used for browser-specific applications, such as scanning tests, testing page structure, screenshots, and even capturing pre-loaded content for one-page applications. Puppeteer also supports ES6 features such as standby and asynchronization, form submission automation, interface testing, and keyboard input.

  5. MochaJS is the most popular test framework that supports backend and frontend testing. MochaJS is a flexible base for test development as needed. It runs asynchronous tests on the Chrome v8 engine or any other browser.

There are many more libraries and frameworks to test, but you'll definitely find a tool to test the units for your programming needs, regardless of the type of project you use or the language you use.

Unit Testing Advantages



  • Issues can be identified at an early stage of development, so even very simple mistakes that are obvious most of the time, but for some reason go unnoticed, can be easily avoided by performing some unit tests.
  • Unit testing allows the programmers to later analyze their code and make sure that the modules work properly.
  • You can read the unit tests to find out what functionality a particular section of code provides and how to use it.
  • If an error occurs when changing the code, it can be quickly identified and corrected.
  • Due to the modular nature of unit testing, we can test parts of a project without waiting for others to complete.

Disadvantages of unit testing



  • Unit testing does not guarantee the detection of every error in the program. It is impossible to estimate all ways of performance even in the most trivial programs.
  • Because Unit Testing focuses on code units so it cannot detect system-wide errors or integration errors.

Unit test example



Consider a simple example of a unit test using Puppeteer framework:

const puppeteer = require('puppeteer');

describe('Login flow', () => {
  test('User Login', async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto("https://example.com");

    // Query selector
    const LOGGED_IN_BUTTON = "#loggedIn_button";
    const USERNAME_INPUT = '#username_input';
    const PASSWORD_INPUT = '#password_input';
    const LOGIN_BUTTON = '#login_button';
    const USER_ICON = '#logedin_user_icon';

    // Login as following registered user
    await page.waitForSelector(LOGGED_IN_BUTTON);
    await page.click(LOGGED_IN_BUTTON);
    await page.waitForSelector(USERNAME_INPUT);
    await page.type(USERNAME_INPUT, "user.name@test.com");
    await page.type(PASSWORD_INPUT, "secretPassword");
    await page.click(LOGIN_BUTTON);
    await page.waitForSelector(USER_ICON);

    await browser.close();
  }, 10000);
});

As we can see from this example the test is for ‘User Login’ functionality.

In this test, we go to a given web page and execute asynchronous set commands, if at any stage something goes wrong then the test fails. Otherwise if the command await page.waitForSelector (USER_ICON) is executed and the browser page is closed, then the test passes successfully. More details about the Puppeteer can be found here.

Conclusion



Test development is not difficult to manage, for this you need to choose test tools that are suitable for your project and consider the process of writing tests in the early stages, without putting them for later.

As you can see, there can be a lot of involvement in unit testing. It can be complex or fairly simple, depending on the testing program and the testing strategies, tools, and philosophy used. Unit testing is always required at some level.