Skip to content
Rails upgrade's best friend
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin bundle gem still_life Feb 27, 2019
lib Version 0.1.0 Mar 19, 2019
test bundle before run Mar 23, 2019
.gitignore Ignore more bundler lock files Mar 2, 2019
.travis.yml Setting up Chrome on Travis Mar 23, 2019
Gemfile bundle gem still_life Feb 27, 2019
MIT-LICENSE MIT-LICENSE Feb 27, 2019 README Mar 19, 2019
Rakefile `rake test` now doesn't run tests in the dummy app Mar 2, 2019
still_life.gemspec WIP Mar 2, 2019


What's This?

still_life is a testing framework enhancements for test-unit, minitest, RSpec, and Capybara that records all HTML response body texts that are rendered during E2E or unit test executions.

So What?

You can compare actually rendered HTML results before and after any app updates.

For What?

By comparing all these HTML files that are processed before and after any kind of code change, you can make sure that you did not (or you did) introduce any new user-facing incompatibilities. This may greatly help you for example, refactoring your app, replacing external libraries, or upgrading libraries. My personal use case that made me gemifying still_life was that I wanted to make sure that my own template engine renders the same HTML as the one that I was using.

But indeed, the real sweet spot of this tiny library is IMO "Rails upgrade". In fact, The first original version of this tool was implemented as an RSpec monkeypatch while we were upgrading a huge Rails application from Rails 2 to Rails 3.


Bundle still_life gem to your Rails app's :test environment.

gem 'still_life', group: :test


Run tests with an envvar STILL_LIFE. Then still_life creates some HTML files under tmp/html/#{ENV['STILL_LIFE']}/ directory. Each .html file is named from the location in your test code where the request was made.

For instance, if you run the tests against a simple scaffold app, the generated files will be like this:

% STILL_LIFE=rails52 rails test:system test
% tree tmp/html
└── rails52
    └── test
        ├── controllers
        │   ├── users_controller_test.rb-14.html
        │   ├── users_controller_test.rb-20.html
        │   ├── users_controller_test.rb-27.html
        │   ├── users_controller_test.rb-32.html
        │   ├── users_controller_test.rb-37.html
        │   ├── users_controller_test.rb-43.html
        │   └── users_controller_test.rb-9.html
        └── system
            ├── users_test.rb-14.html
            ├── users_test.rb-18.html
            ├── users_test.rb-21.html
            ├── users_test.rb-25.html
            ├── users_test.rb-26.html
            ├── users_test.rb-29.html
            ├── users_test.rb-32.html
            ├── users_test.rb-36.html
            ├── users_test.rb-37.html
            └── users_test.rb-9.html

4 directories, 17 files

And each file content is just an HTML.

% cat tmp/html/rails52/test/system/users_test.rb-18.html
<!DOCTYPE html><html xmlns=""><head>

    <link rel="stylesheet" media="all" href="/assets/application-35729bfbaf9967f119234595ed222f7ab14859f304ab0acc5451afb387f637fa.css" data-turbolinks-track="reload" />
    <script src="/assets/application-3c2e77f06bf9a01c87fc8ca44294f3d3879d89483d83b66a13a89fc07412dd59.js" data-turbolinks-track="reload"></script>

    <p id="notice">User was successfully created.</p>


<a href="/users/980190963/edit">Edit</a> |
<a href="/users">Back</a>



Usage Scenario

Consider you have a well-tested Rails 5.2 app, and you want to upgrade its Rails version to 6.0 without introducing any user-facing incompatibilities. Then the workflow will be as follows:

1. Draw a still_life with the 5.2 app

% STILL_LIFE=rails52 rails test:system test

2. Do the upgrade job

% bundle u
% rails app:update

and push some more commits...

3. Draw another still_life with the 6.0 app

% STILL_LIFE=rails60 rails test:system test

4. Compare the results, and make sure there's no unexpected diffs

% diff -r tmp/html/rails52 tmp/html/rails60


Random Values

If your response includes some kind of random values, the test results may change between each test runs. In such case, maybe you could specify a random seed, or mock the random source in your app, or grep -v is always your friend.

TODOs / Known Issues

  • The Capybara monkeypatch sometimes fails to get the page.body due to Capybara timing problem
  • Support older versions of Rails, Capybara, and Ruby


Pull requests are welcome on GitHub at


The original idea of this library was implemented as a 10 LOC anonymous module by @hotchpotch at Cookpad Inc. back in 2011 as written in this slide.


The gem is available as open source under the terms of the MIT License.

You can’t perform that action at this time.