posted on

XML , Ruby , RSpec , Testing , Open Source


We've been working on a few projects recently that have required a lot of XML to be generated. This XML is defined by a schema and as such must validate against it.

While the generated documents can be validated using external tools this was proving inconvienent and didn't integrate with the rest of the test-suites. Inspired by a recent post from Thoughtbot on validaing JSON schemas with RSpec I put together a custom RSpec matcher to provide the same functionality for XML.

Introducing RSpec-XSD

RSpec-XSD provides a single matcher to check that the document (or fragment) provided validates against the given schema.

To install the matcher just add the RSpec-XSD to your Gemfile.

group :test do
  gem 'rspec-xsd'
end

Then require the gem in your spec_helper and include the matcher.

require 'rspec/xsd'

RSpec.configure do |config|
  config.include RSpec::XSD
end

RSpec-XSD provides a single matcher (pass_validation) to use in your specs, e.g.

describe MyXMLGenerator do
  let(:schema) { '/path/to/schema.xsd' }

  describe '.generate' do
    context 'with valid input' do
      let(:xml) { MyXMLGenerator.generate(valid_details) }

      it 'validates' do
        expect(xml).to pass_validation(schema)
      end
    end

    context 'with invalid input' do
      let(:xml) { MyXMLGenerator.generate(invalid_details) }

      it 'does not validate' do
        expect(xml).not_to pass_validation(schema)
      end
    end
  end
end

Now when your specs run any validation issues will be raised in the failure message, e.g.

Failures:

  1) MyXMLGenerator.generate with valid input validates
     Failure/Error: expect(xml).to pass_validation(schema)
       expected that XML would validate against schema.xsd

       Element 'note': Missing child element(s). Expected is ( body ).

For further details or to submit a pull request or issue please refer to the repo on Github.