lineman 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ `lineman` is a test runner for
2
+ [test-unit](https://github.com/test-unit/test-unit) that prints a line per test,
3
+ with statistics about its performance.
4
+
5
+ Example output:
6
+
7
+ NPCRobotTest
8
+ test: should have a cool nickname 0:1 0.01 N
9
+ test: should have big birthday party 1:1 0.00
10
+ test: should have pizzas for party 0:0 0.00 ON
11
+ test: should not dance 0:0 0.00 P
12
+ NPCRobotTest 1:2 0.01 PON
13
+ test/npc_robot_test 1:2 0.01 PON
14
+
15
+ ========
16
+ Failures
17
+ ========
18
+
19
+ 1) Failure:
20
+ test: should have a cool nickname(NPCRobotTest) [test/npc_robot_test.rb:30]:
21
+ <"claptrap"> expected but was
22
+ <"Claptrap">.
23
+
24
+ diff:
25
+ - claptrap
26
+ ? ^
27
+ + Claptrap
28
+ ? ^
29
+
30
+ 2) Failure:
31
+ test: should have big birthday party(NPCRobotTest) [test/npc_robot_test.rb:14]:
32
+ Pending block should not be passed: acquaintances != friends.
33
+
34
+
35
+ =========
36
+ Omissions
37
+ =========
38
+
39
+ 1) Omission: I am not sure what a pizza is
40
+ test: should have pizzas for party(NPCRobotTest)
41
+ test/npc_robot_test.rb:43:in `block in <class:NPCRobotTest>'
42
+
43
+
44
+ ========
45
+ Pendings
46
+ ========
47
+
48
+ 1) Pending: pended.
49
+ test: should not dance(NPCRobotTest)
50
+ test/npc_robot_test.rb:23:in `block in <class:NPCRobotTest>'
51
+
52
+
53
+ =============
54
+ Notifications
55
+ =============
56
+
57
+ 1) Notification: Claptrap
58
+ test: should have a cool nickname(NPCRobotTest)
59
+ test/npc_robot_test.rb:29:in `block in <class:NPCRobotTest>'
60
+
61
+ 2) Notification: NPCRobotTest#test: should have pizzas for party was redefined
62
+ test: should have pizzas for party(NPCRobotTest)
63
+ test/npc_robot_test.rb:42:in `<class:NPCRobotTest>'
64
+ test/npc_robot_test.rb:10:in `<main>'
65
+
66
+
67
+
68
+ Finished in 0.013893
69
+ 4 tests, 3 assertions, 2 failures, 0 errors, 1 pendings, 1 omissions, 2 notifications
70
+
71
+ The characters P, O, and N that are reported in the last column map to calls to
72
+ `pend`, `omit`, and `notify` inside of the test. (These are part of test-unit).
73
+
74
+ Usage:
75
+
76
+ * put lineman in you bundle or otherwise install the gem
77
+ * `Test::Unit::AutoRunner.default_runner = 'lineman'`
78
+ * You could also specify --runner on the command line or your test-unit.yml
79
+ * Run your tests!
80
+
81
+ Make pull requests and be friendly.
82
+
@@ -0,0 +1,21 @@
1
+ require 'test/unit/ui/statistics/base_runner'
2
+
3
+
4
+ module Test::Unit # :nodoc:
5
+ class << self
6
+ def require_statistics_runners # :nodoc:
7
+ stat_dir = File.expand_path('../ui/statistics/runners',
8
+ File.dirname(__FILE__))
9
+ Dir["#{stat_dir}/*.rb"].each do |f|
10
+ require_relative "../ui/statistics/runners/#{File.basename(f)}"
11
+ end
12
+ end
13
+ end
14
+
15
+ require_statistics_runners
16
+ Test::Unit::UI::Statistics::BaseRunner.each_subclass do |subclass|
17
+ AutoRunner.register_runner(subclass.name) do |_auto_runner|
18
+ subclass
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,146 @@
1
+ require 'test/unit/ui/testrunner'
2
+ require 'test/unit/ui/testrunnermediator'
3
+ require_relative '../statistics'
4
+
5
+ module Test::Unit::UI::Statistics
6
+
7
+ # Inherit from this class to create a runner that has access to statistics.
8
+ #
9
+ # Implement any/all of the following callbacks in your subclass:
10
+ # * reset
11
+ # * started
12
+ # * finished
13
+ # * suite_started
14
+ # * suite_finished
15
+ # * case_started
16
+ # * case_finished
17
+ # * assertion
18
+ # * error
19
+ # * failure
20
+ # * pending
21
+ # * omission
22
+ # * notification
23
+ # * fault
24
+ #
25
+ class BaseRunner < Test::Unit::UI::TestRunner # :nodoc:
26
+
27
+ attr_accessor :result
28
+
29
+ # Case Statistics
30
+ def cstat
31
+ @method_metrics
32
+ end
33
+
34
+ # Suite Statistics
35
+ def sstat
36
+ @suite_stack.last
37
+ end
38
+
39
+ def self.inherited kls #:nodoc:
40
+ (@@subclasses ||= []) << kls
41
+ end
42
+
43
+ def self.each_subclass #:nodoc:
44
+ @@subclasses.each {|kls| yield kls }
45
+ end
46
+
47
+ def initialize suite, options={} #:nodoc:
48
+ super
49
+ @suite_stack = []
50
+ @output = options[:output] || STDOUT
51
+ end
52
+
53
+ # Inherited from TestRunner, sets up callbacks via i-var.
54
+ def attach_to_mediator #:nodoc:
55
+ @mediator.add_listener(Test::Unit::UI::TestRunnerMediator::RESET,
56
+ &callback(:reset))
57
+ @mediator.add_listener(Test::Unit::UI::TestRunnerMediator::STARTED,
58
+ &callback(:stats_started, :started))
59
+ @mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED,
60
+ &callback(:finished))
61
+ @mediator.add_listener(Test::Unit::TestSuite::STARTED_OBJECT,
62
+ &callback(:stats_suite_started, :suite_started))
63
+ @mediator.add_listener(Test::Unit::TestSuite::FINISHED_OBJECT,
64
+ &callback(:suite_finished, :stats_suite_finished))
65
+ @mediator.add_listener(Test::Unit::TestCase::STARTED,
66
+ &callback(:stats_case_started, :case_started))
67
+ @mediator.add_listener(Test::Unit::TestCase::FINISHED,
68
+ &callback(:stats_case_finished, :case_finished))
69
+ @mediator.add_listener(Test::Unit::TestResult::PASS_ASSERTION,
70
+ &callback(:stats_assertion, :assertion))
71
+ @mediator.add_listener(Test::Unit::TestResult::FAULT,
72
+ &callback(:stats_fault, :fault))
73
+ end
74
+
75
+ # Forward to methods (in-order) that we might respond to.
76
+ def callback *types #:nodoc:
77
+ ->(*args) { types.select{|t| respond_to?(t) }.each{|t| send(t, *args) }}
78
+ end
79
+
80
+ def stats_started result #:nodoc:
81
+ @result = result
82
+ end
83
+
84
+ def stats_suite_started testsuite #:nodoc:
85
+ @suite_stack << SuiteStatistics.new(testsuite)
86
+ end
87
+
88
+ def stats_suite_finished testsuite #:nodoc:
89
+ @suite_stack.pop
90
+ end
91
+
92
+ def stats_case_started name #:nodoc:
93
+ @method_metrics = CaseStatistics.new(@result)
94
+ end
95
+
96
+ def stats_case_finished name #:nodoc:
97
+ @method_metrics.complete
98
+ update_suites_with_case_statistics
99
+ end
100
+
101
+ def stats_assertion testresult #:nodoc:
102
+ @method_metrics.pass += 1
103
+ end
104
+
105
+ def stats_fault fault #:nodoc:
106
+ base_type = fault.class.name.split('::').last.downcase
107
+ stat_method_name = "stats_handle_#{base_type}".to_sym
108
+ method_name = "#{base_type}".to_sym
109
+ send(stat_method_name, fault)
110
+ if respond_to?(method_name)
111
+ send(method_name, fault)
112
+ end
113
+ end
114
+
115
+ def stats_handle_error fault #:nodoc:
116
+ # Don't count errors before setup (i.e. in startup).
117
+ return unless @method_metrics
118
+ @method_metrics.errs += 1
119
+ end
120
+
121
+ def stats_handle_failure fault #:nodoc:
122
+ # The PASS_ASSERTION message just means it was run, we handle failures
123
+ @method_metrics.fail += 1
124
+ @method_metrics.pass -= 1
125
+ end
126
+
127
+ def stats_handle_pending fault #:nodoc:
128
+ @method_metrics.pend += 1
129
+ end
130
+
131
+ def stats_handle_omission fault #:nodoc:
132
+ @method_metrics.omit += 1
133
+ end
134
+
135
+ def stats_handle_notification fault #:nodoc:
136
+ @method_metrics.note += 1
137
+ end
138
+
139
+ def update_suites_with_case_statistics #:nodoc:
140
+ @suite_stack.each do |suite|
141
+ suite.add_test_case_statistics @method_metrics
142
+ end
143
+ end
144
+
145
+ end
146
+ end
@@ -0,0 +1,109 @@
1
+ require_relative '../base_runner'
2
+ #require 'test/unit/color-scheme'
3
+ #require 'test/unit/code-snippet-fetcher'
4
+ #require 'test/unit/diff'
5
+
6
+
7
+ module Test::Unit::UI::Statistics::Lineman
8
+ class TestRunner < Test::Unit::UI::Statistics::BaseRunner
9
+
10
+ def self.name
11
+ 'lineman'
12
+ end
13
+
14
+ # callback
15
+ def reset size
16
+ puts "Preparing to run #{size} tests"
17
+ end
18
+
19
+ # callback
20
+ def finished time
21
+ show_faults
22
+ puts "Finished in #{time.inspect}"
23
+ puts result.to_s
24
+ end
25
+
26
+ # callback
27
+ def suite_started testcase
28
+ puts "%-0.80s" % testcase
29
+ end
30
+
31
+ # callback
32
+ def suite_finished testcase
33
+ two_point_time = ("%.2f" % sstat.elapsed_time)
34
+ extended_actions = ''
35
+ extended_actions += (sstat.errs.nonzero? ? 'E' : ' ')
36
+ extended_actions += (sstat.pend.nonzero? ? 'P' : ' ')
37
+ extended_actions += (sstat.omit.nonzero? ? 'O' : ' ')
38
+ extended_actions += (sstat.note.nonzero? ? 'N' : ' ')
39
+ puts "%-50.50s %4.4s:%-4.4s %6.6s %s" % [testcase,
40
+ sstat.pass,
41
+ sstat.fail,
42
+ two_point_time,
43
+ extended_actions]
44
+ end
45
+
46
+ # callback
47
+ def case_started test_name
48
+ output_name = test_name.gsub(/\(#{sstat.test_suite.to_s}\)$/, '')
49
+ print " %-46.46s " % output_name
50
+ end
51
+
52
+ # callback
53
+ def case_finished test_name
54
+ two_point_time = ("%.2f" % cstat.elapsed_time)
55
+ if cstat.errs.nonzero?
56
+ err_or_pass_fail = 'ERROR'
57
+ else
58
+ err_or_pass_fail = '%4.4s:%-4.4s' % [cstat.pass,
59
+ cstat.fail]
60
+ end
61
+ extended_actions = ''
62
+ extended_actions += (cstat.pend.nonzero? ? 'P' : ' ')
63
+ extended_actions += (cstat.omit.nonzero? ? 'O' : ' ')
64
+ extended_actions += (cstat.note.nonzero? ? 'N' : ' ')
65
+ puts "%9.9s %6.6s %s" % [err_or_pass_fail, two_point_time,
66
+ extended_actions]
67
+ end
68
+
69
+ def show_faults
70
+ puts "\n"
71
+ order = [Test::Unit::Error, Test::Unit::Failure, Test::Unit::Omission,
72
+ Test::Unit::Pending, Test::Unit::Notification]
73
+ order.each do |type|
74
+ faults = result.faults.select {|f| f.is_a?(type) }
75
+ if faults.length.nonzero?
76
+ type_str = "#{type.to_s.split('::').last}s"
77
+ puts "=" * type_str.length
78
+ puts type_str
79
+ puts "=" * type_str.length
80
+ puts ''
81
+ max_width = faults.length.to_s.length
82
+ faults.each_with_index do |f,i|
83
+ puts " %#{max_width}i) %s\n" % [i+1, f.long_display]
84
+ puts ''
85
+ end
86
+ puts ''
87
+ end
88
+ end
89
+ puts "\n"
90
+ end
91
+
92
+ def fault_header_line num, fault
93
+ " %#{@exception_max_width}i) %s:" % [num, fault.label]
94
+ end
95
+
96
+ def fault_location_line fault
97
+ "#{fault.test_name} #{fault.location}:"
98
+ end
99
+
100
+ def fault_message fault
101
+ fault.message
102
+ end
103
+
104
+ def exception_backtrace fault
105
+ " " + fault.backtrace.join("\n ")
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,65 @@
1
+ module Test::Unit::UI::Statistics
2
+ class CaseStatistics
3
+ attr_accessor :pass
4
+ attr_accessor :fail
5
+ attr_accessor :errs
6
+ attr_accessor :pend
7
+ attr_accessor :omit
8
+ attr_accessor :note
9
+
10
+ def initialize results
11
+ self.pass = 0
12
+ self.fail = 0
13
+ self.errs = 0
14
+ self.pend = 0
15
+ self.omit = 0
16
+ self.note = 0
17
+ @start_time = Time.now
18
+ @end_time = nil
19
+ end
20
+
21
+ def elapsed_time
22
+ end_time - @start_time
23
+ end
24
+
25
+ def end_time
26
+ @end_time ? @end_time : Time.now
27
+ end
28
+
29
+ def complete
30
+ @end_time = Time.now
31
+ end
32
+ end
33
+
34
+
35
+ class SuiteStatistics
36
+ attr_reader :test_suite
37
+ attr_accessor :forward_class
38
+
39
+ def initialize test_suite
40
+ @test_suite = test_suite
41
+ @aggregate_statistics = []
42
+ end
43
+
44
+ def add_test_case_statistics stats
45
+ @aggregate_statistics << stats
46
+ end
47
+
48
+ def aggregate sym
49
+ @aggregate_statistics.inject(0) {|a,v| a + v.send(sym) }
50
+ end
51
+
52
+ def method_missing sym, *args
53
+ if respond_to?(sym)
54
+ aggregate(sym)
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ def respond_to? sym
61
+ Test::Unit::TestResult.instance_methods.include?(sym) or
62
+ CaseStatistics.instance_methods.include?(sym)
63
+ end
64
+ end
65
+ end
data/lineman.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'lineman'
3
+ s.version = '0.9.0'
4
+ s.date = '2012-10-07'
5
+
6
+ s.summary = 'A test runner (UI) for test-unit'
7
+ s.description = 'Lineman provides clean output for your tests, giving you one line for each test that shows the name along with some statistics.'
8
+
9
+ s.authors = ['Todd Willey (xtoddx)']
10
+ s.email = 'xtoddx@gmail.com'
11
+ s.homepage = 'http://github.com/xtoddx/lineman'
12
+
13
+ s.require_paths = %w[lib]
14
+
15
+ s.rdoc_options = ["--charset=UTF-8"]
16
+ s.extra_rdoc_files = %w[README.md]
17
+
18
+ s.add_dependency('test-unit', '~> 2.4')
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {spec,tests}/*`.split("\n")
22
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lineman
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Todd Willey (xtoddx)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: test-unit
16
+ requirement: &70263140719340 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70263140719340
25
+ description: Lineman provides clean output for your tests, giving you one line for
26
+ each test that shows the name along with some statistics.
27
+ email: xtoddx@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files:
31
+ - README.md
32
+ files:
33
+ - README.md
34
+ - lib/test/unit/runner/statistics.rb
35
+ - lib/test/unit/ui/statistics.rb
36
+ - lib/test/unit/ui/statistics/base_runner.rb
37
+ - lib/test/unit/ui/statistics/runners/lineman.rb
38
+ - lineman.gemspec
39
+ homepage: http://github.com/xtoddx/lineman
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.17
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: A test runner (UI) for test-unit
64
+ test_files: []
65
+ has_rdoc: