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.
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')
end
# verify twitter cards (must use domain name etc)
def test_meta
doc = Nokogiri::HTML(IO.read('_site/2018/10/11/getting-feedback-from-a-kiba-etl-job/index.html'))
data = doc.search('meta[name^="twitter"]').inject({}) do |r, e|
r[e['name']] = e['content'] ; r
end
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']
end
# ensure the sitemap uses the absolute domain name
def test_sitemap
doc = Nokogiri::XML(IO.read('_site/sitemap.xml'))
url = doc.xpath('/aws:urlset/aws:url/aws:loc', 'aws' => 'http://www.sitemaps.org/schemas/sitemap/0.9').last
assert_equal 'http://thibautbarrere.com/', url.text
end
# more full url checking
def test_tweet_buttons
expected_url = 'http://thibautbarrere.com/2018/10/11/ruby-kaigi-2018-etl/'
doc = Nokogiri::HTML(IO.read('_site/2018/10/11/ruby-kaigi-2018-etl/index.html'))
url = doc.search('.twitter-share-button').first['data-url']
assert_equal expected_url, url
url = doc.search('.tweet').first['href']
assert_equal "http://twitter.com/share?via=thibaut_barrere&url=#{expected_url}&text=Ruby Kaigi 2018 talk - Kiba ETL data pipelines", url
end
# I rarely visit the RSS hidden, so test it as well
def test_rss
doc = Nokogiri::XML(IO.read('_site/rss.xml'))
links = doc.xpath('/aws:feed/aws:link', 'aws' => 'http://www.w3.org/2005/Atom')
assert_equal 2, links.size
assert_equal({
'type' => 'application/atom+xml',
'href' => 'http://thibautbarrere.com/rss.xml',
'rel' => 'self'
}, links[0].to_h)
assert_equal({
'type' => 'text',
'href' => 'http://thibautbarrere.com/',
'rel' => 'alternate'
}, links[1].to_h)
end
def test_robots_txt
doc = IO.read('_site/robots.txt').strip
assert_equal 'Sitemap: http://thibautbarrere.com/sitemap.xml', doc
end
end
You just run bundle exec ruby tests.rb
.
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")
end
Add:
require 'minitest/focus'
Then:
focus
def test_this_test
end
Thanks!
Perhaps this helps someone:
I needed to add
gem "nokogiri" to the Gemfile
I also neede to change "class Tests < MiniTest::Test" to "class Tests < Minitest::Test" in the test file.
Then fix the tests with things like:
File.exists -> File.exist
but by now I get proper error messages.
I guess that is changed in the last 4 years. :)
Have you changed you approach?