{"id":16,"date":"2007-02-06T05:33:23","date_gmt":"2007-02-06T04:33:23","guid":{"rendered":"http:\/\/schuerig.de\/michael\/blog\/?p=16"},"modified":"2021-11-24T09:20:10","modified_gmt":"2021-11-24T08:20:10","slug":"valid-markup-test","status":"publish","type":"post","link":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/2007\/02\/06\/valid-markup-test\/","title":{"rendered":"Rails valid markup testing"},"content":{"rendered":"<p>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 <a href=\"http:\/\/plugins.codahale.com\/responsible_markup\/\">Responsible Markup<\/a>.<\/p>\n<p>But let&#8217;s be honest, do you really want to spend much time on writing tests for your markup? After all, it&#8217;s taking long enough to get the markup right. Ruby to the rescue! Why write tests when we can get Ruby to write them?<\/p>\n<p>Here&#8217;s what I&#8217;m using.<\/p>\n<p><code><\/p>\n<pre>\r\nclass ValidMarkupTest &lt; Test::Unit::TestCase\r\n  ResponsibleMarkup::validator_uri = 'http:\/\/localhost\/w3c-markup-validator\/check'\r\n\r\n  def self.validate_markup_for_resources(*resources)\r\n    default_actions = {\r\n      :index =&gt; { :method =&gt; :get, :template =&gt; 'list' }, \r\n      :new   =&gt; { :method =&gt; :get, :template =&gt; 'new' },\r\n      :edit  =&gt; { :method =&gt; :get, :id =&gt; 1, :template =&gt; 'edit' }\r\n    }\r\n    if resources.last.kind_of?(Hash)\r\n      actions = resources.pop\r\n      actions.each do |action, options|\r\n        options.reverse_merge!(default_actions[action] || {})\r\n      end\r\n    else\r\n      actions = default_actions\r\n    end\r\n\r\n    resources.each do |resource|\r\n      fixtures resource\r\n\r\n      controller_class = \"#{resource.to_s.camelize}Controller\".constantize\r\n\r\n      actions.each do |action, options|\r\n        options = options.dup\r\n\r\n        define_method(\"test_action_#{action}_for_#{resource}_returns_valid_markup\") do\r\n          @controller = controller_class.new\r\n\r\n          request_method    = options.delete(:method)\r\n          expected_template = options.delete(:template)\r\n\r\n          send(request_method, action, options)\r\n\r\n          assert_response :success\r\n          assert_template expected_template\r\n          assert_valid_markup\r\n        end\r\n      end\r\n    end\r\n  end\r\n\r\n  validate_markup_for_resources :thingamuhjigs, :humdingers, :gizmos\r\n\r\n  def setup\r\n    @request  = ActionController::TestRequest.new\r\n    @response = ActionController::TestResponse.new\r\n    login_test_user\r\n  end\r\n\r\n  def assert_valid_markup\r\n    assert_doctype(:xhtml_10_strict)\r\n    assert_content_type\r\n#    assert_compatible_empty_elements\r\n    assert_no_empty_attributes\r\n    assert_no_long_style_attributes\r\n    assert_unobtrusive_javascript :allowed =&gt; [ :inline_events, :blank_hrefs ]\r\n    assert_valid_html\r\n  end\r\n\r\nend\r\n<\/pre>\n<p><\/code><\/p>\n<p>The idea is to have separate the testing task into three parts.<\/p>\n<ul>\n<li>\n    A generic, lightly configurable, method for defining tests: <code>validate_markup_for_resources<\/code>\n  <\/li>\n<li>\n    A <code>setup<\/code> method that is specific to your application. In the example above, I need to login a user.\n  <\/li>\n<li>\n   A <code>assert_valid_markup<\/code> method that contains assertions for your validation goals.\n  <\/li>\n<\/ul>\n<h3>Configuration<\/h3>\n<p>By default, <code>validate_markup_for_resources<\/code> generates tests for <code>index<\/code>, <code>new<\/code>, and <code>edit<\/code> actions. For the <code>edit<\/code> 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<\/p>\n<p><code><\/p>\n<pre>\r\nvalidate_markup_for_resources :gizmos, :id => 2, :template => 'gizmo', :\\other_param => 'xyz'\r\n<\/pre>\n<p><\/code><\/p>\n<h3>Running<\/h3>\n<p>Normally, by Rails convention, the above example test would belong in <code>test\/functional<\/code>. 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&#8217;ve created a new directory, <code>test\/markup<\/code> and run the tests in there with<\/p>\n<p><code><\/p>\n<pre>\r\n$ rake test:markup\r\n<\/pre>\n<p><\/code><\/p>\n<p>This rake task is provided by the following snippet in <code>lib\/tasks\/markup.rake<\/code>.<\/p>\n<p><code><\/p>\n<pre>\r\nnamespace :test do\r\n  desc \"Run the checks for valid markup defined in test\/markup\"\r\n  Rake::TestTask.new(:markup =&gt; \"environment\") do |t|\r\n    t.libs &lt;&lt; \"test\"\r\n    t.pattern = 'test\/markup\/**\/*_test.rb'\r\n    t.verbose = true\r\n  end\r\nend\r\n<\/pre>\n<p><\/code><\/p>\n<p>Incidentally, yes, I know that the markup of this blog is broken. Blame WordPress.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s be honest, do you really want to &hellip; <a href=\"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/2007\/02\/06\/valid-markup-test\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,12],"tags":[],"class_list":["post-16","post","type-post","status-publish","format-standard","hentry","category-rails","category-testing"],"_links":{"self":[{"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":1,"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"predecessor-version":[{"id":147,"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/posts\/16\/revisions\/147"}],"wp:attachment":[{"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.schuerig.de\/michael\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}