tack 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  = tack
2
2
 
3
- Description goes here.
3
+ USE AT YOUR OWN RISK. This is highly experimental and the interface is changing rapidly.
4
4
 
5
5
  == Note on Patches/Pull Requests
6
6
 
@@ -13,6 +13,10 @@ Description goes here.
13
13
  bump version in a commit by itself I can ignore when I pull)
14
14
  * Send me a pull request. Bonus points for topic branches.
15
15
 
16
+ == Acknowledgements
17
+
18
+ Tack is heavily inspired by Rack and Faraday and borrows ideas and code from both. Early versions of the Test::Unit and RSpec adapters borrowed code from Hydra.
19
+
16
20
  == Copyright
17
21
 
18
22
  Copyright (c) 2010 Ben Brinckerhoff. See LICENSE for details.
data/Rakefile CHANGED
@@ -10,7 +10,9 @@ begin
10
10
  gem.email = "ben@bbrinck.com"
11
11
  gem.homepage = "http://github.com/bhb/tack"
12
12
  gem.authors = ["Ben Brinckerhoff"]
13
+ gem.add_dependency "test-unit", "~> 1.0" if RUBY_VERSION=~/1\.9/
13
14
  gem.add_development_dependency "shoulda"
15
+ gem.add_development_dependency "test-construct"
14
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
17
  end
16
18
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'tack'
5
+ require 'pp'
6
+ require 'optparse'
7
+
8
+ def require_ruby_debug
9
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
10
+ require 'ruby-debug'
11
+ end
12
+
13
+ options = {}
14
+ option_parser = OptionParser.new do |opts|
15
+ opts.banner = "Usage: tack [options] [file]"
16
+ opts.on("-I","--include PATH", "specify $LOAD_PATH (may be used more than once)") do |path|
17
+ options[:include] = path.split(":")
18
+ end
19
+ opts.on("-n", "--name PATTERN", "run only tests that match pattern") do |pattern|
20
+ if pattern=~/^\/.*\/$/
21
+ options[:pattern] = Regexp.new(pattern[1..-2])
22
+ else
23
+ options[:pattern] = pattern
24
+ end
25
+ end
26
+ opts.on("-u", "--debugger", "Enable ruby-debugging.") do
27
+ require_ruby_debug
28
+ end
29
+ opts.on_tail("-h","--help", "Show this message") do
30
+ puts opts
31
+ exit
32
+ end
33
+ end
34
+
35
+ args = ARGV
36
+ option_parser.parse! args
37
+ options[:paths] = ARGV
38
+
39
+ if includes = options[:include]
40
+ $LOAD_PATH.unshift *includes
41
+ end
42
+
43
+ runner = Tack::Runner.new(:root => Dir.pwd) do |runner|
44
+ runner.use Tack::Formatters::Profiler, :tests => 3
45
+ runner.use Tack::Formatters::TotalTime
46
+ runner.use Tack::Formatters::PrintFailures
47
+ runner.use Tack::Formatters::BasicSummary
48
+ runner.use Tack::Formatters::ProgressBar
49
+ end
50
+
51
+ set = Tack::TestSet.new(Dir.pwd)
52
+ tests = set.tests_for(options[:paths], Tack::TestPattern.new(options[:pattern]))
53
+
54
+ runner.run(tests)
55
+
56
+ exit 0
57
+
58
+
59
+
@@ -0,0 +1,30 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ module Tack
5
+
6
+ autoload :Runner, 'tack/runner'
7
+ autoload :TestSet, 'tack/test_set'
8
+ autoload :Middleware, 'tack/middleware'
9
+ autoload :TestPattern, 'tack/test_pattern'
10
+
11
+
12
+ module Adapters
13
+
14
+ autoload :Adapter, 'tack/adapters/adapter'
15
+ autoload :RSpecAdapter, 'tack/adapters/rspec_adapter'
16
+ autoload :TestUnitAdapter, 'tack/adapters/test_unit_adapter'
17
+
18
+ end
19
+
20
+ module Formatters
21
+
22
+ autoload :BasicSummary, 'tack/formatters/basic_summary'
23
+ autoload :ProgressBar, 'tack/formatters/progress_bar'
24
+ autoload :Profiler, 'tack/formatters/profiler'
25
+ autoload :TotalTime, 'tack/formatters/total_time'
26
+ autoload :PrintFailures, 'tack/formatters/print_failures'
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,25 @@
1
+ module Tack
2
+
3
+ module Adapters
4
+
5
+ class Adapter
6
+
7
+ def self.for(path)
8
+ # Using a simple path-based heuristic for now
9
+ case path
10
+ when /test.rb$/
11
+ TestUnitAdapter.new
12
+ when /spec.rb$/
13
+ RSpecAdapter.new
14
+ else
15
+ raise "Cannot determine an adapter for path #{path}"
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+
@@ -0,0 +1,106 @@
1
+ require 'spec'
2
+ require 'spec/runner/formatter/base_formatter'
3
+
4
+ if defined?(Spec)
5
+ module Spec
6
+ module Runner
7
+ class << self
8
+ # stop the auto-run at_exit
9
+ def run
10
+ return 0
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ module Spec
18
+ module Runner
19
+ module Formatter
20
+ # Stolen from Hydra for now
21
+ class TackFormatter < BaseFormatter
22
+
23
+ attr_accessor :results
24
+
25
+ def initialize(options)
26
+ io = StringIO.new # suppress output
27
+ super(options, io)
28
+ @results = { :passed => [],
29
+ :failed => [],
30
+ :pending => []}
31
+ end
32
+
33
+ # Stifle the output of pending examples
34
+ def example_pending(example)
35
+ @results[:pending] << {
36
+ :description => example.description,
37
+ }
38
+ end
39
+
40
+ def example_passed(example)
41
+ @results[:passed] << {
42
+ :description => example.description,
43
+ }
44
+ end
45
+
46
+ def example_failed(example, counter, error=nil)
47
+ @results[:failed] <<
48
+ {
49
+ :description => example.description,
50
+ :failure => build_failure(example, error)
51
+ }
52
+ end
53
+
54
+ private
55
+
56
+ def build_failure(example, error)
57
+ case error.exception
58
+ when Spec::Expectations::ExpectationNotMetError
59
+ { :message => error.exception.message,
60
+ :backtrace => error.exception.backtrace}
61
+ else
62
+ { :message => "#{error.exception.class} was raised: #{error.exception.message}",
63
+ :backtrace => error.exception.backtrace}
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ module Tack
73
+
74
+ module Adapters
75
+
76
+ class RSpecAdapter
77
+
78
+ def tests_for(file, pattern)
79
+ Spec::Runner.options.instance_variable_set(:@formatters, [Spec::Runner::Formatter::TackFormatter.new(Spec::Runner.options.formatter_options)])
80
+ Spec::Runner.options.instance_variable_set(:@example_groups, [])
81
+ Spec::Runner.options.instance_variable_set(:@files, [file])
82
+ Spec::Runner.options.instance_variable_set(:@files_loaded, false)
83
+ runner = Spec::Runner::ExampleGroupRunner.new(Spec::Runner.options)
84
+ runner.load_files([file])
85
+ example_groups = runner.send(:example_groups)
86
+ examples = example_groups.inject([]) do |arr, group|
87
+ arr += group.examples
88
+ end
89
+ examples.map {|example| [file, example.description]}.select {|file,description| description.match(pattern)}
90
+ end
91
+
92
+ def run(file, test)
93
+ Spec::Runner.options.instance_variable_set(:@examples, [test])
94
+ Spec::Runner.options.instance_variable_set(:@example_groups, [])
95
+ Spec::Runner.options.instance_variable_set(:@files, [file])
96
+ Spec::Runner.options.instance_variable_set(:@files_loaded, false)
97
+ formatter = Spec::Runner::Formatter::TackFormatter.new(Spec::Runner.options.formatter_options)
98
+ Spec::Runner.options.instance_variable_set(:@formatters, [formatter])
99
+ Spec::Runner.options.run_examples
100
+ formatter.results
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,114 @@
1
+ if RUBY_VERSION=~/1.9/
2
+ gem 'test-unit', '~> 1.0'
3
+ end
4
+ require 'test/unit'
5
+ require 'test/unit/testresult'
6
+
7
+ Test::Unit.run = true
8
+
9
+ module Tack
10
+
11
+ module Adapters
12
+
13
+ class TestUnitAdapter
14
+
15
+ def tests_for(file, pattern)
16
+ require file
17
+ classes = test_classes_for(file)
18
+ classes.inject([]) do |tests, klass|
19
+ tests += test_methods(klass).map {|method_name| [file, method_name.to_s]}.select {|file, method_name| method_name.match(pattern)}
20
+ end
21
+ end
22
+
23
+ def run(path, description)
24
+ results = { :passed => [],
25
+ :failed => [],
26
+ :pending => []}
27
+ require(path)
28
+ # Note that this won't work if there are multiple classes in a file
29
+ klass = test_classes_for(path).first
30
+ test = klass.new(description)
31
+ result = Test::Unit::TestResult.new
32
+
33
+ result.add_listener(Test::Unit::TestResult::FAULT) do |failure|
34
+ results[:failed] << build_result(description, failure)
35
+ end
36
+
37
+ test.run(result) do |started,name|
38
+ # We do nothing here
39
+ # but this method requires a block
40
+ end
41
+ if result.passed?
42
+ results[:passed] << build_result(description)
43
+ end
44
+ results
45
+ end
46
+
47
+ private
48
+
49
+ def build_result(description, failure=nil)
50
+ { :description => description,
51
+ :failure => build_failure(failure) }
52
+ end
53
+
54
+ def build_failure(failure)
55
+ return {} if failure.nil?
56
+ case failure
57
+ when Test::Unit::Error
58
+ { :message => "#{failure.exception.class} was raised: #{failure.exception.message}",
59
+ :backtrace => failure.exception.backtrace }
60
+ else
61
+ { :message => failure.message,
62
+ :backtrace => failure.location }
63
+ end
64
+ end
65
+
66
+ def test_classes_for(file)
67
+ # taken from from hydra
68
+ #code = ""
69
+ # File.open(file) {|buffer| code = buffer.read}
70
+ code = File.read(file)
71
+ matches = code.scan(/class\s+([\S]+)/)
72
+ klasses = matches.collect do |c|
73
+ begin
74
+ if c.first.respond_to? :constantize
75
+ c.first.constantize
76
+ else
77
+ eval(c.first)
78
+ end
79
+ rescue NameError
80
+ # means we could not load [c.first], but thats ok, its just not
81
+ # one of the classes we want to test
82
+ nil
83
+ rescue SyntaxError
84
+ # see above
85
+ nil
86
+ end
87
+ end
88
+ return klasses.select{|k| k.respond_to? 'suite'}
89
+ end
90
+
91
+ def test_methods(test_class)
92
+ test_class.instance_methods.select do |method_name|
93
+ method_name =~ /^test./ &&
94
+ (test_class.instance_method(method_name).arity == 0 ||
95
+ test_class.instance_method(method_name).arity == -1
96
+ )
97
+ end
98
+ end
99
+
100
+ def get_test_classes
101
+ test_classes = []
102
+ ObjectSpace.each_object(Class) do |klass|
103
+ if(Test::Unit::TestCase > klass)
104
+ test_classes << klass
105
+ end
106
+ end
107
+ test_classes
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,22 @@
1
+ module Tack
2
+
3
+ module Formatters
4
+
5
+ class BasicSummary
6
+ include Middleware
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def run_suite(tests)
13
+ returning @app.run_suite(tests) do |results|
14
+ puts "%d tests, %d failures, %d pending" % [results.values.flatten.length, results[:failed].length, results[:pending].length]
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,43 @@
1
+ module Tack
2
+
3
+ module Formatters
4
+
5
+ class PrintFailures
6
+ include Middleware
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def run_suite(tests)
13
+ returning @app.run_suite(tests) do |results|
14
+ results[:failed].each_with_index do |result, index|
15
+ print_failure(index+1, result)
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def format_backtrace(backtrace)
23
+ return "" if backtrace.nil?
24
+ "["+backtrace.map { |line| backtrace_line(line) }.join("\n")+"]:"
25
+ end
26
+
27
+ def backtrace_line(line)
28
+ line.sub(/\A([^:]+:\d+)$/, '\\1:')
29
+ end
30
+
31
+ def print_failure(counter, result)
32
+ puts
33
+ puts "#{counter.to_s})"
34
+ puts result[:description]
35
+ puts format_backtrace(result[:failure][:backtrace])
36
+ puts result[:failure][:message]
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,39 @@
1
+ module Tack
2
+
3
+ module Formatters
4
+
5
+ class Profiler
6
+ include Middleware
7
+
8
+ def initialize(app, args)
9
+ @app = app
10
+ @num_tests = args.fetch(:tests) { 10 }
11
+ @times = []
12
+ end
13
+
14
+ def run_suite(tests)
15
+ returning @app.run_suite(tests) do |results|
16
+ puts "\n\nTop #{@num_tests} slowest examples:\n"
17
+ @times = @times.sort_by do |description, time|
18
+ time
19
+ end.reverse
20
+ @times[0..@num_tests-1].each do |description, time|
21
+ print "%.7f" % time
22
+ puts " #{description}"
23
+ end
24
+ end
25
+ end
26
+
27
+ def run_test(file, description)
28
+ time = Time.now
29
+ returning @app.run_test(file,description) do
30
+ @times << [description, Time.now - time]
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,36 @@
1
+ module Tack
2
+
3
+ module Formatters
4
+
5
+ class ProgressBar
6
+ include Middleware
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def run_suite(tests)
13
+ returning @app.run_suite(tests) do
14
+ puts
15
+ end
16
+ end
17
+
18
+ def run_test(file, description)
19
+ returning @app.run_test(file, description) do |result|
20
+ result[:passed].each do
21
+ print "."
22
+ end
23
+ result[:pending].each do
24
+ print "P"
25
+ end
26
+ result[:failed].each do
27
+ print "F"
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,23 @@
1
+ module Tack
2
+
3
+ module Formatters
4
+
5
+ class TotalTime
6
+ include Middleware
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def run_suite(tests)
13
+ time = Time.now
14
+ returning @app.run_suite(tests) do
15
+ puts "Finished in %.7f seconds." % (Time.now - time)
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,22 @@
1
+ module Tack
2
+
3
+ module Middleware
4
+
5
+ def run_suite(tests)
6
+ @app.run_suite(tests)
7
+ end
8
+
9
+ def run_test(file, description)
10
+ @app.run_test(file, description)
11
+ end
12
+
13
+ # not necessary for the middleware API, but handy for implementing
14
+ # middleware methods
15
+ def returning(value)
16
+ yield(value)
17
+ value
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,50 @@
1
+ module Tack
2
+
3
+ class Runner
4
+
5
+ def initialize(args)
6
+ if(args.is_a?(Hash))
7
+ @root_dir = args.fetch(:root)
8
+ else
9
+ @root_dir = args
10
+ end
11
+ @handlers = []
12
+ yield self if block_given?
13
+ end
14
+
15
+ def run(tests)
16
+ to_app if @start_app.nil?
17
+ @start_app.run_suite(tests)
18
+ end
19
+
20
+ def run_suite(tests)
21
+ results = { :passed => [],
22
+ :failed => [],
23
+ :pending => []}
24
+ tests.each do |path, description|
25
+ result = @start_app.run_test(path, description)
26
+ results[:passed] += result[:passed]
27
+ results[:failed] += result[:failed]
28
+ results[:pending] += result[:pending]
29
+ end
30
+ results
31
+ end
32
+
33
+ def run_test(path, description)
34
+ adapter = Adapters::Adapter.for(path)
35
+ adapter.run(path, description)
36
+ end
37
+
38
+ def use(middleware, *args, &block)
39
+ @handlers << lambda { |app|
40
+ middleware.new(app, *args, &block) }
41
+ end
42
+
43
+ def to_app
44
+ inner_app = self
45
+ @start_app = @handlers.reverse.inject(inner_app) { |a, e| e.call(a) }
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,21 @@
1
+ module Tack
2
+
3
+ class TestPattern < Regexp
4
+
5
+ DEFAULT = /.*/
6
+
7
+ def initialize(pattern=nil)
8
+ pattern = case pattern
9
+ when nil
10
+ DEFAULT
11
+ when String, Regexp
12
+ pattern
13
+ else
14
+ DEFAULT
15
+ end
16
+ super(pattern)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,39 @@
1
+ module Tack
2
+
3
+ class TestSet
4
+
5
+ def initialize(root_dir)
6
+ @root_dir = root_dir
7
+ end
8
+
9
+ def tests_for(paths, pattern=TestPattern.new)
10
+ paths = Array(paths).map { |path| path.to_s}
11
+ files = paths.inject([]) do |files, path|
12
+ if File.directory?(path)
13
+ files += Dir[File.join(path,"**/*")].select {|f| valid_test_file?(f)}
14
+ else
15
+ files << path
16
+ end
17
+ end
18
+
19
+ files.inject([]) do |tests, file|
20
+ adapter = Adapters::Adapter.for(file)
21
+ tests += adapter.tests_for(file, pattern)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def valid_test_file?(path)
28
+ return false if File.directory?(path)
29
+ case path
30
+ when /_test.rb$/, /_spec.rb$/
31
+ true
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,134 @@
1
+ require 'test_helper'
2
+
3
+ class RSpecTest < Test::Unit::TestCase
4
+
5
+ def with_rspec_context(args)
6
+ body = args.fetch(:body)
7
+ describe = args.fetch(:describe)
8
+ within_construct(false) do |c|
9
+ file_name = 'fake_spec.rb'
10
+ c.file file_name do
11
+ <<-EOS
12
+ describe #{describe} do
13
+
14
+ #{body}
15
+
16
+ end
17
+ EOS
18
+ end
19
+ path = c+file_name.to_s
20
+ yield path
21
+ end
22
+ end
23
+
24
+ should "grab all specs" do
25
+ body = <<-EOS
26
+ specify "something" do
27
+ end
28
+
29
+ it "should do something" do
30
+ end
31
+ EOS
32
+ with_rspec_context :describe => String, :body => body do |path|
33
+ set = Tack::TestSet.new(path.parent)
34
+ tests = set.tests_for(path)
35
+ assert_equal 2, tests.length
36
+ assert_equal [path.to_s, "something"], tests.sort.last
37
+ assert_equal [path.to_s, "should do something"], tests.sort.first
38
+ end
39
+ end
40
+
41
+ should "find specs that match substring" do
42
+ body = <<-EOS
43
+ specify "something" do
44
+ end
45
+
46
+ it "does nothing" do
47
+ end
48
+ EOS
49
+ with_rspec_context :describe => String, :body => body do |path|
50
+ set = Tack::TestSet.new(path.parent)
51
+ tests = set.tests_for(path, "some")
52
+ assert_equal 1, tests.length
53
+ assert_equal [path.to_s, "something"], tests.sort.first
54
+ end
55
+ end
56
+
57
+ should "find specs that match regular expression" do
58
+ body = <<-EOS
59
+ specify "something" do
60
+ end
61
+
62
+ it "does nothing" do
63
+ end
64
+ EOS
65
+ with_rspec_context :describe => String, :body => body do |path|
66
+ set = Tack::TestSet.new(path.parent)
67
+ tests = set.tests_for(path, /does/)
68
+ assert_equal 1, tests.length
69
+ assert_equal [path.to_s, "does nothing"], tests.sort.first
70
+ end
71
+ end
72
+
73
+ should "run failing spec" do
74
+ body = <<-EOS
75
+ specify "append length is sum of component string lengths" do
76
+ ("ab"+"cd").length.should == ("ab".length - "cd".length)
77
+ end
78
+ EOS
79
+ with_rspec_context :describe => String, :body => body do |path|
80
+ set = Tack::TestSet.new(path.parent)
81
+ tests = set.tests_for(path)
82
+ runner = Tack::Runner.new(path.parent)
83
+ results = runner.run(tests)
84
+
85
+ assert_equal 0, results[:passed].length
86
+ assert_equal 1, results[:failed].length
87
+ result = results[:failed].first
88
+ assert_equal "append length is sum of component string lengths", result[:description]
89
+ assert_equal "expected: 0,\n got: 4 (using ==)", result[:failure][:message]
90
+ assert_kind_of Array, result[:failure][:backtrace]
91
+ end
92
+ end
93
+
94
+ should "run spec that raises error" do
95
+ body = <<-EOS
96
+ specify "append length is sum of component string lengths" do
97
+ raise "failing!"
98
+ end
99
+ EOS
100
+ with_rspec_context :describe => String, :body => body do |path|
101
+ set = Tack::TestSet.new(path.parent)
102
+ tests = set.tests_for(path)
103
+ runner = Tack::Runner.new(path.parent)
104
+ results = runner.run(tests)
105
+
106
+ assert_equal 0, results[:passed].length
107
+ assert_equal 1, results[:failed].length
108
+
109
+ result = results[:failed].first
110
+ assert_equal "append length is sum of component string lengths", result[:description]
111
+ assert_match /was raised/, result[:failure][:message]
112
+ assert_kind_of Array, result[:failure][:backtrace]
113
+ end
114
+ end
115
+
116
+ should "run successful spec" do
117
+ body = <<-EOS
118
+ specify "append length is sum of component string lengths" do
119
+ ("ab"+"cd").length.should == ("ab".length + "cd".length)
120
+ end
121
+ EOS
122
+ with_rspec_context :describe => String, :body => body do |path|
123
+ set = Tack::TestSet.new(path.parent)
124
+ tests = set.tests_for(path)
125
+ runner = Tack::Runner.new(path.parent)
126
+ results = runner.run(tests)
127
+
128
+ assert_equal 1, results[:passed].length
129
+ assert_equal 0, results[:failed].length
130
+ assert_equal "append length is sum of component string lengths", results[:passed].first[:description]
131
+ end
132
+ end
133
+
134
+ end
@@ -0,0 +1,139 @@
1
+ require 'test_helper'
2
+
3
+ class TestUnitTest < Test::Unit::TestCase
4
+
5
+ def remove_test_class_definition(class_name)
6
+ Object.send(:remove_const, class_name) if Object.const_defined?(class_name)
7
+ end
8
+
9
+ def with_test_class(args)
10
+ body = args.fetch(:body)
11
+ class_name = args.fetch(:class_name) { :FakeTest }
12
+ within_construct(false) do |c|
13
+ begin
14
+ file = c.file 'fake_test.rb' do
15
+ <<-EOS
16
+ require 'test/unit'
17
+
18
+ class #{class_name} < Test::Unit::TestCase
19
+
20
+ #{body}
21
+
22
+ end
23
+ EOS
24
+ end
25
+ path = c + file.to_s
26
+ yield file.to_s, path
27
+ ensure
28
+ remove_test_class_definition(class_name)
29
+ end
30
+ end
31
+ end
32
+
33
+ should "grab all tests" do
34
+ body =<<-EOS
35
+ def test_one
36
+ end
37
+
38
+ def test_two
39
+ end
40
+ EOS
41
+ with_test_class(:body => body) do |file_name, path|
42
+ set = Tack::TestSet.new(path.parent)
43
+ tests = set.tests_for(path)
44
+ assert_equal 2, tests.length
45
+ assert_equal [file_name, "test_one"], tests.sort.first
46
+ assert_equal [file_name, "test_two"], tests.sort.last
47
+ end
48
+ end
49
+
50
+ should "find tests that match substring" do
51
+ body=<<-EOS
52
+ def test_one
53
+ end
54
+ def test_two
55
+ end
56
+ EOS
57
+ with_test_class(:body => body) do |file_name, path|
58
+ set = Tack::TestSet.new(path.parent)
59
+ tests = set.tests_for(path, "two")
60
+ assert_equal 1, tests.length
61
+ assert_equal [file_name, "test_two"], tests.sort.first
62
+ end
63
+ end
64
+
65
+ should "find tests that match regular expression" do
66
+ body=<<-EOS
67
+ def test_one
68
+ end
69
+ def test_two
70
+ end
71
+ EOS
72
+ with_test_class(:body => body) do |file_name, path|
73
+ set = Tack::TestSet.new(path.parent)
74
+ tests = set.tests_for(path, /two/)
75
+ assert_equal 1, tests.length
76
+ assert_equal [file_name, "test_two"], tests.sort.first
77
+ end
78
+ end
79
+
80
+ should "run failing test" do
81
+ body =<<-EOS
82
+ def test_append_length
83
+ assert_equal ("ab".length - "cd".length), ("ab"+"cd").length
84
+ end
85
+ EOS
86
+ with_test_class(:body => body) do |file_name, path|
87
+ set = Tack::TestSet.new(path.parent)
88
+ tests = set.tests_for(path)
89
+ runner = Tack::Runner.new(path.parent)
90
+ results = runner.run(tests)
91
+
92
+ assert_equal 0, results[:passed].length
93
+ assert_equal 1, results[:failed].length
94
+ result = results[:failed].first
95
+ assert_equal "test_append_length", result[:description]
96
+ assert_match /expected but was/, result[:failure][:message]
97
+ assert_kind_of Array, result[:failure][:backtrace]
98
+ end
99
+ end
100
+
101
+ should "run test with error" do
102
+ body =<<-EOS
103
+ def test_append_length
104
+ raise "failing!"
105
+ end
106
+ EOS
107
+ with_test_class(:body => body) do |file_name, path|
108
+ set = Tack::TestSet.new(path.parent)
109
+ tests = set.tests_for(path)
110
+ runner = Tack::Runner.new(path.parent)
111
+ results = runner.run(tests)
112
+
113
+ assert_equal 0, results[:passed].length
114
+ assert_equal 1, results[:failed].length
115
+ result = results[:failed].first
116
+ assert_equal "test_append_length", result[:description]
117
+ assert_match /was raised/, result[:failure][:message]
118
+ assert_kind_of Array, result[:failure][:backtrace]
119
+ end
120
+ end
121
+
122
+ should "run successful test" do
123
+ body =<<-EOS
124
+ def test_append_length
125
+ assert_equal ("ab".length + "cd".length), ("ab"+"cd").length
126
+ end
127
+ EOS
128
+ with_test_class(:body => body) do |file_name, path|
129
+ set = Tack::TestSet.new(path.parent)
130
+ tests = set.tests_for(path)
131
+ runner = Tack::Runner.new(path.parent)
132
+ results = runner.run(tests)
133
+ assert_equal 1, results[:passed].length
134
+ assert_equal 0, results[:failed].length
135
+ assert_equal "test_append_length", results[:passed].first[:description]
136
+ end
137
+ end
138
+
139
+ end
@@ -1,7 +1,9 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class TackTest < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
4
+
5
+ should "do whatever" do
6
+ # nothing here for now
6
7
  end
8
+
7
9
  end
@@ -1,10 +1,13 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'shoulda'
4
+ require 'construct'
5
+ require 'ruby-debug'
4
6
 
5
7
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
8
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
9
  require 'tack'
8
10
 
9
11
  class Test::Unit::TestCase
12
+ include Construct::Helpers
10
13
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 0
9
- version: 0.0.0
8
+ - 1
9
+ version: 0.0.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ben Brinckerhoff
@@ -14,8 +14,8 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-04 00:00:00 -06:00
18
- default_executable:
17
+ date: 2010-06-07 00:00:00 -06:00
18
+ default_executable: tack
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: shoulda
@@ -29,10 +29,22 @@ dependencies:
29
29
  version: "0"
30
30
  type: :development
31
31
  version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: test-construct
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :development
43
+ version_requirements: *id002
32
44
  description: A Rack-inspired interface for testing libraries
33
45
  email: ben@bbrinck.com
34
- executables: []
35
-
46
+ executables:
47
+ - tack
36
48
  extensions: []
37
49
 
38
50
  extra_rdoc_files:
@@ -45,7 +57,22 @@ files:
45
57
  - README.rdoc
46
58
  - Rakefile
47
59
  - VERSION
60
+ - bin/tack
48
61
  - lib/tack.rb
62
+ - lib/tack/adapters/adapter.rb
63
+ - lib/tack/adapters/rspec_adapter.rb
64
+ - lib/tack/adapters/test_unit_adapter.rb
65
+ - lib/tack/formatters/basic_summary.rb
66
+ - lib/tack/formatters/print_failures.rb
67
+ - lib/tack/formatters/profiler.rb
68
+ - lib/tack/formatters/progress_bar.rb
69
+ - lib/tack/formatters/total_time.rb
70
+ - lib/tack/middleware.rb
71
+ - lib/tack/runner.rb
72
+ - lib/tack/test_pattern.rb
73
+ - lib/tack/test_set.rb
74
+ - test/acceptance/rspec_test.rb
75
+ - test/acceptance/test_unit_test.rb
49
76
  - test/tack_test.rb
50
77
  - test/test_helper.rb
51
78
  has_rdoc: true
@@ -79,5 +106,7 @@ signing_key:
79
106
  specification_version: 3
80
107
  summary: A Rack-inspired interface for testing libraries
81
108
  test_files:
109
+ - test/acceptance/rspec_test.rb
110
+ - test/acceptance/test_unit_test.rb
82
111
  - test/tack_test.rb
83
112
  - test/test_helper.rb