Skip to content

Instantly share code, notes, and snippets.



Last active Mar 27, 2020
What would you like to do?
Using minitest to regression test your Jekyll static site

Using minitest to regression-test your Jekyll static site

I recently had to upgrade my blog, which involved changes such as:

  • Replacing a sitemap plugin
  • Upgrading from jekyll 2.5.3 to 3.8.4
  • Upgrading from jekyll-assets 0.7.8 to 3.0.11
  • (etc)

The upgrading process was not trivial, and some parts (e.g. RSS, sitemap, or twitter cards tags) are not immediately visible, so I decided to add unit tests on the generated content.

Minitest use nice and lightweight, a perfect fit for what I needed here.

I'm sharing these codebits in hope it will help other developers.

Having this test suite ensures that your static site will age well when you'll upgrade the gems.

Getting started

Add the following gems to your Gemfile:

  • minitest
  • minitest-focus (to easily select a single test)
  • awesome_print (to color print when debugging)

Then create a simple tests.rb file.

Here is mine after a few iterations & with a few comments.

The tests assume JEKYLL_ENV is set to production, to test on the output which is uploaded to production.

require 'minitest/autorun'
require 'minitest/focus'
require 'nokogiri'
require 'ap'

class Tests < MiniTest::Test
  # make sure we're not using files with .html, but instead index.html in a directory, for cloudfront support
  def test_urls
    assert File.exists?('_site/2015/06/04/how-to-reformat-csv-files-with-kiba/index.html')
  # verify twitter cards (must use domain name etc)
  def test_meta
    doc = Nokogiri::HTML('_site/2018/10/11/getting-feedback-from-a-kiba-etl-job/index.html'))
    data ='meta[name^="twitter"]').inject({}) do |r, e|
      r[e['name']] = e['content'] ; r
    assert_equal 'summary_large_image', data['twitter:card']
    assert_equal '@thibaut_barrere', data['twitter:site']
    assert_equal 'Get feedback from Kiba ETL jobs', data['twitter:title']
    assert data['twitter:description'].start_with?('Learn how to write Kiba jobs')
    assert_match /\Ahttp:\/\/thibautbarrere\.com\/assets\/programmatic\-feedback\-/, data['twitter:image']

  # ensure the sitemap uses the absolute domain name
  def test_sitemap
    doc = Nokogiri::XML('_site/sitemap.xml'))
    url = doc.xpath('/aws:urlset/aws:url/aws:loc', 'aws' => '').last
    assert_equal '', url.text
  # more full url checking
  def test_tweet_buttons
    expected_url = ''
    doc = Nokogiri::HTML('_site/2018/10/11/ruby-kaigi-2018-etl/index.html'))
    url ='.twitter-share-button').first['data-url']
    assert_equal expected_url, url
    url ='.tweet').first['href']
    assert_equal "{expected_url}&text=Ruby Kaigi 2018 talk - Kiba ETL data pipelines", url
  # I rarely visit the RSS hidden, so test it as well
  def test_rss
    doc = Nokogiri::XML('_site/rss.xml'))
    links = doc.xpath('/aws:feed/aws:link', 'aws' => '')
    assert_equal 2, links.size
      'type' => 'application/atom+xml',
      'href' => '',
      'rel' => 'self'
    }, links[0].to_h)
      'type' => 'text',
      'href' => '',
      'rel' => 'alternate'
    }, links[1].to_h)
  def test_robots_txt
    doc ='_site/robots.txt').strip
    assert_equal 'Sitemap:', doc

How to run

You just run bundle exec ruby tests.rb.

How to run at build

Put this in _plugins/tests.rb:

Jekyll::Hooks.register :site, :post_write do |site|
  # NOTE: you may want to raise conditionally here to stop the deploy
  system("bundle exec ruby tests.rb")

How to focus on a single test


require 'minitest/focus'


def test_this_test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.