assert 2.15.2 → 2.16.0

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 +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