testable_examples 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +31 -0
- data/Rakefile +9 -0
- data/lib/testable_examples.rb +8 -0
- data/lib/testable_examples/matcher.rb +33 -0
- data/lib/testable_examples/runner.rb +70 -0
- data/lib/testable_examples/version.rb +3 -0
- data/test/test1.rb +11 -0
- data/testable_examples.gemspec +21 -0
- metadata +77 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Testable Examples
|
2
|
+
|
3
|
+
Run your rdoc examples like they are tests!
|
4
|
+
|
5
|
+
## How to
|
6
|
+
|
7
|
+
In your rdoc, you might have something like this
|
8
|
+
|
9
|
+
# Example:
|
10
|
+
# Test1.new.add(1, 2)
|
11
|
+
# => 3
|
12
|
+
# Test1.new.add(1, "something")
|
13
|
+
# => TypeError: String can't be coerced into Fixnum
|
14
|
+
def add(num1, num2)
|
15
|
+
num1 + num2
|
16
|
+
end
|
17
|
+
|
18
|
+
With testable examples, simply add this to your Rakefile
|
19
|
+
|
20
|
+
desc "test_examples"
|
21
|
+
task :test do
|
22
|
+
$: << 'lib'
|
23
|
+
require 'testable_examples'
|
24
|
+
TestableExamples::Runner.new(:dir => 'lib', :include_path => 'lib', :requires => 'test1').run_examples
|
25
|
+
end
|
26
|
+
|
27
|
+
And you will now be able to validate these!
|
28
|
+
|
29
|
+
## TODO
|
30
|
+
|
31
|
+
So much, this is really just a proof-of-concept.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module TestableExamples
|
2
|
+
class Matcher
|
3
|
+
def initialize(val)
|
4
|
+
@val = val
|
5
|
+
@literal_val = begin
|
6
|
+
eval(val)
|
7
|
+
rescue Exception
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def match(*args)
|
13
|
+
o = args.compact.first
|
14
|
+
if @literal_val
|
15
|
+
@literal_val === o
|
16
|
+
elsif @val[/^[A-Z][a-z0-9_]*$/]
|
17
|
+
Object.const_get(@val.to_sym)
|
18
|
+
elsif @val[/^([A-Z][a-zA-Z0-9_]*?):(.*)$/] and o.is_a?(Exception)
|
19
|
+
o.class.to_s === $1.strip && o.message == $2.strip
|
20
|
+
else
|
21
|
+
raise "Unable to understand val type #{@val.inspect}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def match_exception?
|
26
|
+
@val[/^[A-Z]/]
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert(*args)
|
30
|
+
match(*args) or raise("Unable to match #{args.inspect} against #{@val.inspect}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module TestableExamples
|
2
|
+
class Runner
|
3
|
+
def initialize(opts)
|
4
|
+
@base = opts[:dir] || Dir.pwd
|
5
|
+
@name = opts[:task_name] || "test_examples"
|
6
|
+
@include_path = opts.key?(:include_path) ? opts[:include_path] : "lib"
|
7
|
+
@requires = opts.key?(:requires) ? opts[:requires] : opts[:requires]
|
8
|
+
end
|
9
|
+
|
10
|
+
def install
|
11
|
+
desc "Test your rdoc examples"
|
12
|
+
task @name do
|
13
|
+
run_examples
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_examples
|
18
|
+
$: << @include_path if @include_path
|
19
|
+
Array(@requires).each {|r| require r} if @requires
|
20
|
+
in_example = false
|
21
|
+
examples = []
|
22
|
+
STDOUT.sync = true
|
23
|
+
current_example = ''
|
24
|
+
matchers = []
|
25
|
+
rb_files = File.exist?(@base) ? [@base] : Dir[File.join(@base, 'lib/**/*.rb')]
|
26
|
+
puts "Scanning #{rb_files * ', '}"
|
27
|
+
rb_files.each do |file|
|
28
|
+
lines = File.read(file).split(/\n/)
|
29
|
+
lines.each do |line|
|
30
|
+
if line[/^\s*#(.*)/] # comment
|
31
|
+
line = $1.strip
|
32
|
+
case line
|
33
|
+
when /^example:/i then in_example = true
|
34
|
+
when /^(?:# )?=+> (.*)/
|
35
|
+
if in_example
|
36
|
+
expected = $1.strip
|
37
|
+
matchers << Matcher.new(expected)
|
38
|
+
if matchers.last.match_exception?
|
39
|
+
current_example << " rescue e = $!; nil"
|
40
|
+
end
|
41
|
+
current_example << "\nmatchers[#{matchers.size - 1}].match(__example_runner, $!)"
|
42
|
+
end
|
43
|
+
when ''
|
44
|
+
unless current_example.empty?
|
45
|
+
examples << current_example
|
46
|
+
current_example = ''
|
47
|
+
end
|
48
|
+
in_example = false
|
49
|
+
else
|
50
|
+
current_example << "\n__example_runner = (" << line << ")" if in_example
|
51
|
+
end
|
52
|
+
else
|
53
|
+
unless current_example.empty?
|
54
|
+
examples << current_example
|
55
|
+
current_example = ''
|
56
|
+
end
|
57
|
+
in_example = false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
print "Running #{examples.size} example#{'s' if examples.size != 1} "
|
62
|
+
examples.each do |example|
|
63
|
+
print "."
|
64
|
+
eval(example)
|
65
|
+
end
|
66
|
+
puts " ✔"
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/test/test1.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "testable_examples/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "testable_examples"
|
7
|
+
s.version = TestableExamples::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Joshua Hull"]
|
10
|
+
s.email = ["joshbuddy@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/joshbuddy/testable_examples"
|
12
|
+
s.summary = %q{Test your examples!}
|
13
|
+
s.description = %q{Test your examples!}
|
14
|
+
|
15
|
+
s.rubyforge_project = "testable_examples"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: testable_examples
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joshua Hull
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-29 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Test your examples!
|
23
|
+
email:
|
24
|
+
- joshbuddy@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- README.md
|
35
|
+
- Rakefile
|
36
|
+
- lib/testable_examples.rb
|
37
|
+
- lib/testable_examples/matcher.rb
|
38
|
+
- lib/testable_examples/runner.rb
|
39
|
+
- lib/testable_examples/version.rb
|
40
|
+
- test/test1.rb
|
41
|
+
- testable_examples.gemspec
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: https://github.com/joshbuddy/testable_examples
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project: testable_examples
|
72
|
+
rubygems_version: 1.3.7
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Test your examples!
|
76
|
+
test_files:
|
77
|
+
- test/test1.rb
|