Doctests (documentation testing) for Ruby
The best kind of documentation is documentation that can never go out of date!
Doctest2 adds documentation testing capabilities to your existing test suite: The code examples in your documentation are now automatically turned into tests!
Doctest2 integrates with your existing test suite, making it a breeze to add to your project.
Doctest2 is split up in multiple gems, so you only pull in what you need:
doctest2-rspec
gem to your Gemfile:group :test do
# ...
gem 'doctest2-rspec, '~> 0.9.0', require: false
end
require 'doctest2/rspec'
in your spec/spec_helper.rb
(or on top of your individual RSpec test files).Now you have access to the doctest
class-method inside describe
blocks.
doctest2-minitest
gem to your Gemfile:group :test do
# ...
gem 'doctest2-minitest', '~> 0.9.0', require: false
end
In test/test_helper.rb
(before the require 'minitest/autorun'
line, if it exists):
class Minitest::Test
include Doctest2::Minitest::DoctestHelpers
end
Now you have access to the doctest
class-method in all test-classes.
If you're using another testing framework, you can invoke doctest2-core
directly. Look at the source of the existing wrapper gems for inspiration. PRs adding support for other testing frameworks are very welcome!
From within the module where the other tests regarding a particular class or module are placed, add the line doctest MyClassOrModule
. This will add any doctests found in its source code as unit tests next to the other tests in that file:
class Adder
# Adds two to a given number
#
# Usage:
# >> m = Adder.new
# >> m.plus_two(3)
# => 5
def plus_two(x)
2 + x
end
end
Within a RSpec test suite:
require 'doctest/rspec'
describe Adder do
doctest Adder
... # <- any normal tests here :-)
end
Within a Minitest test suite:
require 'test_helper'
class AdderTest < Minitest::Test # Or `AdderTest < ActiveSupport::TestCase` in a Rails project
doctest Adder
... # <- any normal tests here :-)
end
Because invoking the doctest
class-method adds normal test cases to your test class,
any setup/cleanup logic can be added in exactly the same way as for normal test cases (using before
/after
/around
for RSpec, setup
/teardown
for Minitest).
Doctest2 extracts any comments starting with >>
or =>
(and any amount of whitespace).
A doctest consists of one or multiple comment lines starting with >>
.
The outcome of evaluating these lines is compared (using ==
) to evaluating the single comment starting with =>
(which can be on the next line or at the end of the last code line):
class User
attr_accessor :first_name, :last_name, :age
def initialize(first_name: nil, last_name: nil)
self.first_name = first_name
self.last_name = last_name
end
# Presents the full name of the user.
#
# Usage:
#
# >> bob = User.new(first_name: "Bob", last_name: "Ross")
# >> bob.display_name
# => "Bob Ross"
#
# If the last name is not set, only the first name will be used
# without extra whitespace
#
# >> User.new(first_name: "Adam")
# >> adam.display_name #=> "Adam"
def display_name
"#{first_name} #{last_name}".strip
end
end
After checking out the repo, use the just command runner for common tasks:
just setup
: Installs dev dependenciesjust test
: Runs the test suite(s)just console
: Opens an IRb console with the gem loaded for experimenting.just install
: Install the gem(s) on your local machine.just release
: Create and push a new release to the git repo and Rubygems. (Be sure to increase the version number in version.rb
first!)The same commands are available in the subdirectories, in which case they only operate on that particular gem.
Bug reports and pull requests are welcome on GitHub at https://github.com/Qqwy/ruby-doctest2.
The gems are available as open source under the terms of the MIT License.
This work is based on the original doctest-core and related gems, which have not been updated since 2014 and for which the repo is no longer available.
Alternative Ruby libraries for doctesting exist (yard-doctest, rdoctest, rubydoctest, dest), but none of them integrates with your normal test suite, instead using their own dedicated test runner.
The syntax and ergonomics of doctest2 takes inspiration from Elixir's doctests.