Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 8ab012b3d3f2e19fbe66502161d3caa92e60fdd9 0 parents
Josh Hull authored
4 .gitignore
@@ -0,0 +1,4 @@
+*.gem
+.bundle
+Gemfile.lock
+pkg/*
4 Gemfile
@@ -0,0 +1,4 @@
+source "http://rubygems.org"
+
+# Specify your gem's dependencies in testable_examples.gemspec
+gemspec
31 README.md
@@ -0,0 +1,31 @@
+# Testable Examples
+
+Run your rdoc examples like they are tests!
+
+## How to
+
+In your rdoc, you might have something like this
+
+ # Example:
+ # Test1.new.add(1, 2)
+ # => 3
+ # Test1.new.add(1, "something")
+ # => TypeError: String can't be coerced into Fixnum
+ def add(num1, num2)
+ num1 + num2
+ end
+
+With testable examples, simply add this to your Rakefile
+
+ desc "test_examples"
+ task :test do
+ $: << 'lib'
+ require 'testable_examples'
+ TestableExamples::Runner.new(:dir => 'lib', :include_path => 'lib', :requires => 'test1').run_examples
+ end
+
+And you will now be able to validate these!
+
+## TODO
+
+So much, this is really just a proof-of-concept.
9 Rakefile
@@ -0,0 +1,9 @@
+require 'bundler'
+Bundler::GemHelper.install_tasks
+
+desc "test"
+task :test do
+ $: << 'lib'
+ require 'testable_examples'
+ TestableExamples::Runner.new(:dir => 'test/test1.rb', :include_path => 'test', :requires => 'test1').run_examples
+end
8 lib/testable_examples.rb
@@ -0,0 +1,8 @@
+require 'testable_examples/matcher'
+require 'testable_examples/runner'
+
+module TestableExamples
+ def self.install_tasks(opts = {})
+ Runner.new(opts).install
+ end
+end
33 lib/testable_examples/matcher.rb
@@ -0,0 +1,33 @@
+module TestableExamples
+ class Matcher
+ def initialize(val)
+ @val = val
+ @literal_val = begin
+ eval(val)
+ rescue Exception
+ nil
+ end
+ end
+
+ def match(*args)
+ o = args.compact.first
+ if @literal_val
+ @literal_val === o
+ elsif @val[/^[A-Z][a-z0-9_]*$/]
+ Object.const_get(@val.to_sym)
+ elsif @val[/^([A-Z][a-zA-Z0-9_]*?):(.*)$/] and o.is_a?(Exception)
+ o.class.to_s === $1.strip && o.message == $2.strip
+ else
+ raise "Unable to understand val type #{@val.inspect}"
+ end
+ end
+
+ def match_exception?
+ @val[/^[A-Z]/]
+ end
+
+ def assert(*args)
+ match(*args) or raise("Unable to match #{args.inspect} against #{@val.inspect}")
+ end
+ end
+end
70 lib/testable_examples/runner.rb
@@ -0,0 +1,70 @@
+module TestableExamples
+ class Runner
+ def initialize(opts)
+ @base = opts[:dir] || Dir.pwd
+ @name = opts[:task_name] || "test_examples"
+ @include_path = opts.key?(:include_path) ? opts[:include_path] : "lib"
+ @requires = opts.key?(:requires) ? opts[:requires] : opts[:requires]
+ end
+
+ def install
+ desc "Test your rdoc examples"
+ task @name do
+ run_examples
+ end
+ end
+
+ def run_examples
+ $: << @include_path if @include_path
+ Array(@requires).each {|r| require r} if @requires
+ in_example = false
+ examples = []
+ STDOUT.sync = true
+ current_example = ''
+ matchers = []
+ rb_files = File.exist?(@base) ? [@base] : Dir[File.join(@base, 'lib/**/*.rb')]
+ puts "Scanning #{rb_files * ', '}"
+ rb_files.each do |file|
+ lines = File.read(file).split(/\n/)
+ lines.each do |line|
+ if line[/^\s*#(.*)/] # comment
+ line = $1.strip
+ case line
+ when /^example:/i then in_example = true
+ when /^(?:# )?=+> (.*)/
+ if in_example
+ expected = $1.strip
+ matchers << Matcher.new(expected)
+ if matchers.last.match_exception?
+ current_example << " rescue e = $!; nil"
+ end
+ current_example << "\nmatchers[#{matchers.size - 1}].match(__example_runner, $!)"
+ end
+ when ''
+ unless current_example.empty?
+ examples << current_example
+ current_example = ''
+ end
+ in_example = false
+ else
+ current_example << "\n__example_runner = (" << line << ")" if in_example
+ end
+ else
+ unless current_example.empty?
+ examples << current_example
+ current_example = ''
+ end
+ in_example = false
+ end
+ end
+ end
+ print "Running #{examples.size} example#{'s' if examples.size != 1} "
+ examples.each do |example|
+ print "."
+ eval(example)
+ end
+ puts ""
+
+ end
+ end
+end
3  lib/testable_examples/version.rb
@@ -0,0 +1,3 @@
+module TestableExamples
+ VERSION = "0.0.1"
+end
11 test/test1.rb
@@ -0,0 +1,11 @@
+class Test1
+
+ # Example:
+ # Test1.new.add(1, 2)
+ # => 3
+ # Test1.new.add(1, "something")
+ # => TypeError: String can't be coerced into Fixnum
+ def add(num1, num2)
+ num1 + num2
+ end
+end
21 testable_examples.gemspec
@@ -0,0 +1,21 @@
+# -*- encoding: utf-8 -*-
+$:.push File.expand_path("../lib", __FILE__)
+require "testable_examples/version"
+
+Gem::Specification.new do |s|
+ s.name = "testable_examples"
+ s.version = TestableExamples::VERSION
+ s.platform = Gem::Platform::RUBY
+ s.authors = ["TODO: Write your name"]
+ s.email = ["TODO: Write your email address"]
+ s.homepage = ""
+ s.summary = %q{TODO: Write a gem summary}
+ s.description = %q{TODO: Write a gem description}
+
+ s.rubyforge_project = "testable_examples"
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ s.require_paths = ["lib"]
+end
Please sign in to comment.
Something went wrong with that request. Please try again.