assert 2.15.2 → 2.16.0

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.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/lib/assert/assertions.rb +6 -0
  3. data/lib/assert/config_helpers.rb +35 -14
  4. data/lib/assert/context.rb +36 -43
  5. data/lib/assert/context/test_dsl.rb +4 -4
  6. data/lib/assert/default_suite.rb +35 -40
  7. data/lib/assert/default_view.rb +109 -37
  8. data/lib/assert/file_line.rb +1 -1
  9. data/lib/assert/result.rb +67 -27
  10. data/lib/assert/runner.rb +14 -10
  11. data/lib/assert/suite.rb +41 -50
  12. data/lib/assert/test.rb +39 -81
  13. data/lib/assert/version.rb +1 -1
  14. data/lib/assert/view_helpers.rb +11 -21
  15. data/test/helper.rb +40 -0
  16. data/test/system/test_tests.rb +90 -88
  17. data/test/unit/assertions/assert_block_tests.rb +14 -10
  18. data/test/unit/assertions/assert_empty_tests.rb +14 -10
  19. data/test/unit/assertions/assert_equal_tests.rb +22 -14
  20. data/test/unit/assertions/assert_file_exists_tests.rb +14 -10
  21. data/test/unit/assertions/assert_includes_tests.rb +14 -10
  22. data/test/unit/assertions/assert_instance_of_tests.rb +14 -10
  23. data/test/unit/assertions/assert_kind_of_tests.rb +14 -10
  24. data/test/unit/assertions/assert_match_tests.rb +14 -10
  25. data/test/unit/assertions/assert_nil_tests.rb +14 -10
  26. data/test/unit/assertions/assert_raises_tests.rb +14 -10
  27. data/test/unit/assertions/assert_respond_to_tests.rb +14 -10
  28. data/test/unit/assertions/assert_same_tests.rb +20 -14
  29. data/test/unit/assertions/assert_true_false_tests.rb +28 -20
  30. data/test/unit/assertions_tests.rb +12 -9
  31. data/test/unit/config_helpers_tests.rb +72 -13
  32. data/test/unit/context/test_dsl_tests.rb +38 -45
  33. data/test/unit/context_tests.rb +12 -8
  34. data/test/unit/default_suite_tests.rb +66 -43
  35. data/test/unit/file_line_tests.rb +4 -1
  36. data/test/unit/result_tests.rb +71 -47
  37. data/test/unit/runner_tests.rb +34 -16
  38. data/test/unit/suite_tests.rb +61 -29
  39. data/test/unit/test_tests.rb +97 -134
  40. data/test/unit/view_helpers_tests.rb +17 -31
  41. metadata +2 -2
@@ -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(/(^[^\:]*)\:*(\d*)$/) || [])[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
data/lib/assert/result.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'assert/file_line'
2
+
1
3
  module Assert; end
2
4
  module Assert::Result
3
5
 
@@ -30,11 +32,11 @@ module Assert::Result
30
32
 
31
33
  def self.for_test(test, message, bt)
32
34
  self.new({
33
- :test_name => test.name,
34
- :test_id => test.file_line.to_s,
35
- :message => message,
36
- :output => test.output,
37
- :backtrace => Backtrace.new(bt)
35
+ :test_name => test.name,
36
+ :test_file_line => test.file_line,
37
+ :message => message,
38
+ :output => test.output,
39
+ :backtrace => Backtrace.new(bt)
38
40
  })
39
41
  end
40
42
 
@@ -42,17 +44,43 @@ module Assert::Result
42
44
  @build_data = build_data
43
45
  end
44
46
 
45
- def type; @type ||= (@build_data[:type] || self.class.type).to_sym; end
46
- def name; @name ||= (@build_data[:name] || self.class.name.to_s); end
47
- def test_name; @test_name ||= (@build_data[:test_name] || ''); end
48
- def test_id; @test_id ||= (@build_data[:test_id] || ''); end
49
- def message; @message ||= (@build_data[:message] || ''); end
50
- def output; @output ||= (@build_data[:output] || ''); end
51
- def backtrace; @backtrace ||= (@build_data[:backtrace] || Backtrace.new([])); end
52
- def trace; @trace ||= (@build_data[:trace] || build_trace(self.backtrace)); end
47
+ def type
48
+ @type ||= (@build_data[:type] || self.class.type).to_sym
49
+ end
53
50
 
54
- Assert::Result.types.keys.each do |type|
55
- define_method("#{type}?"){ self.type == type }
51
+ def name
52
+ @name ||= (@build_data[:name] || self.class.name.to_s)
53
+ end
54
+
55
+ def test_name
56
+ @test_name ||= (@build_data[:test_name] || '')
57
+ end
58
+
59
+ def test_file_line
60
+ @test_file_line ||= (@build_data[:test_file_line] || Assert::FileLine.parse(''))
61
+ end
62
+
63
+ def test_file_name; self.test_file_line.file; end
64
+ def test_line_num; self.test_file_line.line.to_i; end
65
+
66
+ def test_id
67
+ self.test_file_line.to_s
68
+ end
69
+
70
+ def message
71
+ @message ||= (@build_data[:message] || '')
72
+ end
73
+
74
+ def output
75
+ @output ||= (@build_data[:output] || '')
76
+ end
77
+
78
+ def backtrace
79
+ @backtrace ||= (@build_data[:backtrace] || Backtrace.new([]))
80
+ end
81
+
82
+ def trace
83
+ @trace ||= (@build_data[:trace] || build_trace(self.backtrace))
56
84
  end
57
85
 
58
86
  # we choose to implement this way instead of using an `attr_writer` to be
@@ -60,18 +88,18 @@ module Assert::Result
60
88
  def set_backtrace(bt)
61
89
  @backtrace = Backtrace.new(bt)
62
90
  @trace = build_trace(@backtrace)
91
+ @file_line = Assert::FileLine.parse(first_filtered_bt_line(@backtrace))
63
92
  end
64
93
 
65
- def data
66
- { :type => self.type,
67
- :name => self.name,
68
- :test_name => self.test_name,
69
- :test_id => self.test_id,
70
- :message => self.message,
71
- :output => self.output,
72
- :backtrace => self.backtrace,
73
- :trace => self.trace,
74
- }
94
+ def file_line
95
+ @file_line ||= Assert::FileLine.parse(first_filtered_bt_line(self.backtrace))
96
+ end
97
+
98
+ def file_name; self.file_line.file; end
99
+ def line_num; self.file_line.line.to_i; end
100
+
101
+ Assert::Result.types.keys.each do |type|
102
+ define_method("#{type}?"){ self.type == type }
75
103
  end
76
104
 
77
105
  def to_sym; self.type; end
@@ -88,14 +116,26 @@ module Assert::Result
88
116
  end
89
117
 
90
118
  def inspect
91
- "#<#{self.class}:#{'0x0%x' % (object_id << 1)} @message=#{self.message.inspect}>"
119
+ "#<#{self.class}:#{'0x0%x' % (object_id << 1)} "\
120
+ "@message=#{self.message.inspect} "\
121
+ "@file_line=#{self.file_line.to_s.inspect} "\
122
+ "@test_file_line=#{self.test_file_line.to_s.inspect}>"
92
123
  end
93
124
 
94
125
  private
95
126
 
96
127
  # by default, a result's trace is the first line of its filtered backtrace
97
- def build_trace(backtrace); backtrace.filtered.first.to_s; end
128
+ # if the filtered backtrace is empty, just use the backtrace itself (this
129
+ # should only occur if the result is an error from a line in assert's
130
+ # non-test code). This is overridden for error results as they always show
131
+ # the entire backtrace
132
+ def build_trace(backtrace)
133
+ first_filtered_bt_line(backtrace)
134
+ end
98
135
 
136
+ def first_filtered_bt_line(backtrace)
137
+ ((fbt = backtrace.filtered).empty? ? backtrace : fbt).first.to_s
138
+ end
99
139
  end
100
140
 
101
141
  class Pass < Base
data/lib/assert/runner.rb CHANGED
@@ -21,16 +21,18 @@ module Assert
21
21
  self.view.on_start
22
22
 
23
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}\""
24
+ self.view.print "Running test: #{self.single_test_file_line}"
25
+ elsif self.tests_to_run?
26
+ self.view.print "Running tests in random order"
27
+ end
28
+ if self.tests_to_run?
29
+ self.view.puts ", seeded with \"#{self.runner_seed}\""
28
30
  end
29
31
 
30
32
  begin
31
33
  self.suite.start_time = Time.now
32
34
  self.suite.setups.each(&:call)
33
- tests_to_run.each do |test|
35
+ tests_to_run.tap{ self.suite.clear_tests_to_run }.delete_if do |test|
34
36
  self.before_test(test)
35
37
  self.suite.before_test(test)
36
38
  self.view.before_test(test)
@@ -42,6 +44,9 @@ module Assert
42
44
  self.after_test(test)
43
45
  self.suite.after_test(test)
44
46
  self.view.after_test(test)
47
+
48
+ # always delete `test` from `tests_to_run` since it has been run
49
+ true
45
50
  end
46
51
  self.suite.teardowns.each(&:call)
47
52
  self.suite.end_time = Time.now
@@ -52,7 +57,7 @@ module Assert
52
57
  raise(err)
53
58
  end
54
59
 
55
- (self.suite.count(:fail) + self.suite.count(:error)).tap do
60
+ (self.fail_result_count + self.error_result_count).tap do
56
61
  self.view.on_finish
57
62
  self.suite.on_finish
58
63
  self.on_finish
@@ -76,12 +81,11 @@ module Assert
76
81
  private
77
82
 
78
83
  def tests_to_run
84
+ srand self.runner_seed
79
85
  if self.single_test?
80
- [ self.suite.tests.find{ |t| t.file_line == self.single_test_file_line }
81
- ].compact
86
+ [self.suite.find_test_to_run(self.single_test_file_line)].compact
82
87
  else
83
- srand self.runner_seed
84
- self.suite.tests.sort.sort_by{ rand self.suite.tests.size }
88
+ self.suite.sorted_tests_to_run{ rand self.tests_to_run_count }
85
89
  end
86
90
  end
87
91
 
data/lib/assert/suite.rb CHANGED
@@ -3,6 +3,12 @@ require 'assert/test'
3
3
 
4
4
  module Assert
5
5
 
6
+ # This is the base suite. It loads the tests to run in memory and provides
7
+ # methods for these tests that the runner/view uses for handling and
8
+ # presentation purposes. It also stores suite-level setups and teardowns.
9
+ # Override the test/result count methods and the callbacks as needed. See
10
+ # the default suite for example usage.
11
+
6
12
  class Suite
7
13
  include Assert::ConfigHelpers
8
14
 
@@ -11,7 +17,7 @@ module Assert
11
17
  # A suite is a set of tests to run. When a test class subclasses
12
18
  # the Context class, that test class is pushed to the suite.
13
19
 
14
- attr_reader :config, :tests, :test_methods, :setups, :teardowns
20
+ attr_reader :config, :test_methods, :setups, :teardowns
15
21
  attr_accessor :start_time, :end_time
16
22
 
17
23
  def initialize(config)
@@ -36,6 +42,26 @@ module Assert
36
42
  end
37
43
  alias_method :shutdown, :teardown
38
44
 
45
+ def tests_to_run?; @tests.size > 0; end
46
+ def tests_to_run_count; @tests.size; end
47
+ def clear_tests_to_run; @tests.clear; end
48
+
49
+ def find_test_to_run(file_line)
50
+ @tests.find{ |t| t.file_line == file_line }
51
+ end
52
+
53
+ def sorted_tests_to_run(&sort_by_proc)
54
+ @tests.sort.sort_by(&sort_by_proc)
55
+ end
56
+
57
+ def test_count; end
58
+ def result_count; end
59
+ def pass_result_count; end
60
+ def fail_result_count; end
61
+ def error_result_count; end
62
+ def skip_result_count; end
63
+ def ignore_result_count; end
64
+
39
65
  def run_time
40
66
  @end_time - @start_time
41
67
  end
@@ -48,55 +74,26 @@ module Assert
48
74
  get_rate(self.result_count, self.run_time)
49
75
  end
50
76
 
51
- def count(thing)
52
- if thing == :tests
53
- test_count
54
- elsif thing == :results
55
- result_count
56
- elsif thing == :pass || thing == :passed
57
- result_count(:pass)
58
- elsif thing == :fail || thing == :failed
59
- result_count(:fail)
60
- elsif thing == :error || thing == :errored
61
- result_count(:error)
62
- elsif thing == :skip || thing == :skipped
63
- result_count(:skip)
64
- elsif thing == :ignore || thing == :ignored
65
- result_count(:ignore)
66
- else
67
- 0
68
- end
69
- end
70
-
71
- # Test data
72
-
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
-
79
- # Result data
80
-
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
77
  # Callbacks
88
78
 
89
79
  # define callback handlers to do special behavior during the test run. These
90
80
  # will be called by the test runner
91
81
 
92
82
  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
83
+
84
+ # this is required to load tests into the suite, be sure to `super` if you
85
+ # override this method
86
+ def on_test(test)
87
+ @tests << test
88
+ end
89
+
90
+ def after_load; end
91
+ def on_start; end
92
+ def before_test(test); end
93
+ def on_result(result); end
94
+ def after_test(test); end
95
+ def on_finish; end
96
+ def on_interrupt(err); end
100
97
 
101
98
  def inspect
102
99
  "#<#{self.class}:#{'0x0%x' % (object_id << 1)}"\
@@ -104,12 +101,6 @@ module Assert
104
101
  " result_count=#{self.result_count.inspect}>"
105
102
  end
106
103
 
107
- private
108
-
109
- def get_rate(count, time)
110
- time == 0 ? 0.0 : (count.to_f / time.to_f)
111
- end
112
-
113
104
  end
114
105
 
115
106
  end
data/lib/assert/test.rb CHANGED
@@ -9,10 +9,6 @@ module Assert
9
9
  # a Test is some code/method to run in the scope of a Context that may
10
10
  # produce results
11
11
 
12
- def self.result_count_meth(type)
13
- "#{type}_result_count".to_sym
14
- end
15
-
16
12
  def self.name_file_line_context_data(ci, name)
17
13
  { :name => ci.test_name(name),
18
14
  :file_line => ci.called_from
@@ -35,82 +31,55 @@ module Assert
35
31
  }))
36
32
  end
37
33
 
38
- attr_reader :results
39
- attr_writer :total_result_count
40
-
41
34
  def initialize(build_data = nil)
42
- @build_data, @results = build_data || {}, []
35
+ @build_data = build_data || {}
36
+ @result_callback = nil
43
37
  end
44
38
 
45
- def file_line; @file_line ||= FileLine.parse((@build_data[:file_line] || '').to_s); end
46
- def name; @name ||= (@build_data[:name] || ''); end
47
- def output; @output ||= (@build_data[:output] || ''); end
48
- def run_time; @run_time ||= (@build_data[:run_time] || 0); end
49
-
50
- def total_result_count
51
- @total_result_count ||= (@build_data[:total_result_count] || 0)
39
+ def file_line
40
+ @file_line ||= FileLine.parse((@build_data[:file_line] || '').to_s)
52
41
  end
53
42
 
54
- Assert::Result.types.keys.each do |type|
55
- n = result_count_meth(type)
56
- define_method(n) do
57
- instance_variable_get("@#{n}") || instance_variable_set("@#{n}", @build_data[n] || 0)
58
- end
43
+ def file_name; self.file_line.file; end
44
+ def line_num; self.file_line.line.to_i; end
45
+
46
+ def name
47
+ @name ||= (@build_data[:name] || '')
59
48
  end
60
49
 
61
- def context_info; @context_info ||= @build_data[:context_info]; end
62
- def config; @config ||= @build_data[:config]; end
63
- def code; @code ||= @build_data[:code]; end
50
+ def output
51
+ @output ||= (@build_data[:output] || '')
52
+ end
64
53
 
65
- def data
66
- { :file_line => self.file_line.to_s,
67
- :name => self.name.to_s,
68
- :output => self.output.to_s,
69
- :run_time => self.run_time
70
- }.merge(result_count_data(:total_result_count => self.total_result_count))
54
+ def run_time
55
+ @run_time ||= (@build_data[:run_time] || 0)
71
56
  end
72
57
 
73
- def context_class; self.context_info.klass; end
74
- def file; self.file_line.file; end
75
- def line_number; self.file_line.line; end
58
+ def context_info
59
+ @context_info ||= @build_data[:context_info]
60
+ end
76
61
 
77
- def result_rate
78
- get_rate(self.result_count, self.run_time)
62
+ def context_class
63
+ self.context_info.klass
79
64
  end
80
65
 
81
- def result_count(type = nil)
82
- if Assert::Result.types.keys.include?(type)
83
- self.send(result_count_meth(type))
84
- else
85
- self.total_result_count
86
- end
66
+ def config
67
+ @config ||= @build_data[:config]
87
68
  end
88
69
 
89
- def capture_result(result, callback)
90
- self.results << result
91
- self.total_result_count += 1
92
- n = result_count_meth(result.to_sym)
93
- instance_variable_set("@#{n}", (instance_variable_get("@#{n}") || 0) + 1)
94
- callback.call(result)
70
+ def code
71
+ @code ||= @build_data[:code]
95
72
  end
96
73
 
97
74
  def run(&result_callback)
98
- result_callback ||= proc{ |result| } # do nothing by default
99
- scope = self.context_class.new(self, self.config, result_callback)
75
+ @result_callback = result_callback || proc{ |result| } # noop by default
76
+ scope = self.context_class.new(self, self.config, @result_callback)
100
77
  start_time = Time.now
101
78
  capture_output do
102
- self.context_class.run_arounds(scope) do
103
- run_test(scope, result_callback)
104
- end
79
+ self.context_class.run_arounds(scope){ run_test(scope) }
105
80
  end
81
+ @result_callback = nil
106
82
  @run_time = Time.now - start_time
107
- @results
108
- end
109
-
110
- Assert::Result.types.each do |name, klass|
111
- define_method "#{name}_results" do
112
- self.results.select{|r| r.kind_of?(klass) }
113
- end
114
83
  end
115
84
 
116
85
  def <=>(other_test)
@@ -118,7 +87,7 @@ module Assert
118
87
  end
119
88
 
120
89
  def inspect
121
- attributes_string = ([ :name, :context_info, :results ].collect do |attr|
90
+ attributes_string = ([:name, :context_info].collect do |attr|
122
91
  "@#{attr}=#{self.send(attr).inspect}"
123
92
  end).join(" ")
124
93
  "#<#{self.class}:#{'0x0%x' % (object_id << 1)} #{attributes_string}>"
@@ -126,7 +95,7 @@ module Assert
126
95
 
127
96
  private
128
97
 
129
- def run_test(scope, result_callback)
98
+ def run_test(scope)
130
99
  begin
131
100
  # run any assert style 'setup do' setups
132
101
  self.context_class.run_setups(scope)
@@ -135,13 +104,13 @@ module Assert
135
104
  # run the code block
136
105
  scope.instance_eval(&(self.code || proc{}))
137
106
  rescue Result::TestFailure => err
138
- capture_result(Result::Fail.for_test(self, err), result_callback)
107
+ capture_result(Result::Fail, err)
139
108
  rescue Result::TestSkipped => err
140
- capture_result(Result::Skip.for_test(self, err), result_callback)
109
+ capture_result(Result::Skip, err)
141
110
  rescue SignalException => err
142
111
  raise(err)
143
112
  rescue Exception => err
144
- capture_result(Result::Error.for_test(self, err), result_callback)
113
+ capture_result(Result::Error, err)
145
114
  ensure
146
115
  begin
147
116
  # run any assert style 'teardown do' teardowns
@@ -149,17 +118,21 @@ module Assert
149
118
  # run any test/unit style 'def teardown' teardowns
150
119
  scope.teardown if scope.respond_to?(:teardown)
151
120
  rescue Result::TestFailure => err
152
- capture_result(Result::Fail.for_test(self, err), result_callback)
121
+ capture_result(Result::Fail, err)
153
122
  rescue Result::TestSkipped => err
154
- capture_result(Result::Skip.for_test(self, err), result_callback)
123
+ capture_result(Result::Skip, err)
155
124
  rescue SignalException => err
156
125
  raise(err)
157
126
  rescue Exception => err
158
- capture_result(Result::Error.for_test(self, err), result_callback)
127
+ capture_result(Result::Error, err)
159
128
  end
160
129
  end
161
130
  end
162
131
 
132
+ def capture_result(result_klass, err)
133
+ @result_callback.call(result_klass.for_test(self, err))
134
+ end
135
+
163
136
  def capture_output(&block)
164
137
  if self.config.capture_output == true
165
138
  orig_stdout = $stdout.clone
@@ -175,21 +148,6 @@ module Assert
175
148
  StringIO.new(self.output, "a+")
176
149
  end
177
150
 
178
- def result_count_data(seed)
179
- Assert::Result.types.keys.inject(seed) do |d, t|
180
- d[result_count_meth(t)] = self.send(result_count_meth(t))
181
- d
182
- end
183
- end
184
-
185
- def result_count_meth(type)
186
- self.class.result_count_meth(type)
187
- end
188
-
189
- def get_rate(count, time)
190
- time == 0 ? 0.0 : (count.to_f / time.to_f)
191
- end
192
-
193
151
  end
194
152
 
195
153
  end