Software Developer & Founder Torsten Bühl

Hi, I'm Torsten Bühl. I am the founder of Foodlane, Company Signal, and Exceptiontrap (acquired by Scout APM). I strive to build simple and beautiful software products that people love to use. Learn more about them here

How to test your Rails app with subdomains the easy way

Torsten Bühl

When you look for ways to test your Ruby on Rails app that uses (wildcard) subdomains, you are usually told to use lvh.me or similar domains as your host. These services resolve all subdomains you throw at them to localhost. Problem solved, right? Well, not really …

The problem

First, I’ve always wondered how anyone could feel good about relying on an external service for that. Especially one that no one knows anything about. It could either change the way things work, have network issues, or just shut down from one day to another. And the latter is exactly what happened. Even if it wouldn’t have: local testing doesn’t work without an internet connection, and your CI builds could break any moment. A recipe for flaky tests.

The solution

Luckily there is a simple solution: Just use your hosts file to resolve the needed subdomains back to localhost. But what if I have wildcard subdomains you might ask? There is no way to add these to the hosts file, but you don’t need to do that anyway. I would argue that you only need to test a limited number of subdomains to make sure things work as expected.

Rails setup

Alright, let’s assume our app sits on foodlane.io. For testing we will make that foodlane.test. (For some time Safari didn’t set cookies for .test domains, but that seems to be fixed now. A workaround was to use .local.)

# development.rb
config.hosts << 'foodlane.test'
config.hosts << /[a-z0-9-]*\.foodlane\.test/
# test_helper.rb
# ...
class ActiveSupport::TestCase
  # ...
  Capybara.app_host = 'http://foodlane.test'
end

Hosts file

Add the main domain and all the subdomains you need to your /etc/hosts file

# /etc/hosts
127.0.0.1 foodlane.test app.foodlane.test ristorante-milano.foodlane.test

CI

On your CI server it works exactly the same way. Just add the necessary domains to the hosts file before running your tests.

My Github Actions file looks like this:

# ci.yml
# ...
- name: Add hosts to /etc/hosts
  run: |
    echo "127.0.0.1 foodlane.test" | sudo tee -a /etc/hosts
    echo "127.0.0.1 app.foodlane.test" | sudo tee -a /etc/hosts
    echo "127.0.0.1 ristorante-milano.foodlane.test" | sudo tee -a /etc/hosts
- name: Run system tests
  run: bin/rails test:system

Let me know

Any feedback? Just ping me at @tbuehl, or send me an email.