CSS Testing: The Definitive Guide

CSS is an essential component in front-end web development. But in the past, automated CSS testing didn't get the same…

Testim
By Testim,

CSS is an essential component in front-end web development. But in the past, automated CSS testing didn’t get the same attention as testing JavaScript. Now that front-end development involves ever-more-complicated systems for writing and using CSS, its testing has transformed from a niche to a necessity.

This guide aims to demystify the rapidly changing world of CSS testing. You’ll get a high-level view of what CSS testing entails and what it can do for your testing workflow.

What Is CSS Testing?

CSS testing is part of front-end testing. It overlaps with other types of front-end testing. It’s rare to test CSS in isolation, mainly because setups where CSS interacts with and mixes with JavaScript are increasingly common. Accordingly, CSS testing involves scripting languages (such as SASS, Less, and so on) and framework code (React, Vue, etc.) and the final application in the browser.

Let’s look at a React render example from the React documentation. The component’s CSS class name is set through a conditional. If the prop isActive is true, the component gets the class menu-active.

render() {
  let className = 'menu';
  if (this.props.isActive) {
    className += ' menu-active';
  }
  return <span className={className}>Menu</span>
}

A high-coverage CSS testing strategy might test these issues:

  • Does the rendered component have the correct class when isActive is true?
  • Are the CSS properties (width, height, etc.) correct on the rendered component?
  • Does the rendered component meet visual requirements in the final application?
  • When a user is in a section of a webpage, is the active section of the menu styled correctly?

What Are the Benefits of CSS Testing?

CSS testing aims to catch potential bugs and encourage quality code. As the example above illustrates, CSS can be part of all stages of development with other CSS and with JavaScript, making it impossible to test manually.

Benefit 1: Save Time

Good CSS testing saves a developer’s time. Imagine you’re a developer altering some button styles in a React web application. The button is part of dozens of components. Checking them all to make sure the button style changes didn’t cause misalignment could take a long time.

With CSS testing, the developer can run a test suite that looks at how changes affect different parts of the system, such as components. This helps prevent code from causing unexpected or unintended changes.

Benefit 2: Make It Easier to Be Consistent

CSS testing can also maintain team cohesion based on agreed-on best practices such as indentation, naming, and nesting depth. When tests catch these issues, code reviewers don’t have to pick through the code looking for them.

CSS Testing Types

There have been many proposed categorizations for CSS testing. I’ve divided them into the stages of the codebase. We’ll move from the styling code to how it performs in the final application.

Testing Styles

At the styling stage, developers set the styles. This can be through CSS or languages that compile to CSS, such as Sass.

Linting

The practice of linting catches basic syntax errors, such as misspellings of property names or missing semicolons after a property. One example is a misspelling like wdith: 100. It’s also common to use this practice to enforce mutually agreed-on standards, such as indention type and naming format. Common CSS linters include CSS Lint and Stylelint.

Quality

CSS quality tools analyze the entire codebase for overall quality. A tool like Project Wallace can analyze CSS for complexity. This can help a team root out CSS code that’s difficult to read and debug.

For example, a project may have hundreds of unique font sizes. Combining them into a smaller number of standardized styles helps reduce the difficulty of typesetting.

Other quality tools like PurifyCSS identify unused CSS, which can be removed to improve performance.

Testing Interactions Between Styles and Other Code

When working with so many moving parts, it’s critical to ensure the correct CSS ends up in the right place. This testing stage involves the interactions between different styles and between the styles and other code, such as JavaScript.

Snapshot Testing

Snapshot tests compare diffs of rendered code, typically a component. A test contains the intended correct code. Then any new code is compared against it, checking for unintended changes. Jest is the most popular tool for snapshot tests.

Unit Testing

Unit tests look at the properties of the rendered code instead of the rendered code itself. In The case against React snapshot testing, Ben Jackson describes using the jest-emotion library for the “it applies some CSS rules” test, which can check the values of CSS properties.

Testing the Rendered Application

Next is the rendered application as a whole. That’s the final result of the build deployed into production.

Visual Regression Testing

Visual regression is one of the most popular types of CSS testing. Tools like Percy and BackstopJS capture pictures of components. When new code comes through, they take pictures of the components again. Then they compare these to the previous pictures. If they’re different, this difference may trigger an alert so a developer can review the details.

HTML Validation

Similar to the Jest snapshot testing, but on the final HTML itself, is Testim’s Validate HTML attribute. For example, if you want buttons on a particular page to have the .button-large class, you can check to make sure that’s present.

CSS Property Validation

This is similar to the unit testing described above, but it usually acts on the final build rather than parts of the code. This is especially important when working with complicated items with multiple classes setting the same properties. Testim’s Validate CSS Property test can get all the properties of an element and ensure they have the intended values.

Cross-Browser Testing

Cross-browser testing examines the application in different devices and popular browsers, such as Chrome, Safari, and Mobile Safari. People used to do this manually. But now, many other tools like Testim can run tests on multiple browsers.

Performance Testing

Performance tools like Lighthouse can check for performance issues that CSS can cause. A typical example is render-blocking CSS, which can cause a loaded webpage to look unstyled when first loaded.

Accessibility Testing

CSS is part of meeting accessibility standards. These ensure that people using assistive technology can access your site. This issue can get complicated.

For example, what if the application consists of many elements with different color combinations and different stages of user interaction? These color combinations need to be accessible for people with color blindness or trouble reading poorly contrasted text.

Tests like Testim’s Accessibility Validations can examine the elements to make sure they meet such standards.

End-to-End Testing

End-to-end (E2E) testing aims to simulate the user experience through automation. This typically involves the tools mentioned in the previous section running alongside certain simulated user actions, such as clicking, hovering, typing, and so on.

For example, an E2E test in Testim could simulate a user scrolling down a page, hovering over a button, and clicking the button. The intended functionality might be for the button to have a different visual design at each stage. So at each stage, you could test for:

Challenges

CSS testing is a real challenge, often requiring a lot of time and effort. To create a successful E2E test, for example, the developer must simulate the actions of the fake user on a fake website. These include actions like clicking a button, of course. But they also include conditions of the web, such as waiting for the page to load before acting.

Writing such automation for tools like Selenium or Puppeteer often involves quite a lot of coding. Luckily, there are a growing number of low-code tools, like Testim, where you can record the actions required for the test.

Selecting the proper element to examine is a considerable challenge with dynamic classes and scoped CSS. Fortunately, new tools like smart selectors from Testim can target elements using machine learning rather than class names.

Another common complaint is the work required to update and maintain tests. Snapshot tests and visual regression tests often require a significant amount of setup. Also, they run slowly and are likely to need lots of manual updates as the code changes. It’s critical to design them as carefully as possible so changes that aren’t relevant (such as copy changes) don’t cause test failures.

Refactoring some snapshot tests to unit tests and adjusting the sensitivity of visual regression tests can help mitigate these issues. Another option is a living style guide containing components with boilerplate content. This isolates their design from the dynamic content of the web application.

CSS Testing Is for Everyone

CSS testing solves so many challenges of front-end development. In the past, it was hard to get started, given the difficulty of writing tests. Now that there are an increasing number of user-friendly testing tools, the barrier to testing CSS has gotten lower.

If you’re looking for a user-friendly testing tool for E2E testing, check out Testim.

What to read next

A Deep Dive Into CSS Testing: A Developer&#8217;s Complete Guide

XPath vs. CSS Selector: The Difference and How to Choose