Quality assurance checklist for UX engineers
Our UX Engineers strive to create code that is accessible, performant, and modular based on a detailed list of best practices for our HTML, CSS, and JavaScript. The goal is to balance user experience and developer experience—making sure users enjoy the product while developers also enjoy writing code for the product.
While traditional quality assurance (QA) in software development consists of validating design and functionality against specs and mockups for great UX, we also use a QA checklist while authoring code to enhance the experience for developers.
This list is a subset of the items currently included in the Think Company Front-End Web Development Standards. It’s been assembled over time with contributions from many Thinkers and continues to change with new technologies, tooling, and approaches.
If you’re a developer or UX engineer looking to write your best code possible while anticipating user and developer needs, use this list as a guide while you’re working or while checking your work.
What is a QA checklist for UI/UX engineers?
A QA Checklist for UI/UX Engineers is a tool that ensures that the code that you are writing is compliant, accessible, performant, and secure for your users and maintainable and readable for other developers. Traditional QA focuses on output while this checklist focuses on the code as it is written. This list is a combination of items you should do throughout the project lifecycle—some may be a one time check point at the beginning and end of the project while other checks are done frequently throughout the duration of a project.
QA checklist for UI/UX engineers
A good QA process for UI/UX Engineers should cover a handful of overarching best practices. We’ll go over:
Standards compliance
There are many best practices and standards in the software development industry. Some items are related to style preferences—coding style, organization, naming conventions—while others are related to specific language or framework compliance. Validating that you are sticking to these standards will give your projects structure and predictability to help with long-term maintenance.
1. Write code according to your team (or client’s desired) standards
We generally follow our team standards, but sometimes our clients have their own standards for code quality, naming conventions, and directory structure. There is no right or wrong when it comes to standards, but they are a great tool for ensuring your code is organized and well written, and especially important when working on a project with multiple contributors.
Don’t have standards of your own to follow? Many companies make their standards public and are a great starting point for finding a guide that works for you. We even based our standards around earlier versions of AirBnb standards.
2. Follow the conventions of the frameworks and libraries included in the project
When you are using a framework or library, it is a good practice to follow its accepted standards and conventions. Deviating from standards outlined by a 3rd party can lead to issues down the road, especially when upgrading or updating your code. Libraries like React have some great documentation to help you understand what you should and should not be doing.
3. Document custom functions
Whether the code you are writing is something you are handing off to another group of developers or something you may come back to later down the line, providing adequate commenting, especially in complex custom functions, can make everyone’s life much easier. Function comment blocks, inline comments explaining gotchas, or even documenting choices for a solution can go a long way for future developers (or you!) who may be tasked with updating your code.
4. Verify that all code follows the DRY principle
A very common principle in writing any code, look for opportunities to keep your code DRY (don’t repeat yourself). Looking at your code again after you’ve completed a major milestone or feature should help you identify any opportunities to refactor code to be DRY.
5. Validate and/or lint HTML, CSS, and JavaScript
Make sure to validate HTML and CSS according to W3C Specifications. Using linters is a great way to ensure the code you are writing code that is both valid and up to snuff with your standards. Some of the linters we use include HTMLHint, Sass Lint, or CSS (CSSLint) and we set up a custom ESLint configuration for JavaScript.
Many text editors have plugins that can be configured to give some immediate feedback from the linters. You can also set up task runners to help run the linters at different points in the development cycle.
Accessibility
Accessibility and inclusion is a must have for all of our work. While we may do more extensive testing in our QA phases, it is important to think about accessibility and inclusion up front while coding to enhance the experience for all users and prevent major refactors down the line.
1. Verify basic keyboard accessibility
Use your keyboard to navigate through content to ensure it is in a logical order and that you can interact with all UI elements. Make sure the active focused element is clearly indicated at all times when navigating the site with the keyboard. WebAIM’s Keyboard Accessibility recommendations is a great resource to understand keyboard testing.
2. Perform manual and automated accessibility testing on compiled HTML
The aXe browser extension for Chrome or Firefox is our go to for this type of testing. It is also available as a library that integrates with automated testing scripts.
3. Perform manual and automated color accessibility testing
Certain combinations of colors are difficult to see for people with various visual disabilities. You may be able to identify obvious instances of this at a glance, but you should also use automated processes (like the aXe browser extension!) to find the rest.
4. Test manually with screen readers
Ensure that the site’s content is announced correctly and can be navigated using screen readers. We use NVDA (with Firefox) and/or JAWS (with Internet Explorer or Edge) on Windows or VoiceOver on Mac as the primary tools for this testing.
5. Ensure appropriate use of ARIA attributes
Use ARIA attributes as needed to support, but not replace, semantic HTML. ARIA is particularly helpful in support of dynamic content and advanced UI controls. See Using WAI-ARIA in HTML for more information.
Browser compatibility
Browser makers sometimes implement different standards and support for new and existing web technologies. It is important to test your application on multiple devices, operating systems, and browsers. This helps to ensure the same experience regardless of the device someone is using.
1. Review the browser support requirements for your project
Make sure the browser/operating system requirements are clearly defined for your project, and follow them when coding and testing.
Not sure what browsers you should be supporting? We generally recommend the latest version of modern browsers for desktop (Chrome, Firefox, Safari, and Edge) and mobile Safari and Chrome. Analytics tools like Google Analytics can give you a good idea of the browsers people use most when visiting your website which can also help you determine which browsers to support.
2. Test on native devices when possible
When available, test on native devices with as many of the required browser/operating systems as possible. Testing on real devices generally yields more accurate results than simulators.
When native device testing isn’t possible, we use Browserstack which allows us to test additional device, OS, and browser combinations.
3. Run visual and functional regression testing
Visual regression and functional testing is an important piece of the testing process to verify that changes do not have any unintended consequences. Visual regression testing compares changes visually to past versions to ensure every change you’ve made is intentional. Functional regression testing works similarly by testing certain interactions a user may perform and making sure the intended functionality occurs.
Both visual and functional regression testing can be supported with automation tools to make the process more efficient and repeatable.
4. Verify appropriate image formats, according to browser support
Not all image formats, e.g. WebP, work in all browsers. Make sure the format you choose works across the browsers you need to support. Caniuse.com is a great tool to use to identify what will and won’t work in certain browsers.
Performance
No one likes a slow website. In fact, a slow website can cost a company a lot of money. Performance tuning is important, and there are a lot of ways you can achieve (or hinder) it.
1. Verify that all images/graphics are optimized
Media assets can contain extra metadata and file information that isn’t necessary. Use the proper tools to remove that data and compress the file down as much as possible. Raster images may require creative direction to meet visual needs and performance budgets.
Whenever possible, image compression should be part of a project’s build process to ensure that all files have been optimized. Tools such as ImageOptim for compressing raster images and SVGO for compressing SVG vector files can be integrated into a build process or used on their own.
2. Remove unused font weights and character sets from web fonts to conserve bandwidth and eliminate FOUT
Large webfont payloads, especially Google Font API calls, can cause flashing of unstyled text (FOUT). Remove any unused font weights and character sets from their source.
Also consider font loading tools that provide more control over how webfonts are loaded on the page.
3. Minimize additional or unused HTTP requests
Browsers can only handle so many requests at a time; the more requests a website has to make, the longer it can take to load. Make sure you are not requesting resources when they are not needed. For example, if you are using a WordPress plugin like Gravity Forms, dequeue the scripts it uses except for the page it is called on.
4. Concatenate and minify text-based assets (JavaScript, CSS, etc.)
To help reduce the number and size of HTTP calls, use build tools to concatenate and minify your code. This can be further improved by using a server side compression algorithm like GZIP to reduce file size before being sent to the client.
Use build tools like Sass, Browserify, and Webpack to compile and concatenate source files, and tools like UglifyJS to minify your source code.
5. Choose the most efficient SVG icon system approach
Consider the most appropriate approach for SVG icon systems (inline, background, sprites). Some of the things to consider when deciding include project requirements, browser support, accessibility, performance, and maintenance. This post from CSS-Tricks is a great round up of options with details about implementation.
6. Run automated performance tests
Automating performance testing done with tools like Louis will help identify changes that affect performance during development.
7. Perform manual tests on key pages with performance testing tools, document before and after results
Performance testing tools that show key metrics such as “time to first byte” along a visual representation of the page load process (e.g. WebPageTest, Google PageSpeed, Chrome Dev Tools film strip), can help identify areas that need further optimization. These tools can also point out code that causes poor performance by triggering excessive CPU/painting cycles that can have a negative impact on performance.
8. Implement CDN (if applicable)
If applicable, use a Content Delivery Network (CDN) for loading a website’s assets. CDNs reduce the physical location between users and servers, reducing the amount of time it takes to load assets. Typically this will be necessary on larger high traffic websites.
Security
Security is extremely important. As a UI Engineer, there are items specific to the front end that you should look out for to prevent your site or application from being vulnerable.Take steps to provide safeguards against basic hacks like SQL injections, remote file inclusion, XSS (cross-site scripting), and CSRF (cross-site request forgery).
1. Secure input and output handling
When handling data that is sent to or from an application, it is important to secure it. This means checking to make sure data that is going into the system is safe, secure, and valid, while also ensuring that the data sent from the system meets that criteria as well. OWASP has guides for input validation and data validation.
2. Do not include sensitive environment information or credentials in project documents or codebase
Keep sensitive information like logins, user data, etc. where it can be secured. Should a password accidentally find its way into version control, remove it from the repository’s history.
3. Set least privileged access
Only people who need access to data, login information, etc. should have access to it. Avoid including MySQL root passwords in company-wide “reply-all” email threads.
4. Set minimum folder and file permissions
Make sure that folders and files have the lowest permissions necessary to run. This will help mitigate remote file inclusions, directory traversal attacks, and jailbreaking.
5. Remove unused code
Unused code is still vulnerable code. This is especially true with PHP. Most WordPress, Drupal, and Joomla hacks come from plugins that are deactivated but can still be exploited.
6. Remove metadata from SVG
Metadata will be removed during the image optimization process for SVGs that we create. Any process that allows user SVG uploads should verify that no vulnerabilities are allowed.
7. Check code against OWASP standards and best practices
OWASP is a great resource for how to secure code. Review your code and compare it to their standards and best practices.
Codebase integrity
Whether we are creating code that our team maintains or handing that code off to other developers to integrate, codebase integrity helps keep our repositories and code clean, easy to understand, and dead simple for anyone to pick up and start coding with. The more developers working in a project, the more important code integrity becomes.
1. Remove unused assets and scripts from the project
During the lifecycle of a project, a codebase can go through many iterations of adding and removing assets and functionality. It is a good practice to occasionally prune your project of unused assets and scripts, especially after large refactors of existing features.
There are also certain files that should never be in a repository. Rendered/compiled files, user generated content, and extremely large images and videos are some examples.
2. Verify that all dependencies are included, and unused dependencies are removed
If a project cannot run correctly without certain libraries or assets, make sure they are included. Never have a dependency that exists in your local development environment but not in the repository.
Note that installed packages should not be included in your repository. For example, we do not store node_modules in the repo, only the package.json file that references the modules.
3. Verify that the file/directory structure is clear and consistent
Make sure files and folders follow standard naming conventions, are consistent, and match the content inside of them. For example, a js folder will only contain JavaScript files and a file called modal.js will only contain JavaScript for a modal.
4. Verify that the project README is complete, and current
Ensure that the project README file is always current and contains all of the information that a developer needs to get up and running. Include things like prerequisites, build/installation steps, and deployment instructions.
Produce better code over time
There is a lot to take in here, but a lot of these items have become a pretty natural part of our authoring process over time. If you are feeling overwhelmed, pick a few areas of focus that align with your project needs before adopting too many new things at once—something is better than nothing. Make sure to use automated tools where you can to help catch things along the way.
As you get more comfortable with incorporating these steps into your process, you’ll produce and advocate for higher-quality code over time.
We’re passionate about development standards and practices. If you need support evaluating your approach to QA or auditing your existing site, contact us.