November 27, 2006

Posted by John

Tagged multisite and testing

Older: Fixture Groups

Newer: Styleaby CSS Plugin

Testing A Multi-Site Application

In Building A Multi-Site Application, I showed you the basics of getting a development environment setup and how to make your application deal with multiple sites. That is great, but an app is just a hack without tests so now it’s time to fulfill the promise that I stated in the previous article and show you a few tips on how to test your multi-site application.

First off, the current multi-site application that I’m working on isn’t finished so this will not be a complete article. However, I have picked up a few tricks that will get you started. Oh, and the final caveat is that I’m not going to cover unit testing. There aren’t really any tricks to unit testing a multi-site app. It works the same as unit testing any other rails app. Functional testing a multi-site app is a bit different and that is what I will cover here.

Picking Up Where We Left Off

I’m going to pick up with the same application that I started in the first article so if you haven’t read that, do so now. For starters, let’s create a post resource and allow each site to have multiple posts. Creating this relationship will help demonstrate what I’ve picked up so far.

$ script/generate scaffold_resource post title:string body:text created_at:datetime updated_at:datetime site_id:integer

That created a new migration for us, so let’s migrate to the newest version.

$ rake db:migrate

Ok, now that we have a new resource and our database is updated, let’s start this baby up again.

$ script/server

…and navigate our browser to http://notredame.multisite.local:3000/posts. Currently, sites and posts are in no way related so let’s add the correct associations into the site model and post models:

class Site < ActiveRecord::Base
  has_many :posts

class Post < ActiveRecord::Base
  belongs_to :site

Look Ma, Tests!

Ok, now that we have that working, it’s time to start writing some tests. If you look in the tests/fixtures directory, you’ll notice the sites.yml and posts.yml files. These have some information in them, but we’ll change a few things. Leave posts.yml the way it is and update sites.yml to the code below:

  id: 1
  name: Notre Dame
  subdomain: notredame
  created_at: <%= 4.days.ago %>
  updated_at: <%= 4.days.ago %>
  id: 2
  name: Ohio State
  subdomain: ohiostate
  created_at: <%= 2.days.ago %>
  updated_at: <%= 2.days.ago %>

Again, I just want to put out this little reminder that you should test a lot more than I will in this article. I’m only going to cover the multi-site specific testing stuff.

So now that we have a few test sites to work with, let’s open up test/functional/post_controller_test.rb. You’ll notice that it already has several tests in there. Go ahead and delete them all. Also, before I forget, let’s prepare the test database so that our fixtures will have tables to load into. Run the following command from your terminal:

$ rake db:test:prepare

Now make sure that both the sites and posts fixtures are loaded in the post_controller_test file.

fixtures :sites, :posts

The key to testing a multisite application is the host. After we initialize the controller and the test response and request, we need to change the host. In order to do so, I use a simple little helper which you can add to your test/test_helper.rb file:

def change_host_to(site) = sites(site).subdomain + ""

Now that we have that helper, we can change the host for our requests by adding change_host_to :nd after are test setup code. This will make your setup method look like this:

def setup
  @controller =
  @request    =
  @response   =
  change_host_to :nd

Let’s check and see if that worked by testing the index action. Add the following method to your post_controller_test.rb file:

def test_should_get_index
  get :index
  puts @controller.current_site.inspect

…and run your functional tests:

$ rake test:functionals

You should see something along the lines of:

#<Site:0x32aeaec @attributes={"name"=>"Notre Dame", "updated_at"=>"0000-00-00 00:00:00", "subdomain"=>"notredame", "id"=>"1", "created_at"=>"0000-00-00 00:00:00"}>

…somewhere inside the output of your test. One thing to note is that @controller.current_site is not available until you have actually made a request using get, post, put or delete. In order to not make this article longer than it already is, I’ll once again furnish a zip file that you can download and peruse. I switched around the posts controller a bit and tested the create method in the posts_controller_test. Enjoy!


  1. Awesome, thanks!

  2. @Ryan – No problem. I’m sure I’ll have more as I get farther into my current work project.

Sorry, comments are closed for this article to ease the burden of pruning spam.


Authored by John Nunemaker (Noo-neh-maker), a programmer who has fallen deeply in love with Ruby. Learn More.


Release your software more often with fewer problems.
Flip your features.