rails
Fixing slow, flaky system tests in Vite-Rails
Turn off autoBuild
.
By default, Vite-Rails automatically detects changes in your JavaScript, JSX, SCSS, etc. source files and then compiles them as needed. This is really convenient in local development. But when running a large test suite, this “auto build” behavior can cause problems.
Sporadic failures when using Rails parallel testing
Rails 6.0 introduced parallel testing, and it is now enabled by default for test suites containing 50 or more tests. This can lead to some interesting race conditions.
When Vite-Rails is detecting and recompiling assets on the fly, parallel testing means that multiple compilations can be triggered simultaneously. The manifest.json
file, which is the bill-of-materials for the compilation output, can get corrupted as a result.
You may see system tests fail with sporadic errors like these:
JSON::ParserError: unexpected token at ''
or
ViteRuby::MissingEntrypointError: Vite Ruby can't find logo.svg in public/vite-test/manifest.json or public/vite-test/manifest-assets.json.
Slow system tests
To detect if any source files have changed, Vite-Rails traverses all of your frontend code and computes a checksum for every file. It does this every time an asset is referenced. Furthermore, Vite-Rails also needs to check whether the Vite dev server is running, which involves attempting a socket connection and waiting for a timeout.
That means every vite_javascript_tag
, vite_image_tag
, etc. in your views end up triggering a potentially expensive set of operations. Repeat these over dozens of system tests, and this can add up.
In my experience, this auto-detection can add about 10% overhead to a Rails system test suite.
Solution: disable autoBuild
The solution, as hinted at in the Vite-Ruby CI docs, is to disable autoBuild
.
{
...,
"test": {
"autoBuild": false,
"publicOutputDir": "vite-test",
"port": 3037
}
}
Set
autoBuild: false
for the test environment.
However, this introduces a big inconvenience. With autoBuild
off, you have to remember to explicitly build your assets with RAILS_ENV=test rake assets:precompile
before running tests.
To fix the testing experience, add the following line to rails_helper.rb
(RSpec) or test_helper.rb
(Minitest):
ViteRuby.commands.build
With these changes, you no longer have to run an explicit assets:precompile
before running tests, either locally or in CI.
Further reading
- Introduction to Vite Ruby (Vite Ruby docs)
- Integration Tests in the CI (Vite Ruby docs)
- Checksum computation in the
vite_ruby
gem (GitHub) - Parallel testing (Rails guides)
TestCase.parallelize
(Rails API docs)- Discussion thread on Vite + Rails parallel testing conflicts (GitHub)
The solution described in this post is also included in mattbrictson/rails-template. Specify the --javascript vite
option to generate a new project with Vite best practices.