assert 2.15.0 → 2.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -7
  2. data/Gemfile +0 -1
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +106 -35
  5. data/assert.gemspec +2 -2
  6. data/lib/assert/assert_runner.rb +19 -12
  7. data/lib/assert/assertions.rb +1 -0
  8. data/lib/assert/cli.rb +3 -0
  9. data/lib/assert/config.rb +24 -6
  10. data/lib/assert/config_helpers.rb +15 -28
  11. data/lib/assert/context.rb +4 -3
  12. data/lib/assert/context/test_dsl.rb +3 -2
  13. data/lib/assert/context_info.rb +19 -0
  14. data/lib/assert/default_runner.rb +12 -0
  15. data/lib/assert/default_suite.rb +64 -0
  16. data/lib/assert/default_view.rb +17 -15
  17. data/lib/assert/file_line.rb +3 -2
  18. data/lib/assert/result.rb +6 -0
  19. data/lib/assert/runner.rb +58 -21
  20. data/lib/assert/suite.rb +61 -100
  21. data/lib/assert/test.rb +3 -3
  22. data/lib/assert/version.rb +1 -1
  23. data/lib/assert/view.rb +58 -74
  24. data/lib/assert/view_helpers.rb +10 -48
  25. data/test/helper.rb +9 -0
  26. data/test/support/factory.rb +5 -5
  27. data/test/unit/assertions/assert_raises_tests.rb +20 -0
  28. data/test/unit/config_helpers_tests.rb +29 -29
  29. data/test/unit/config_tests.rb +43 -10
  30. data/test/unit/context/suite_dsl_tests.rb +1 -1
  31. data/test/unit/context_info_tests.rb +55 -0
  32. data/test/unit/default_runner_tests.rb +18 -0
  33. data/test/unit/default_suite_tests.rb +74 -0
  34. data/test/unit/file_line_tests.rb +6 -2
  35. data/test/unit/result_tests.rb +15 -4
  36. data/test/unit/runner_tests.rb +128 -6
  37. data/test/unit/suite_tests.rb +73 -182
  38. data/test/unit/view_helpers_tests.rb +44 -38
  39. data/test/unit/view_tests.rb +15 -39
  40. metadata +42 -28
  41. data/Rakefile +0 -1
@@ -3,6 +3,7 @@ require 'assert/context/setup_dsl'
3
3
  require 'assert/context/subject_dsl'
4
4
  require 'assert/context/suite_dsl'
5
5
  require 'assert/context/test_dsl'
6
+ require 'assert/context_info'
6
7
  require 'assert/macros/methods'
7
8
  require 'assert/result'
8
9
  require 'assert/suite'
@@ -40,7 +41,7 @@ module Assert
40
41
 
41
42
  self.suite.tests << Test.for_method(
42
43
  method_name.to_s,
43
- Suite::ContextInfo.new(self, nil, caller.first),
44
+ ContextInfo.new(self, nil, caller.first),
44
45
  self.suite.config
45
46
  )
46
47
  end
@@ -116,13 +117,13 @@ module Assert
116
117
  # alter the backtraces of fail results generated in the given block
117
118
  def with_backtrace(bt, &block)
118
119
  bt ||= []
119
- current_results.count.tap do |count|
120
+ current_results.size.tap do |size|
120
121
  begin
121
122
  instance_eval(&block)
122
123
  rescue Result::TestSkipped, Result::TestFailure => e
123
124
  e.set_backtrace(bt); raise(e)
124
125
  ensure
125
- current_results[count..-1].each{ |r| r.set_backtrace(bt) }
126
+ current_results[size..-1].each{ |r| r.set_backtrace(bt) }
126
127
  end
127
128
  end
128
129
  end
@@ -1,3 +1,4 @@
1
+ require 'assert/context_info'
1
2
  require 'assert/macro'
2
3
  require 'assert/suite'
3
4
  require 'assert/test'
@@ -14,7 +15,7 @@ class Assert::Context
14
15
  # create a test from the given code block
15
16
  self.suite.tests << Assert::Test.for_block(
16
17
  desc_or_macro.kind_of?(Assert::Macro) ? desc_or_macro.name : desc_or_macro,
17
- Assert::Suite::ContextInfo.new(self, called_from, first_caller || caller.first),
18
+ Assert::ContextInfo.new(self, called_from, first_caller || caller.first),
18
19
  self.suite.config,
19
20
  &block
20
21
  )
@@ -25,7 +26,7 @@ class Assert::Context
25
26
 
26
27
  def test_eventually(desc_or_macro, called_from = nil, first_caller = nil, &block)
27
28
  # create a test from a proc that just skips
28
- ci = Assert::Suite::ContextInfo.new(self, called_from, first_caller || caller.first)
29
+ ci = Assert::ContextInfo.new(self, called_from, first_caller || caller.first)
29
30
  self.suite.tests << Assert::Test.for_block(
30
31
  desc_or_macro.kind_of?(Assert::Macro) ? desc_or_macro.name : desc_or_macro,
31
32
  ci,
@@ -0,0 +1,19 @@
1
+ module Assert
2
+
3
+ class ContextInfo
4
+
5
+ attr_reader :called_from, :klass, :file
6
+
7
+ def initialize(klass, called_from = nil, first_caller = nil)
8
+ @called_from = called_from || first_caller
9
+ @klass = klass
10
+ @file = @called_from.gsub(/\:[0-9]+.*$/, '') if @called_from
11
+ end
12
+
13
+ def test_name(name)
14
+ [klass.description.to_s, name.to_s].compact.reject(&:empty?).join(' ')
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,12 @@
1
+ require 'assert/runner'
2
+
3
+ module Assert
4
+
5
+ # This is the default runner used by assert. It adds no special behavior on
6
+ # top of the base runner's behavior
7
+
8
+ class DefaultRunner < Assert::Runner
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,64 @@
1
+ require 'assert/suite'
2
+
3
+ module Assert
4
+
5
+ # This is the default suite used by assert. It stores test/result data in-memory.
6
+
7
+ class DefaultSuite < Assert::Suite
8
+
9
+ # Test data
10
+
11
+ def ordered_tests
12
+ self.tests
13
+ end
14
+
15
+ def reversed_tests
16
+ self.tests.reverse
17
+ end
18
+
19
+ def ordered_tests_by_run_time
20
+ self.ordered_tests.sort{ |a, b| a.run_time <=> b.run_time }
21
+ end
22
+
23
+ def reversed_tests_by_run_time
24
+ self.ordered_tests_by_run_time.reverse
25
+ end
26
+
27
+ def test_count
28
+ self.tests.size
29
+ end
30
+
31
+ # Result data
32
+
33
+ def ordered_results
34
+ self.ordered_tests.inject([]){ |results, test| results += test.results }
35
+ end
36
+
37
+ def reversed_results
38
+ self.ordered_results.reverse
39
+ end
40
+
41
+ # dump failed or errored results,
42
+ # dump skipped or ignored results if they have a message
43
+ def ordered_results_for_dump
44
+ self.ordered_results.select do |result|
45
+ [:fail, :error].include?(result.to_sym) ||
46
+ !!([:skip, :ignore].include?(result.to_sym) && result.message)
47
+ end
48
+ end
49
+
50
+ def reversed_results_for_dump
51
+ self.ordered_results_for_dump.reverse
52
+ end
53
+
54
+ def result_count(type = nil)
55
+ self.tests.inject(0){ |count, test| count += test.result_count(type) }
56
+ end
57
+
58
+ # Callbacks
59
+
60
+ # no custom callbacks
61
+
62
+ end
63
+
64
+ end
@@ -1,11 +1,13 @@
1
1
  require 'assert/view'
2
+ require 'assert/view_helpers'
2
3
 
3
4
  module Assert
4
5
 
5
6
  # This is the default view used by assert. It renders ansi test output
6
7
  # designed for terminal viewing.
7
8
 
8
- class DefaultView < Assert::View::Base
9
+ class DefaultView < Assert::View
10
+ include Assert::ViewHelpers::Ansi
9
11
 
10
12
  # setup options and their default values
11
13
 
@@ -69,7 +71,9 @@ module Assert
69
71
 
70
72
  puts "#{result_count_statement}: #{styled_results_sentence}"
71
73
  puts
72
- puts "(#{run_time} seconds, #{test_rate} tests/s, #{result_rate} results/s)"
74
+ puts "(#{formatted_run_time} seconds, " \
75
+ "#{formatted_test_rate} tests/s, " \
76
+ "#{formatted_result_rate} results/s)"
73
77
  end
74
78
 
75
79
  def on_interrupt(err)
@@ -82,22 +86,20 @@ module Assert
82
86
  print "\n"
83
87
  puts
84
88
 
85
- # output detailed results for the tests in reverse test/result order
86
- tests = config.suite.ordered_tests.reverse
87
- result_details_for(tests, :reversed).each do |details|
88
- if show_result_details?(details.result)
89
- # output the styled result details
90
- result = details.result
91
- puts ansi_styled_msg(result.to_s, result)
89
+ config.suite.reversed_results_for_dump.each do |result|
90
+ # output the styled result details
91
+ puts ansi_styled_msg(result.to_s, result)
92
92
 
93
- # output any captured stdout
94
- output = details.output
95
- puts captured_output(output) if output && !output.empty?
93
+ # output any captured stdout
94
+ puts captured_output(result.output) if result.output && !result.output.empty?
96
95
 
97
- # add an empty line between each result detail
98
- puts
99
- end
96
+ # output re-run CLI cmd
97
+ puts re_run_test_cmd(result.test_id)
98
+
99
+ # add an empty line between each result detail
100
+ puts
100
101
  end
102
+
101
103
  end
102
104
 
103
105
  end
@@ -3,7 +3,7 @@ module Assert
3
3
  class FileLine
4
4
 
5
5
  def self.parse(file_line_path)
6
- self.new(*(file_line_path.to_s.match(/(.+)\:(.+)/) || [])[1..2])
6
+ self.new(*(file_line_path.to_s.match(/(^[^\:]*)\:*(\d*)$/) || [])[1..2])
7
7
  end
8
8
 
9
9
  attr_reader :file, :line
@@ -18,7 +18,8 @@ module Assert
18
18
 
19
19
  def ==(other_file_line)
20
20
  if other_file_line.kind_of?(FileLine)
21
- self.file == other_file_line.file && self.line == other_file_line.line
21
+ self.file == other_file_line.file &&
22
+ self.line == other_file_line.line
22
23
  else
23
24
  super
24
25
  end
@@ -31,7 +31,9 @@ module Assert::Result
31
31
  def self.for_test(test, message, bt)
32
32
  self.new({
33
33
  :test_name => test.name,
34
+ :test_id => test.file_line.to_s,
34
35
  :message => message,
36
+ :output => test.output,
35
37
  :backtrace => Backtrace.new(bt)
36
38
  })
37
39
  end
@@ -43,7 +45,9 @@ module Assert::Result
43
45
  def type; @type ||= (@build_data[:type] || self.class.type).to_sym; end
44
46
  def name; @name ||= (@build_data[:name] || self.class.name.to_s); end
45
47
  def test_name; @test_name ||= (@build_data[:test_name] || ''); end
48
+ def test_id; @test_id ||= (@build_data[:test_id] || ''); end
46
49
  def message; @message ||= (@build_data[:message] || ''); end
50
+ def output; @output ||= (@build_data[:output] || ''); end
47
51
  def backtrace; @backtrace ||= (@build_data[:backtrace] || Backtrace.new([])); end
48
52
  def trace; @trace ||= (@build_data[:trace] || build_trace(self.backtrace)); end
49
53
 
@@ -62,7 +66,9 @@ module Assert::Result
62
66
  { :type => self.type,
63
67
  :name => self.name,
64
68
  :test_name => self.test_name,
69
+ :test_id => self.test_id,
65
70
  :message => self.message,
71
+ :output => self.output,
66
72
  :backtrace => self.backtrace,
67
73
  :trace => self.trace,
68
74
  }
@@ -1,5 +1,6 @@
1
1
  require 'assert/config_helpers'
2
2
  require 'assert/suite'
3
+ require 'assert/view'
3
4
 
4
5
  module Assert
5
6
 
@@ -12,40 +13,76 @@ module Assert
12
13
  @config = config
13
14
  end
14
15
 
16
+ def runner; self; end
17
+
15
18
  def run
16
- suite, view = @config.suite, @config.view
17
- raise ArgumentError if !suite.kind_of?(Suite)
18
- if tests?
19
- view.puts "Running tests in random order, seeded with \"#{runner_seed}\""
19
+ self.on_start
20
+ self.suite.on_start
21
+ self.view.on_start
22
+
23
+ if self.single_test?
24
+ self.view.puts "Running test: #{self.single_test_file_line}"
25
+ elsif self.tests?
26
+ self.view.puts "Running tests in random order, " \
27
+ "seeded with \"#{self.runner_seed}\""
20
28
  end
21
- view.fire(:on_start)
22
29
 
23
30
  begin
24
- suite.setup
25
-
26
- suite.start_time = Time.now
27
- tests_to_run(suite).each do |test|
28
- view.fire(:before_test, test)
29
- test.run{ |result| view.fire(:on_result, result) }
30
- view.fire(:after_test, test)
31
+ self.suite.start_time = Time.now
32
+ self.suite.setups.each(&:call)
33
+ tests_to_run.each do |test|
34
+ self.before_test(test)
35
+ self.suite.before_test(test)
36
+ self.view.before_test(test)
37
+ test.run do |result|
38
+ self.on_result(result)
39
+ self.suite.on_result(result)
40
+ self.view.on_result(result)
41
+ end
42
+ self.after_test(test)
43
+ self.suite.after_test(test)
44
+ self.view.after_test(test)
31
45
  end
32
- suite.end_time = Time.now
33
-
34
- suite.teardown
46
+ self.suite.teardowns.each(&:call)
47
+ self.suite.end_time = Time.now
35
48
  rescue Interrupt => err
36
- view.fire(:on_interrupt, err)
49
+ self.on_interrupt(err)
50
+ self.suite.on_interrupt(err)
51
+ self.view.on_interrupt(err)
37
52
  raise(err)
38
53
  end
39
54
 
40
- view.fire(:on_finish)
41
- suite.count(:failed) + suite.count(:errored)
55
+ (self.suite.count(:fail) + self.suite.count(:error)).tap do
56
+ self.view.on_finish
57
+ self.suite.on_finish
58
+ self.on_finish
59
+ end
42
60
  end
43
61
 
62
+ # Callbacks
63
+
64
+ # define callback handlers to do special behavior during the test run. These
65
+ # will be called by the test runner
66
+
67
+ def before_load(test_files); end
68
+ def after_load; end
69
+ def on_start; end
70
+ def before_test(test); end
71
+ def on_result(result); end
72
+ def after_test(test); end
73
+ def on_finish; end
74
+ def on_interrupt(err); end
75
+
44
76
  private
45
77
 
46
- def tests_to_run(suite)
47
- srand self.config.runner_seed
48
- suite.tests.sort.sort_by{ rand suite.tests.size }
78
+ def tests_to_run
79
+ if self.single_test?
80
+ [ self.suite.tests.find{ |t| t.file_line == self.single_test_file_line }
81
+ ].compact
82
+ else
83
+ srand self.runner_seed
84
+ self.suite.tests.sort.sort_by{ rand self.suite.tests.size }
85
+ end
49
86
  end
50
87
 
51
88
  end
@@ -1,98 +1,102 @@
1
+ require 'assert/config_helpers'
1
2
  require 'assert/test'
2
3
 
3
4
  module Assert
5
+
4
6
  class Suite
7
+ include Assert::ConfigHelpers
5
8
 
6
- TEST_METHOD_REGEX = /^test./
9
+ TEST_METHOD_REGEX = /^test./.freeze
7
10
 
8
11
  # A suite is a set of tests to run. When a test class subclasses
9
12
  # the Context class, that test class is pushed to the suite.
10
13
 
11
- attr_accessor :config, :tests, :test_methods, :start_time, :end_time
14
+ attr_reader :config, :tests, :test_methods, :setups, :teardowns
15
+ attr_accessor :start_time, :end_time
12
16
 
13
17
  def initialize(config)
14
- @config = config
15
- @tests = []
18
+ @config = config
19
+ @tests = []
16
20
  @test_methods = []
17
- @start_time = Time.now
18
- @end_time = @start_time
21
+ @setups = []
22
+ @teardowns = []
23
+ @start_time = Time.now
24
+ @end_time = @start_time
19
25
  end
20
26
 
21
- def run_time
22
- @end_time - @start_time
23
- end
27
+ def suite; self; end
24
28
 
25
- def test_rate
26
- get_rate(self.tests.size, self.run_time)
29
+ def setup(&block)
30
+ self.setups << (block || proc{})
27
31
  end
32
+ alias_method :startup, :setup
28
33
 
29
- def result_rate
30
- get_rate(self.results.size, self.run_time)
34
+ def teardown(&block)
35
+ self.teardowns << (block || proc{})
31
36
  end
37
+ alias_method :shutdown, :teardown
32
38
 
33
- alias_method :ordered_tests, :tests
39
+ def run_time
40
+ @end_time - @start_time
41
+ end
34
42
 
35
- def ordered_tests_by_run_time
36
- self.ordered_tests.sort{ |a, b| a.run_time <=> b.run_time }
43
+ def test_rate
44
+ get_rate(self.test_count, self.run_time)
37
45
  end
38
46
 
39
- def results
40
- tests.inject([]){ |results, test| results += test.results }
47
+ def result_rate
48
+ get_rate(self.result_count, self.run_time)
41
49
  end
42
- alias_method :ordered_results, :results
43
50
 
44
51
  def count(thing)
45
- case thing
46
- when :tests
52
+ if thing == :tests
47
53
  test_count
48
- when :results
54
+ elsif thing == :results
49
55
  result_count
50
- when :passed, :pass
56
+ elsif thing == :pass || thing == :passed
51
57
  result_count(:pass)
52
- when :failed, :fail
58
+ elsif thing == :fail || thing == :failed
53
59
  result_count(:fail)
54
- when :ignored, :ignore
55
- result_count(:ignore)
56
- when :skipped, :skip
57
- result_count(:skip)
58
- when :errored, :error
60
+ elsif thing == :error || thing == :errored
59
61
  result_count(:error)
62
+ elsif thing == :skip || thing == :skipped
63
+ result_count(:skip)
64
+ elsif thing == :ignore || thing == :ignored
65
+ result_count(:ignore)
60
66
  else
61
67
  0
62
68
  end
63
69
  end
64
70
 
65
- def test_count
66
- self.tests.size
67
- end
71
+ # Test data
68
72
 
69
- def result_count(type = nil)
70
- if type
71
- self.tests.inject(0) do |count, test|
72
- count += test.result_count(type)
73
- end
74
- else
75
- self.results.size
76
- end
77
- end
73
+ def ordered_tests; end
74
+ def reversed_tests; end
75
+ def ordered_tests_by_run_time; end
76
+ def reversed_tests_by_run_time; end
77
+ def test_count; end
78
78
 
79
- def setup(&block)
80
- if block_given?
81
- self.setups << block
82
- else
83
- self.setups.each{ |setup| setup.call }
84
- end
85
- end
86
- alias_method :startup, :setup
79
+ # Result data
87
80
 
88
- def teardown(&block)
89
- if block_given?
90
- self.teardowns << block
91
- else
92
- self.teardowns.reverse.each{ |teardown| teardown.call }
93
- end
94
- end
95
- alias_method :shutdown, :teardown
81
+ def ordered_results; end
82
+ def reversed_results; end
83
+ def ordered_results_for_dump; end
84
+ def reversed_results_for_dump; end
85
+ def result_count(type = nil); end
86
+
87
+ # Callbacks
88
+
89
+ # define callback handlers to do special behavior during the test run. These
90
+ # will be called by the test runner
91
+
92
+ def before_load(test_files); end
93
+ def after_load; end
94
+ def on_start; end
95
+ def before_test(test); end
96
+ def on_result(result); end
97
+ def after_test(test); end
98
+ def on_finish; end
99
+ def on_interrupt(err); end
96
100
 
97
101
  def inspect
98
102
  "#<#{self.class}:#{'0x0%x' % (object_id << 1)}"\
@@ -100,55 +104,12 @@ module Assert
100
104
  " result_count=#{self.result_count.inspect}>"
101
105
  end
102
106
 
103
- protected
104
-
105
- def setups
106
- @setups ||= []
107
- end
108
-
109
- def teardowns
110
- @teardowns ||= []
111
- end
112
-
113
- def local_public_test_methods(klass)
114
- # start with all public meths, store off the local ones
115
- methods = klass.public_instance_methods
116
- local_methods = klass.public_instance_methods(false)
117
-
118
- # remove any from the superclass
119
- while (klass.superclass)
120
- methods -= (klass = klass.superclass).public_instance_methods
121
- end
122
-
123
- # add back in the local ones (to work around super having the same methods)
124
- methods += local_methods
125
-
126
- # uniq and remove any that don't start with 'test'
127
- methods.uniq.delete_if {|method_name| method_name !~ TEST_METHOD_REGEX }
128
- end
129
-
130
107
  private
131
108
 
132
109
  def get_rate(count, time)
133
110
  time == 0 ? 0.0 : (count.to_f / time.to_f)
134
111
  end
135
112
 
136
- class ContextInfo
137
-
138
- attr_reader :called_from, :klass, :file
139
-
140
- def initialize(klass, called_from = nil, first_caller = nil)
141
- @called_from = called_from || first_caller
142
- @klass = klass
143
- @file = @called_from.gsub(/\:[0-9]+.*$/, '') if @called_from
144
- end
145
-
146
- def test_name(name)
147
- [klass.description.to_s, name.to_s].compact.reject(&:empty?).join(' ')
148
- end
149
-
150
- end
151
-
152
113
  end
153
114
 
154
115
  end