-
Notifications
You must be signed in to change notification settings - Fork 14
What Is It?
Ruby DocTest allows you to put your tests right in with your Ruby code. It also allows you to put tests in a separate documentation file and have the tests run automatically.
See the Example Usage page for a peek at some code.
One of the most compelling features of Ruby DocTest over other test suites is the ability to bring Interactive Ruby (irb) sessions into your code via copy/paste and to use those sessions as your tests. Let’s go through an example of this workflow.
Let’s say we want to create a Digital Object Identifier library that will give us proper bibliographic references, and vice versa from doi.org. In fact, let’s say we are re-creating Rich Apodaca’s 22-line DOI library (note that his page is prettier, since it has source code highlighting):
require 'rubygems'
require 'hpricot'
require 'open-uri'
module DOI
# Convert a doi into a bibliographic reference.
def biblio_for doi
doc = Hpricot(open("http://www.crossref.org/openurl/?" +
"id=doi:#{doi}&noredirect=true&" +
"pid=ourl_sample:sample&format=unixref"))
journal = (doc/"abbrev_title").inner_html
year = (doc/"journal_issue/publication_date/year").inner_html
volume = (doc/"journal_issue/journal_volume/volume").inner_html
number = (doc/"journal_issue/issue").inner_html
first_page = (doc/"pages/first_page").inner_html
last_page = (doc/"pages/last_page").inner_html
"#{journal} #{year}, #{volume}(#{number}) #{first_page}-#{last_page}"
end
# Convert a bibliographic reference into a DOI.
def doi_for journal, year, volume, issue, page
doc = Hpricot(open("http://www.crossref.org/openurl/?" +
"title=#{journal.gsub(/ /, '%20')}&volume=#{volume}&" +
"issue=#{issue}&spage=#{page}&date=#{year}&" +
"pid=ourl_sample:sample&redirect=false&format=unixref"))
(doc/"doi").inner_html
end
end
After showing his code, Rich tests that it is doing what it is advertised to do, by using an irb session. Super! Let’s do that too:
>> require 'doi.rb'
>> include DOI
=> Object
>> biblio_for "10.1021/cr00032a009"
=> "Chem. Rev. 1994, 94(8) 2483-2547"
>> doi_for "Chem. Rev.", 1994, 94, 8, 2483
=> "10.1021/cr00032a009"
Now, let’s copy-paste our irb session into the code:
require 'rubygems'
require 'hpricot'
require 'open-uri'
=begin
doctest: Digital Object Identifier module can be loaded
>> include DOI
=> Object
=end
module DOI
# Convert a doi into a bibliographic reference.
#
# doctest: Try loading a sample DOI and get its bibliographic reference
# >> biblio_for "10.1021/cr00032a009"
# => "Chem. Rev. 1994, 94(8) 2483-2547"
def biblio_for doi
doc = Hpricot(open("http://www.crossref.org/openurl/?" +
"id=doi:#{doi}&noredirect=true&" +
"pid=ourl_sample:sample&format=unixref"))
journal = (doc/"abbrev_title").inner_html
year = (doc/"journal_issue/publication_date/year").inner_html
volume = (doc/"journal_issue/journal_volume/volume").inner_html
number = (doc/"journal_issue/issue").inner_html
first_page = (doc/"pages/first_page").inner_html
last_page = (doc/"pages/last_page").inner_html
"#{journal} #{year}, #{volume}(#{number}) #{first_page}-#{last_page}"
end
# Convert a bibliographic reference into a DOI.
#
# doctest: Try loading a sample bibliographic reference and get its DOI
# >> doi_for "Chem. Rev.", 1994, 94, 8, 2483
# => "10"
# Convert a bibliographic reference into a DOI.
def doi_for journal, year, volume, issue, page
doc = Hpricot(open("http://www.crossref.org/openurl/?" +
"title=#{journal.gsub(/ /, '%20')}&volume=#{volume}&" +
"issue=#{issue}&spage=#{page}&date=#{year}&" +
"pid=ourl_sample:sample&redirect=false&format=unixref"))
(doc/"doi").inner_html
end
end
Let’s run that test code now:
$ rubydoctest doi.rb
=== Testing 'doi.rb'...
OK | Digital Object Identifier module can be loaded
OK | Try loading a sample DOI and get its bibliographic reference
FAIL | Try loading a sample bibliographic reference and get its DOI
Got: "10.1021/cr00032a009"
Expected: "10"
from doi.rb:33
3 comparisons | 3 doctests | 1 failures | 0 errors
Uh-oh! I didn’t copy the result correctly. After fixing the string result, we get:
=== Testing 'doi.rb'...
OK | Digital Object Identifier module can be loaded
OK | Try loading a sample DOI and get its bibliographic reference
OK | Try loading a sample bibliographic reference and get its DOI
3 comparisons | 3 doctests | 0 failures | 0 errors
Done!
One nice feature is the !!! directive, first introduced by Tom Locke in version 0.2 of Ruby DocTest. This lets you open an irb session at any point during your documentation, in the context of the Ruby DocTest code you’ve already written!
For example, let’s say you want to play with some objects after instantiating a complex set of interdependencies. Ok, maybe this won’t be a complex set, but you can use your imagination:
# >> goals = ["mind", "body", "relationships"]
# >> goals.map{ |g| g.capitalize }
# !!!
Now run the rubydoctest, and at the !!! point, an irb session will open where you can play with the “goals” variable, in context.