Jandaweb

Testing XHTML validity with Ruby and libxml

By Andrew Bruce on Wednesday 25th June 2:19 PM

Update: now a plugin

Rails 2.1 and git only. You still need to install the libxml-ruby gem, and you need git installed to install the plugin. Install plugin with:

script/plugin install git://www.jandaweb.com/assert_valid_xhtml

Slow validation

The responsible_markup plugin from codahale is fine and dandy if you want all the features and you're always connected to the net. If, however, like me, you're moving around a bit and sometimes get a dodgy connection, or simply want to speed up your functional tests' XHTML validation, give this a spin.

It's an assertion that can be stuck into your test_helper.rb or made into a plugin as you see fit.
I didn't think it was worth making a special plugin just yet, as it's very limited in scope.
It assumes you're doing XHTML 1.0 validation.

Installation

Install the libxml gem:

sudo gem install libxml-ruby

Download the XHTML 1.0 DTDs to a special directory:

cd YOUR_RAILS_PROJECT
mkdir doc/dtd
cd doc/dtd
wget http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
wget http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent
wget http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent
wget http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent

Now you're ready to paste some code. Open up your test/test_helper.rb and stick the following require lines somewhere at the top, after "require 'test_help'":

require 'xml/libxml'
require 'md5'

We'll be doing some md5 hashing to (almost) guarantee unique versions of markup.

Here's the assertion!


def assert_valid_xhtml
  checksum = MD5.new(@response.body)
  path = "/tmp/assert_valid_xhtml_#{checksum}"

  return true if File.exists?("#{path}-valid")

  dtd = XML::Dtd.new("-//W3C//DTD XHTML 1.0 Strict//EN", 
                     RAILS_ROOT + '/doc/dtd/xhtml1-strict.dtd')

  unless File.exists?(path)
    File.open(path, 'w') { |f| f.puts @response.body }
  end

  doc = XML::Document.file(path)
  if doc.validate(dtd)
    FileUtils.mv(path, "#{path}-valid")
  else
    assert false
  end
end

Usage

Now you can stick "assert_valid_xhtml" after any request to make sure it's valid. Okay, so the results don't come back too pretty and they go to STDERR instead of the failure notice, but this was knocked together quickly.

If you want to see what the code is doing try a "watch ls /tmp" while rake is running. You'll see the files being marked off as valid as it works.

« Back to list