Coda Hale has given the intersection of the Rails and web standards communities a very nice plugin for keeping your markup clean. It is aptly, if slightly pretentiously, named Responsible Markup.
But let’s be honest, do you really want to spend much time on writing tests for your markup? After all, it’s taking long enough to get the markup right. Ruby to the rescue! Why write tests when we can get Ruby to write them?
Here’s what I’m using.
class ValidMarkupTest < Test::Unit::TestCase ResponsibleMarkup::validator_uri = 'http://localhost/w3c-markup-validator/check' def self.validate_markup_for_resources(*resources) default_actions = { :index => { :method => :get, :template => 'list' }, :new => { :method => :get, :template => 'new' }, :edit => { :method => :get, :id => 1, :template => 'edit' } } if resources.last.kind_of?(Hash) actions = resources.pop actions.each do |action, options| options.reverse_merge!(default_actions[action] || {}) end else actions = default_actions end resources.each do |resource| fixtures resource controller_class = "#{resource.to_s.camelize}Controller".constantize actions.each do |action, options| options = options.dup define_method("test_action_#{action}_for_#{resource}_returns_valid_markup") do @controller = controller_class.new request_method = options.delete(:method) expected_template = options.delete(:template) send(request_method, action, options) assert_response :success assert_template expected_template assert_valid_markup end end end end validate_markup_for_resources :thingamuhjigs, :humdingers, :gizmos def setup @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new login_test_user end def assert_valid_markup assert_doctype(:xhtml_10_strict) assert_content_type # assert_compatible_empty_elements assert_no_empty_attributes assert_no_long_style_attributes assert_unobtrusive_javascript :allowed => [ :inline_events, :blank_hrefs ] assert_valid_html end end
The idea is to have separate the testing task into three parts.
-
A generic, lightly configurable, method for defining tests:
validate_markup_for_resources
-
A
setup
method that is specific to your application. In the example above, I need to login a user. -
A
assert_valid_markup
method that contains assertions for your validation goals.
Configuration
By default, validate_markup_for_resources
generates tests for index
, new
, and edit
actions. For the edit
test, it assumes that an object with the id 1 exists. If you need to change the request options used by default, you can override them like this
validate_markup_for_resources :gizmos, :id => 2, :template => 'gizmo', :\other_param => 'xyz'
Running
Normally, by Rails convention, the above example test would belong in test/functional
. However, even when using a validator installed on the local machine, it takes quite some time to run. So, in order not to slow down my functional tests too much, I’ve created a new directory, test/markup
and run the tests in there with
$ rake test:markup
This rake task is provided by the following snippet in lib/tasks/markup.rake
.
namespace :test do desc "Run the checks for valid markup defined in test/markup" Rake::TestTask.new(:markup => "environment") do |t| t.libs << "test" t.pattern = 'test/markup/**/*_test.rb' t.verbose = true end end
Incidentally, yes, I know that the markup of this blog is broken. Blame WordPress.