Spark Joy by Running Fewer Tests

Jessica Xie
9 min readadvanced
--
View Original

Overview

The article discusses the challenges of managing a large test suite in software development, particularly at Shopify, where the number of tests has grown significantly. It highlights the implementation of dynamic analysis to optimize test selection, improving CI stability and developer productivity by running only relevant tests based on code changes.

What You'll Learn

1

How to implement dynamic analysis for test selection in a Ruby codebase

2

Why intermittently failing tests can slow down development processes

3

When to apply selective test running to improve CI efficiency

Prerequisites & Requirements

  • Understanding of Ruby and Rails metaprogramming concepts
  • Experience with continuous integration systems(optional)

Key Questions Answered

What are the main problems with tests at Shopify?
At Shopify, the test suite has over 150,000 tests, growing by 20-30% annually, and takes 30-40 minutes to run. This leads to productivity issues as developers must wait for tests to pass before merging code, exacerbated by intermittently failing tests.
How does dynamic analysis improve test selection?
Dynamic analysis logs every method call during tests to create call graphs. This allows the system to identify which tests are relevant based on modified files, thus optimizing the testing process and reducing the number of tests run.
What are the downsides of using dynamic analysis?
Dynamic analysis can be slow and computationally intensive, often lagging behind the latest code changes. Additionally, it struggles with untraceable files and metaprogramming, which can obscure call paths, leading to some failing tests not being caught.
What benefits come from running fewer tests?
Running fewer tests leads to faster feedback for developers, a decrease in the likelihood of encountering intermittently failing tests, and lower CI costs. This ultimately enhances productivity and efficiency in the development process.

Key Statistics & Figures

Recall of failing tests
99.94%
This metric indicates the effectiveness of the dynamic analysis system in selecting failing tests over two months of operation.
Overall selection rate of tests
60%
This represents the ratio of selected tests to the total number of tests, indicating significant optimization in the testing process.
Compute time savings
25%
This is the average reduction in compute time due to the implementation of dynamic analysis for test selection.

Technologies & Tools

Some links below are affiliate links. We may earn a commission if you make a purchase.

Key Actionable Insights

1
Implement dynamic analysis to optimize your test suite by selecting only relevant tests for code changes.
This approach helps reduce the time developers spend waiting for tests to pass, thereby increasing productivity and allowing for faster iterations.
2
Regularly review and refactor your test suite to minimize intermittently failing tests.
By addressing the root causes of these failures, you can enhance the stability of your CI process and improve overall developer satisfaction.
3
Consider using tools like Rotoscope and Tracepoint to track method calls in Ruby applications.
These tools can aid in creating accurate call graphs, which are essential for effective dynamic analysis and test selection.

Common Pitfalls

1
Failing to address intermittently failing tests can lead to significant delays in development.
These tests can cause developers to waste time on retries and context switching, ultimately hindering productivity.
2
Over-reliance on static analysis may not yield accurate dependency graphs in dynamically typed languages like Ruby.
This can lead to missed test selections and potential undetected failures, emphasizing the need for dynamic analysis.

Related Concepts

Continuous Integration
Test Optimization
Dynamic Analysis
Metaprogramming In Ruby