exemplar 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ *swp
2
+ .bundle/
3
+ Gemfile.lock
4
+ .rvmrc
5
+ pkg/
6
+ jeweler/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem 'test-unit', '2.0.9'
5
+ gem 'rr', :git => 'http://github.com/btakita/rr.git'
6
+ end
@@ -0,0 +1,7 @@
1
+ == Getting started
2
+
3
+ See <tt>examples/algebra.rb</tt> for a simple example.
4
+
5
+ == License and Copyright
6
+
7
+ All of the code is copyrighted by Google and is released under MIT license.
@@ -0,0 +1,27 @@
1
+ require 'rake/testtask'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = "exemplar"
7
+
8
+ gem.summary = "Makes writing examples easy and fun"
9
+
10
+ gem.email = "ratnikov@gmail.com"
11
+ gem.homepage = "http://github.com/ratnikov/exemplar"
12
+ gem.authors = [ "Dmitry Ratnikov" ]
13
+ end
14
+
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: gem install jeweler"
18
+ end
19
+
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.test_files = FileList["test/**/*_test.rb"]
22
+ test.libs << 'test'
23
+ test.verbose = false
24
+ end
25
+
26
+ desc "Run the test suite"
27
+ task :default => :test
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 0
5
+ :build:
@@ -0,0 +1,28 @@
1
+ require 'exemplar'
2
+
3
+ class Exemplar::Example
4
+ # <tt>Exemplar::Example</tt> invoked <tt>rescue_error</tt> when it encounters an error during
5
+ # execution of an example. While the default implementation is logging a simple error message,
6
+ # it's possible to change that behavior by providing a handler of our own:
7
+ def rescue_error(error)
8
+ case error
9
+ when ZeroDivisionError then log("Tried to divide by a zero. Bah!")
10
+ when ArgumentError then log("Whoops, bad argument!")
11
+ else
12
+ log("Unknown error: %s" % error.inspect)
13
+ end
14
+ end
15
+ end
16
+
17
+ example "adding two numbers together" do
18
+ puts "1 + 5 = %s" % (1 + 5)
19
+ end
20
+
21
+ example "subtracting a number" do
22
+ puts "5 - 1 = %s" % (5 - 1 )
23
+ end
24
+
25
+ example "error catching" do
26
+ # this should be caught by our custom error rescuer
27
+ puts "5 / 0 = %s" % (5 / 0)
28
+ end
@@ -0,0 +1,55 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{exemplar}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dmitry Ratnikov"]
12
+ s.date = %q{2010-08-16}
13
+ s.email = %q{ratnikov@gmail.com}
14
+ s.extra_rdoc_files = [
15
+ "README.rdoc"
16
+ ]
17
+ s.files = [
18
+ ".gitignore",
19
+ "Gemfile",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "VERSION.yml",
23
+ "examples/algebra.rb",
24
+ "exemplar.gemspec",
25
+ "lib/exemplar.rb",
26
+ "lib/exemplar/example.rb",
27
+ "lib/exemplar/loggable.rb",
28
+ "lib/exemplar/runner.rb",
29
+ "test/example_test.rb",
30
+ "test/runner_test.rb",
31
+ "test/test_helper.rb"
32
+ ]
33
+ s.homepage = %q{http://github.com/ratnikov/exemplar}
34
+ s.rdoc_options = ["--charset=UTF-8"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.3.7}
37
+ s.summary = %q{Makes writing examples easy and fun}
38
+ s.test_files = [
39
+ "test/example_test.rb",
40
+ "test/runner_test.rb",
41
+ "test/test_helper.rb",
42
+ "examples/algebra.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ else
51
+ end
52
+ else
53
+ end
54
+ end
55
+
@@ -0,0 +1,3 @@
1
+ require 'exemplar/loggable'
2
+ require 'exemplar/example'
3
+ require 'exemplar/runner'
@@ -0,0 +1,58 @@
1
+ module Exemplar
2
+ class Example
3
+ include Loggable
4
+
5
+ class << self
6
+ def before_callbacks
7
+ @before_callbacks ||= []
8
+ end
9
+
10
+ def before(*before_methods)
11
+ before_callbacks.push *before_methods
12
+ end
13
+
14
+ def examples
15
+ @examples ||= []
16
+ end
17
+ end
18
+
19
+ attr_reader :name, :options, :block
20
+
21
+ def initialize(name, options, block)
22
+ @name, @options, @block = name, options, block
23
+
24
+ self.class.examples << self
25
+ end
26
+
27
+ def run
28
+ log "Running example #{name}..."
29
+
30
+ block_return = run_before_callbacks && block.call(self)
31
+
32
+ log "Done running example #{name}"
33
+
34
+ block_return
35
+ rescue Exception => error
36
+ rescue_error(error)
37
+ end
38
+
39
+ private
40
+
41
+ def rescue_error(error)
42
+ log "Whoops, seems like something went wrong. Here's the error message: %s." % error.message
43
+ nil
44
+ end
45
+
46
+ def run_before_callbacks
47
+ self.class.before_callbacks.all? { |callback| send(callback) }
48
+ end
49
+
50
+ def runner
51
+ Exemplar::Runner
52
+ end
53
+ end
54
+ end
55
+
56
+ def example(name, options = nil, &block)
57
+ Exemplar::Example.new(name, options, block)
58
+ end
@@ -0,0 +1,17 @@
1
+ module Exemplar
2
+ module Loggable
3
+ class << self
4
+ def log?
5
+ @log.nil? ? true : @log
6
+ end
7
+
8
+ def log=(log)
9
+ @log = log
10
+ end
11
+ end
12
+
13
+ def log(message)
14
+ puts message if Loggable.log?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ require 'optparse'
2
+
3
+ module Exemplar
4
+ class Runner
5
+ attr_reader :examples
6
+
7
+ def initialize(examples, options = nil)
8
+ @examples = examples
9
+ @match_regex = options && options[:match]
10
+ end
11
+
12
+ def run
13
+ examples.select { |example| run?(example) }.each { |example| example.run }
14
+ end
15
+
16
+ def run?(example)
17
+ @match_regex.nil? || example.name =~ @match_regex
18
+ end
19
+
20
+ def self.parse_options!(argv)
21
+ options = {}
22
+
23
+ OptionParser.new do |opt|
24
+ opt.banner = "Exemplar automatic example runner.\n"
25
+ opt.banner << "Usage: #{$0} [options]"
26
+
27
+ opt.on
28
+ opt.on("-e", "--example [REGEX]", "Run examples matching the regex.") do |regex|
29
+ options[:match] = Regexp.new(regex)
30
+ end
31
+
32
+ opt.on_tail
33
+ end.parse!(argv)
34
+
35
+ options
36
+ rescue OptionParser::ParseError => e
37
+ puts "%s. Run `#{$0} --help` for help." % e
38
+ exit false
39
+ end
40
+ end
41
+ end
42
+
43
+ Kernel.at_exit do
44
+ Exemplar::Runner.new(Exemplar::Example.examples, Exemplar::Runner.parse_options!(ARGV)).run
45
+ end
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+
3
+ module Exemplar
4
+ class ExampleTest < Test::Unit::TestCase
5
+ def test_declaring_example
6
+ test_example = example("test example", :foo => 'bar') { }
7
+
8
+ assert_equal 'test example', test_example.name
9
+ assert_equal({ :foo => 'bar' }, test_example.options)
10
+
11
+ assert_equal [ test_example ], Example.examples, "Should register the example with the runner"
12
+ end
13
+
14
+ def test_running_example
15
+ test_example = example("test example") { |example| self.invoke_something(example); :block_return }
16
+
17
+ mock( self ).invoke_something(test_example)
18
+
19
+ assert_equal :block_return, test_example.run, "Should run the example block and return whatever it returns"
20
+ end
21
+
22
+ def test_before_callback
23
+ Example.before :do_foo
24
+
25
+ assert_equal [ :do_foo ], Example.before_callbacks, "Should register a callback"
26
+
27
+ example = example("test example") { :block_return }
28
+
29
+ mock( example ).do_foo.returns true
30
+
31
+ assert_equal :block_return, example.run
32
+ end
33
+
34
+ def test_before_callback_cancellation
35
+ Example.before :false_callback
36
+
37
+ example = example("test example") { flunk("Wasn't supposed to be run") }
38
+
39
+ mock( example ).false_callback.returns false
40
+
41
+ assert_equal false, example.run, "Should return that example failed to run"
42
+ end
43
+
44
+ def test_exception_handling
45
+ error = Exception.new "bad error"
46
+
47
+ example = example("erroring example") { raise error }
48
+
49
+ mock( example ).rescue_error(error).returns :rescue_return
50
+
51
+ assert_equal :rescue_return, example.run, "should return whatever rescue returned"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+
3
+ module Exemplar
4
+ class RunnerTest < Test::Unit::TestCase
5
+ def test_examples_running
6
+ run_examples = []
7
+
8
+ example1 = example("first test example") { |e| run_examples << e }
9
+ example2 = example("second test example") { |e| run_examples << e }
10
+
11
+ Runner.new([ example1, example2 ]).run
12
+
13
+ assert_equal [ example1, example2 ], run_examples, "Should run the examples in order declared"
14
+ end
15
+
16
+ def test_example_regex
17
+ foo = example("a foo example") { }
18
+ bar = example("a bar example") { }
19
+
20
+ # should run foo, but not run bar
21
+ mock( foo ).run.once
22
+ mock( bar ).run.never
23
+
24
+ Runner.new([ foo, bar], { :match => /foo/ }).run
25
+ end
26
+
27
+ def test_parse_options!
28
+ assert_equal({ :match => /foo bar/ }, Runner.parse_options!([ '-e', 'foo bar' ]))
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,43 @@
1
+
2
+ begin
3
+ require 'bundler'
4
+
5
+ Bundler.setup
6
+ rescue LoadError => error
7
+ warn "Bundler doesn't seem to be installed. Please install bundler and run: bundle install"
8
+ exit
9
+ end
10
+
11
+ require 'test/unit'
12
+ require 'rr'
13
+
14
+ require 'exemplar'
15
+
16
+ # disable the logging for the tests
17
+ Exemplar::Loggable.log = false
18
+
19
+ class << Exemplar::Runner
20
+
21
+ # stub out the option parsing to make sure it doesn't conflict with test/unit options
22
+ # Yea, it's ugly... :(
23
+ alias_method :default_parse_options!, :parse_options!
24
+ def parse_options!(args)
25
+ args == ARGV ? { } : default_parse_options!(args)
26
+ end
27
+ end
28
+
29
+ class Test::Unit::TestCase
30
+ include RR::Adapters::TestUnit
31
+
32
+ setup
33
+ def setup_examples
34
+ # make sure there aren't any lingering examples declared
35
+ Exemplar::Example.examples.clear
36
+ end
37
+
38
+ teardown
39
+ def teardown_callbacks
40
+ # clear the callbacks to avoid future test breakage
41
+ Exemplar::Example.before_callbacks.clear
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: exemplar
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Dmitry Ratnikov
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-08-16 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description:
22
+ email: ratnikov@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ files:
30
+ - .gitignore
31
+ - Gemfile
32
+ - README.rdoc
33
+ - Rakefile
34
+ - VERSION.yml
35
+ - examples/algebra.rb
36
+ - exemplar.gemspec
37
+ - lib/exemplar.rb
38
+ - lib/exemplar/example.rb
39
+ - lib/exemplar/loggable.rb
40
+ - lib/exemplar/runner.rb
41
+ - test/example_test.rb
42
+ - test/runner_test.rb
43
+ - test/test_helper.rb
44
+ has_rdoc: true
45
+ homepage: http://github.com/ratnikov/exemplar
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --charset=UTF-8
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.7
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Makes writing examples easy and fun
76
+ test_files:
77
+ - test/example_test.rb
78
+ - test/runner_test.rb
79
+ - test/test_helper.rb
80
+ - examples/algebra.rb