Ruby Inline Tests

Did you know you can inline tests with your ruby code in the same file?

Posted by Anton Katunin on 31 May 2016
Tags: code

After reading the title Embedding a Test Suite in a Single-file Ruby App (Part 1) I thought: aha! finally somebody has done it and used ruby data block to store tests. However I was disappointed as there was another approach, which I think is less elegant.

Below I show you a proof of concept of embedding tests in ruby code.


Because tests and code are in the same file:

  • easier to refactor
  • easier to navigate
  • documentation from tests near the code
  • does not affect code performance
  • reminds you to write tests
  • How

    Ruby has special feature which I call data blocks. In short you can embed any data after your ruby code in the same file and when you run that file that data will be available as DATA constant. All you need is to separate it with __END__.

    For example

    $ cat t.rb
    puts DATA.gets
    hello world!
    $ ruby t.rb
    hello world!

    Putting all together

    Below is my proof of concept to run rspec tests from the same file.

    # drink.rb
    class Drink
      attr_reader :type
      def initialize
        @type = "water"
    require 'spec_helper'
    RSpec.describe Drink do
       it 'is has default type water' do
        expect( eq('water')

    In order for that to work we need to put small patch to rspec so it reads the file correctly.

    # spec_helper.rb
    class DataBlockLoader
      module RspecConfig
        def load_spec_files
          files_to_run.uniq.each do |f|
            file = File.expand_path(f)
            DataBlockLoader.load file
      END_TOKEN = /^__END__\r?\n/
      def self.load file_path
        io =, 'r' )
        loop do
          line = io.gets
          break if line.nil?
          break if line.match(END_TOKEN)
        line_no = io.lineno
        eval, nil, file_path, line_no + 1
    RSpec::Core::Configuration.prepend DataBlockLoader::RspecConfig


    Now we can just run that file with rspec:

    $ rspec drink.rb
     1/1 |========================= 100 ==========================>| Time: 00:00:01
    Finished in 0.86 seconds (files took 0.70232 seconds to load)
    1 example, 0 failures

    This is just a small proof of concept which requires more work on adopting rspec internals to work with data blocks. Let's me know if you'll take a challenge on that.

    Read next:

    Volunteering at RailsGirls Next

    at Melbourne