tack 0.0.0 → 0.0.1

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.
@@ -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