Front-End Architecture: Tests

Caio Vaccaro
The Startup
Published in
8 min readSep 20, 2020

I am starting a series of articles on architecture of projects, especially Front-End. The posts will have an emphasis on explaining everything “in English”, without so much code. Perhaps, in another moment, the practical part will come up in a series of videos. I will post the texts based on a list of several subjects, from folders and files to versioning, continuous integration and DevOps, not necessarily in that order — and, in the end, I will get everything together in an ordered list. For now, I decided to start with Tests. Leave your suggestions in the comments. :)

Before starting, it is important to remember the existence of a universe of Formatters and Linters, but I prefer to leave them for an article on standards, where we can talk about the choices that are the reason for which linters exists: reinforce patterns, either by convention, security or whatever technical reasons.

We will talk about:

  • Unit
  • Integration
  • End-to-end
  • Regression

Each of these will be structured with:

  • What it is
  • When to use it
  • Pros
  • Cons
  • Tools

Unit

What it is

As the name says, it refers to the units, and, as the word suggest, it means that it is something that cannot be divided, since it is the smallest possible part. When referring to software, it means that they are functions that only do one thing. Unit tests are responsible for attesting that such functions (or units) are behaving properly. As we are talking about Front-End, these functions are written in Javascript or any other language that compiles to it.

Whether using the TDD process or not, it is difficult for a developer to take into account all possible scenarios, especially when programming such functions. Writing unit tests can help you to prepare your code for situations that are not “optimal”. In addition, they can make sure that during the life of the project, the “little guys” (unit tests) will complain before you notice such errors, in case something goes out of the established format or architecture,. By writing them, you are creating an army of robots with a life of their own, whose only mission is to observe their functions and ensure that they are correct.

An example, in the case of a function that formats dates, would be to guarantee the outputs, for practically all types of input — which happens when someone uses a date in different formats, invalid dates, and so on, including how the function handles errors and exceptions.

When to use it

  • The project has a considerable amount of logic
  • There are many functions that are reused in many places
  • You have a business rule or a code that is crucial to the success of how the business flow goes
  • It is a product or project with a long life
  • It is an open-source project with contributors

Note: How can you tell when it’s a logic code or not? Logic, most of the time, is pure Javascript — that is, if you are accessing the DOM, changing classes or animating, this is already the consequence of logic, or, in other words, it is a side effect of a decision. Usually, logical functions are composed of conditionals (if-else, switch) and loops.

Pros

  • Bugs are found faster
  • Run-time errors are treated preventively
  • More confidence in deploys
  • It makes it easier the use of refactor (rewriting functions while keeping the same inputs and outputs)

Cons

  • More time spent in developing
  • More time spent with the project
  • It is difficult to rewrite. Unlike the refactor, if a function or module has been poorly designed and needs to be redone, the test will need to be rewritten as well

Tools

Coverage

This is a controversial point. When using unit tests as a synonym for more stability and security, it is very common to compromise or require some “coverage”, usually measured in percentage. At first, the more of your Javascript files, functions, lines, conditions — in short, the more operation is covered by tests, the better. But there is “too much testing”. A happy medium would be to manually choose critical files, with a business rule or logic, and measure their coverage, instead of doing that with all files.

Integration

What is it

There are a lot of gifs on the internet exemplifying the difference between unit and integration tests. It basically means testing units together. While in unit tests it is often necessary to mock (simulate data locally, removing the need for external integrations) parameters, data and dependencies, in the integration test the “real units” are used as much as possible.

Here’s an example, in the case of dates. You would probably have at least one function to format dates and another to format time (hours of the day). And here’s the question: would a simple integration test be sufficient to verify what would happen, for example, if the date and time formats are different — even if the date and time formatting works in isolation? Will the output be the date in the format of a specific country and will the time be in the format of another one — or is that an exception?

When to use it

The word “integration” in this context means a lot. Basically, these tests aim to answer the question that still remains: how do two units tested together work together? However, in this case, unity can have several meanings:

  • To test two or more functions, when one is used by the other and the unit test was solved by the mock
  • To test functions or modules that use external dependencies (like NPM packages) and the unit test was solved by mock
  • To connect APIs or external services to tests that were previously mocked
  • On microservice architectures, to test functions or modules from different repositories that work together

Pros

  • It provides you even more security in the application, mainly as a validation before deploying
  • It quickly warns you of any failures as a result of a refactor, either from your own code or from the others, which otherwise might only be caught in production

Cons

  • Depending on the stack and the architecture of the project, it might take some considerable setup time, specially when provisioning instances in the cloud, including setup and teardown services
  • It can be slow, increasing the build time considerably

Tools

The same as for unit tests, but depending on the architecture of the project you may need to run a browser to access some specific functionalities.

End-to-end

What is it

It is what the name says: “from end to end”. We are talking about “applications”, which have data, logic and interface, so “end-to-end” tests must encompass all three. They are focused on the interface as a way to automatically test behaviors, interactions and flows, whether they contain data and logic or not.

An example: through this option, it would be to possible to automate an interface test in which the user accesses a calendar and chooses dates, and in another column he/she would be able to choose the hours of the day, attesting that the correct options are shown, that the success and error messages appear and so on.

When to use it

Whenever you and your team find yourselves performing the same interface test dozens of times and there is time to schedule automated tests. The most important question that defines whether this is the case or not is: how long will these tests continue to be done, or how long will this project take? If the answer is at least a few months, it is certainly the case.

Pros

  • It shortens considerably the time you spend doing manual tests
  • If configured correctly, it makes it easier to find cross-browser divergences

Cons

  • It demands considerable time to schedule tests
  • Drivers, browsers headless and different browsers have an unstable behavior when it comes to automated tests, leading to many exceptions that must be skipped and retested manually

Tools

Regression

What is it

All integration and end-to-end (unit) tests have much more value when monitored over time. It is possible to configure them to use a log that clearly shows what has been successful or failed. If you are on a well-structured project, it is possible that there are dedicated QA professionals — and, in this case, they are probably doing exploratory manual tests as well, and writing down the test results over time.

While the uses mentioned above focus primarily on the layer of data and the logic of an application, there is another use, perhaps one of the most useful for large-scale projects. For example, to observe automatically the interface differences during the lifetime of a product or project, using past references. This is extremely useful in a project with hundreds or thousands of pages, since it would take several days or weeks to certify that everything is okay if you check it manually. So it is valid to use regression testing.

When to use it

In complex software where there is a well-used design system, that is, a component system with some consistent design rules. In such systems, it is possible to infer through automated scripts that changes that are poorly made in design are likely to be a break in the design system. In addition, it is possible to have too many pages to remember, especially when considering all multiple releases and timelines.

Pros

  • It can help you to ensure that new releases conform to the previous ones that were successful.

Cons

  • It requires end-to-end testing to be effective.
  • It requires considerable setup time.
  • Depending on your compatibility matrix, it may not remove the need for excessive manual testing.
  • There is no perfect solution yet, since it’s problematic to deal with responsiveness, threshold proportionality and screenshots of all possible interactions.

Tools

Note: In addition to the tests mentioned above, there are also specific test tools for you to use with a framework, such as Protractor from Angular and Enzyme for React.

Tests are a whole different world and there are many new challenges. It is a very old and popular subject in software development, mainly in the Back-End, but it is recent in the Front-End debate, especially in Brazil. More and more companies request this knowledge, even though it is still very rare! Thus, it is a good way for you to stand out in the job market.

If you are interested and don’t know where to start, send me a message on Linkedin, I will be happy to help you with content references.

The Gods of Olympus, trompe l’oeil ceiling from the Sala dei Giganti, 1528 (fresco) by Romano, Giulio (1492–1546)

--

--