November 27, 2006
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
end
class Post < ActiveRecord::Base
belongs_to :site
end
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:
nd:
id: 1
name: Notre Dame
subdomain: notredame
created_at: <%= 4.days.ago %>
updated_at: <%= 4.days.ago %>
oh:
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)
@request.host = sites(site).subdomain + ".multisite.com"
end
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 = PostsController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
change_host_to :nd
end
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
end
…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!
2 Comments
Dec 07, 2006
Awesome, thanks!
Dec 08, 2006
@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.