Did you know that there's an easy way to add quality, speed, reliability, documentation, and long-term value to your software? These three automated tests give you the feedback you need.

"If a software doesn’t work as expected, it doesn’t matter how beautiful or fast it is.” That's a good rule of thumb to live by, but how can developers ensure they follow it? The answer is simple: automated tests. 

Why Do Automated Tests Matter?

Automated tests are programs that automate the task of testing your software, and they matter because they give developers quick feedback on errors. They interface with applications to perform actions and compare the actual result with the expected output you've previously defined. Thus, automated tests enable fast error feedback on the code developed, making the development process more reliable. In other words, developers can see errors quickly and fix them before software goes to production.

Automated testing is also useful when integrating new features into your software. When the integration of features is being done, the written tests can ascertain which parts of the software will break after the integration. Otherwise, if the tests are done manually, the team would need to test the integration at least three times: in a new feature created, in an old feature integrated, and in between both parts.

Testing manually is not only time consuming, but it's also error-prone. After all, the tester would have to follow the same user path manually without making any mistakes to ensure that the integration is a success.

So, developing an application driven by automated tests can provide many benefits, including:

  1. Quality control: we know what to expect from the software’s behavior.
  2. Clear documentation: well-written tests are a good way to document software features.
  3. Long-term value: even if you have to expend more effort up front to develop automated tests, you'll gain long-term dividends. 
  4. Time back: the more the tests are run, the more time they save you.
  5. Energy back: the longer the lifecycle of a project, the more important automated tests become. 

There are many ways to classify tests, but the following three suggestions provide a solid framework for dividing your tests into separate categories:

Unit Tests

Unit tests are the smallest portion of a test that can be written. The main goal of these tests is to create a formal and official registry of the code as a live document. Instead of having to register the code elsewhere, you can register the code documentation as tests. Thus, you don't need to explain how the code works in another document other than the test suites themselves.

Unit tests can only test part of the application and should not have broad coverage. Thus, they are recurrent and frequent.

Unit tests can also test individual functionalities in the software. They are very quick to run and can run many times during the development of a function. They are easy to understand, cheap to develop, and quick to update and run.

Integration Tests

Integration tests verify the observable behavior and the integration between multiple functions. Thus, they offer broader coverage and are run less frequently. They guarantee adequate usage of third-party libraries and check whether the unit being tested performs the expected functionality.

Integration tests take more time to run (a few seconds). They are "medium-sized" tests and cost a little bit more to develop.

E2E (End-to-End) Tests 

E2E tests verify the whole feature in the same way that a user would experience the application. They should be run when a feature is completed, as they check whether or not the feature is correct. They are more expensive to develop, take a long time to run, and are run fewer times during the project lifecycle.

A Few Things to Keep in Mind
  1. Tests cannot tell you if your software works, they can only prove that it doesn’t.
  2. Not using automated tests will make you write too much code before checking that the feature works.

So, let’s take a look at how to write tests on the frontend using a popular framework like react.js.

Testing React.JS with Jest and Enzyme

In this example, we are going to use Jest and Enzyme together with React.js:

  1. React.JS is a Javascript library that is very popular to use on the frontend side of web browsers and mobile applications.
  2. Jest is a Javascript-based test runner and can run fast tests in parallel. It can run in watch mode and run tests every time files are changed. It also generates code coverage reports that help us understand the test passing percentage. Snapshot testing is another great feature in Jest. As its name suggests, Snapshot allows components to be tested by taking a snapshot of what the component should look like internally once it has been rendered.
  3. Enzyme is a Javascript testing utility for React, developed by Airbnb, which makes React component testing much easier.  
Setup and Install

In the terminal or command prompt, install the following dependencies to your existing create-react-app project.

npm install enzyme enzyme-adapter-react-16 enzyme-to-json --save-dev

or using yarn

yarn add enzyme enzyme-adapter-react-16 react-test-renderer enzyme-to-json --dev 

Please note: If you created your app using create-react-app, you don’t need to install Jest. It already comes installed by default.

Configuration

Next, let’s configure Jest and Enzyme to work together with React.

In the src/ directory, create a new file called setupTests.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

In the package.json file, add the following Jest configuration:

"jest": {
  "snapshotSerializers": ["enzyme-to-json/serializer"],
  "collectCoverageFrom": ["src/**/*.js", "!src/index.js"],
  "coverageReporters": ["text"]
}

enzyme-to-json helps make Snapshot tests more readable; by adding it to the snapshotSerializers, it is automatically applied to each Snapshot test via the configuration above.

collectCoverageFrom indicates which set of files coverage information should be collected for. In our case, we have restricted Jest to run on all files with the .js extension except src/index.js, as it is usually just boilerplate code, which doesn’t need to be tested.

coverageReporters tells Jest to output the coverage report via terminal instead of creating an HTML page to display these results. As a developer, it is much easier to check the terminal to understand where you stand in terms of test coverage.

Creating a Test

Let’s say we have a component called DefaultText.js

import React from 'react';


const DefaultText = ({ children }) => (
  <h1>{children}</h1>
);

export default DefaultText;

To create our first test, we will create a new file called DefaultText.test.js; this will be collocated next to the DefaultText.js  component file.

import React from 'react';
import { shallow } from 'enzyme';
import DefaultText from './DefaultText';

const title = 'Test DefaultText';

let wrapped = shallow(<DefaultText>{title}</DefaultText>);


describe('DefaultText', () => {
  it('should render the DefaultText Component accordingly, () => { 
expect(wrapped).toMatchSnapshot();
  });  it('renders the DefaultTexts children component', () => {
expect(wrapped.find('h1').text()).toEqual(title);
  });
});

The first block will create a new snapshot of the DefaultText component.

The second block will do an assertion to check if the value in h1 is equal to the variable named title, which stores ‘Test DefaultText’. If true, the test will pass.

Running the Test

Type npm test in the root directory of your project via cmd/terminal. This will run all the test files in the CRA project and output the results to the terminal/cmd.

Results

Run npm test --watchAll --coverageReport  to generate a code coverage report. This report will show in-depth information about each file, including statement, branch, functions, and line coverage percentage.

I hope you enjoyed this practical tour of the three automated tests every developer should know and use. If you use these tests, you can feel confident that your applications are less error prone and that your developing process is stronger, faster, and smarter.


Author

Ricardo Horiguchi

Ricardo Horiguchi is a UI Engineer at Avenue Code. Educated in Business Management and forged in the Technology field, his quest for the best solutions to old problems is what drives him ahead. Ricardo enjoys teaching programming to other people, studying the Japanese language, and playing in a reggae band.


How to Build a Custom Component in VueJS

READ MORE

DApps: The New Generation of Applications

READ MORE

How to Save Time and Effort Using The Test Pyramid

READ MORE