exemplar 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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