assert 1.1.0 → 2.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.assert.rb +3 -0
  2. data/README.md +182 -108
  3. data/Rakefile +0 -3
  4. data/bin/assert +1 -1
  5. data/lib/assert.rb +75 -4
  6. data/lib/assert/assert_runner.rb +76 -0
  7. data/lib/assert/cli.rb +25 -46
  8. data/lib/assert/context.rb +3 -3
  9. data/lib/assert/result.rb +65 -55
  10. data/lib/assert/runner.rb +19 -38
  11. data/lib/assert/suite.rb +0 -7
  12. data/lib/assert/test.rb +4 -16
  13. data/lib/assert/version.rb +1 -1
  14. data/lib/assert/view.rb +23 -0
  15. data/lib/assert/view/base.rb +10 -19
  16. data/lib/assert/view/default_view.rb +16 -11
  17. data/lib/assert/view/helpers/ansi_styles.rb +1 -1
  18. data/lib/assert/view/helpers/common.rb +37 -16
  19. data/test/assert_test.rb +29 -14
  20. data/test/context/class_methods_test.rb +2 -2
  21. data/test/context_test.rb +28 -50
  22. data/test/helper.rb +4 -2
  23. data/test/runner_test.rb +5 -4
  24. data/test/suite_test.rb +1 -1
  25. data/test/test_test.rb +8 -15
  26. data/test/view/base_tests.rb +20 -37
  27. metadata +17 -39
  28. data/lib/assert/autorun.rb +0 -37
  29. data/lib/assert/options.rb +0 -43
  30. data/lib/assert/rake_tasks.rb +0 -75
  31. data/lib/assert/rake_tasks/irb.rb +0 -33
  32. data/lib/assert/rake_tasks/scope.rb +0 -100
  33. data/lib/assert/rake_tasks/test_task.rb +0 -66
  34. data/lib/assert/result_set.rb +0 -17
  35. data/lib/assert/setup.rb +0 -3
  36. data/lib/assert/setup/all.rb +0 -5
  37. data/lib/assert/setup/helpers.rb +0 -72
  38. data/lib/assert/setup/options.rb +0 -6
  39. data/lib/assert/setup/runner.rb +0 -13
  40. data/lib/assert/setup/suite.rb +0 -13
  41. data/lib/assert/setup/view.rb +0 -39
  42. data/lib/assert/view/helpers/capture_output.rb +0 -23
  43. data/test/default_view_test.rb +0 -16
  44. data/test/irb.rb +0 -5
  45. data/test/options_test.rb +0 -40
  46. data/test/rake_tasks/irb_test.rb +0 -45
  47. data/test/rake_tasks/scope_test.rb +0 -63
  48. data/test/rake_tasks/test_task_test.rb +0 -80
  49. data/test/result_set_test.rb +0 -72
@@ -0,0 +1,76 @@
1
+ module Assert
2
+
3
+ class AssertRunner
4
+ TEST_FILE_SUFFIXES = ['_tests.rb', '_test.rb']
5
+ USER_SETTINGS_FILE = ".assert/init.rb"
6
+ LOCAL_SETTINGS_FILE = ".assert.rb"
7
+
8
+ def initialize(test_paths, test_options)
9
+ require 'assert' # inits config singleton with the default settings
10
+
11
+ apply_user_settings
12
+ apply_local_settings
13
+ apply_option_settings(test_options)
14
+ apply_env_settings
15
+
16
+ files = test_files(test_paths.empty? ? Assert.config.test_dir : test_paths)
17
+ Assert.init(files, {
18
+ :test_dir_path => path_of(Assert.config.test_dir, files.first)
19
+ })
20
+ end
21
+
22
+ def run
23
+ Assert.runner.run(Assert.suite, Assert.view)
24
+ end
25
+
26
+ protected
27
+
28
+ def apply_user_settings
29
+ safe_require("#{ENV['HOME']}/#{USER_SETTINGS_FILE}") if ENV['HOME']
30
+ end
31
+
32
+ def apply_local_settings
33
+ safe_require(ENV['ASSERT_LOCALFILE'] || path_of(LOCAL_SETTINGS_FILE, Dir.pwd))
34
+ end
35
+
36
+ def apply_option_settings(options)
37
+ Assert.config.apply(options)
38
+ end
39
+
40
+ def apply_env_settings
41
+ Assert.configure do |c|
42
+ c.runner_seed ENV['ASSERT_RUNNER_SEED'].to_i if ENV['ASSERT_RUNNER_SEED']
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def test_files(test_paths)
49
+ test_paths.inject(Set.new) do |paths, path|
50
+ paths += Dir.glob("#{path}*") + Dir.glob("#{path}*/**/*")
51
+ end.select{ |p| is_test_file?(p) }.sort
52
+ end
53
+
54
+ def is_test_file?(path)
55
+ TEST_FILE_SUFFIXES.inject(false) do |result, suffix|
56
+ result || path =~ /#{suffix}$/
57
+ end
58
+ end
59
+
60
+ def safe_require(settings_file)
61
+ require settings_file if File.exists?(settings_file)
62
+ end
63
+
64
+ # this method inspects a test path and finds the test dir path.
65
+
66
+ def path_of(segment, a_path)
67
+ full_path = File.expand_path(a_path || '.', Dir.pwd)
68
+ seg_pos = full_path.index(segment_regex(segment))
69
+ File.join(seg_pos && (seg_pos > 0) ? full_path[0..(seg_pos-1)] : full_path, segment)
70
+ end
71
+
72
+ def segment_regex(seg); /^#{seg}$|^#{seg}\/|\/#{seg}\/|\/#{seg}$/; end
73
+
74
+ end
75
+
76
+ end
@@ -1,4 +1,5 @@
1
1
  require 'set'
2
+ require 'assert/assert_runner'
2
3
  require 'assert/version'
3
4
 
4
5
  module Assert
@@ -10,75 +11,53 @@ module Assert
10
11
  end
11
12
 
12
13
  def initialize
13
- @cli = CLIRB.new
14
+ @cli = CLIRB.new do
15
+ option 'runner_seed', 'Use a given seed to run tests', {
16
+ :abbrev => 's', :value => Fixnum
17
+ }
18
+ option 'show_output', 'show stdout output (do not capture)', {
19
+ :abbrev => 'o'
20
+ }
21
+ option 'halt_on_fail', 'halt a test when it fails', {
22
+ :abbrev => 't'
23
+ }
24
+ # show loaded test files, cli err backtraces, etc
25
+ option 'debug', 'run in debug mode'
26
+ end
14
27
  end
15
28
 
16
29
  def run(*args)
30
+ # default debug_mode to the env var
31
+ debug_mode = ENV['ASSERT_DEBUG'] == 'true'
17
32
  begin
18
- @cli.parse!(*args)
19
- tests = @cli.args
20
- tests = ['test'] if tests.empty?
21
- Assert::CLIRunner.new(*tests).run
33
+ # parse manually in the case that parsing fails before the debug arg
34
+ debug_mode ||= args.include?('-d') || args.include?('--debug')
35
+ @cli.parse!(args)
36
+ Assert::AssertRunner.new(@cli.args, @cli.opts).run
22
37
  rescue CLIRB::HelpExit
23
38
  puts help
24
39
  rescue CLIRB::VersionExit
25
40
  puts Assert::VERSION
26
41
  rescue CLIRB::Error => exception
27
- puts "#{exception.message}\n"
28
- puts help
42
+ puts "#{exception.message}\n\n"
43
+ puts debug_mode ? exception.backtrace.join("\n") : help
29
44
  exit(1)
30
45
  rescue Exception => exception
31
46
  puts "#{exception.class}: #{exception.message}"
32
- puts exception.backtrace.join("\n") if ENV['DEBUG']
47
+ puts exception.backtrace.join("\n") if debug_mode
33
48
  exit(1)
34
49
  end
35
-
36
- # Don't call `exit(0)`. The test suite runs as the by an `at_exit`
37
- # callback. Calling `exit(0)` bypasses that callback.
50
+ exit(0)
38
51
  end
39
52
 
40
53
  def help
41
- "Usage: assert [TESTS] [options]\n\n"\
54
+ "Usage: assert [options] [TESTS]\n\n"\
42
55
  "Options:"\
43
56
  "#{@cli}"
44
57
  end
45
58
 
46
59
  end
47
60
 
48
- class CLIRunner
49
- TEST_FILE_SUFFIXES = ['_tests.rb', '_test.rb']
50
-
51
- attr_reader :test_files
52
-
53
- def initialize(*args)
54
- options, test_paths = [
55
- args.last.kind_of?(::Hash) ? args.pop : {},
56
- args
57
- ]
58
-
59
- @test_files = file_paths(test_paths).select{ |f| test_file?(f) }
60
- end
61
-
62
- def run
63
- @test_files.each{ |file| require file }
64
- require 'assert' if @test_files.empty? # show empty test output
65
- end
66
-
67
- private
68
-
69
- def file_paths(test_paths)
70
- test_paths.inject(Set.new) do |paths, path|
71
- paths += Dir.glob("#{path}*") + Dir.glob("#{path}*/**/*")
72
- end
73
- end
74
-
75
- def test_file?(path)
76
- TEST_FILE_SUFFIXES.inject(false) do |result, suffix|
77
- result || path =~ /#{suffix}$/
78
- end
79
- end
80
- end
81
-
82
61
  class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
83
62
  Error = Class.new(RuntimeError);
84
63
  HelpExit = Class.new(RuntimeError); VersionExit = Class.new(RuntimeError)
@@ -204,11 +204,11 @@ module Assert
204
204
  end
205
205
 
206
206
  # adds a Fail result to the end of the test's results
207
- # does not break test execution
207
+ # break test execution if Assert.config.halt_on_fail
208
208
  def fail(fail_msg=nil)
209
209
  message = (fail_message(fail_msg) { }).call
210
- if Assert::Test.halt_on_fail?
211
- raise(Result::TestFailure, message)
210
+ if Assert.config.halt_on_fail
211
+ raise Result::TestFailure, message
212
212
  else
213
213
  capture_result do |test, backtrace|
214
214
  Assert::Result::Fail.new(test, message, backtrace)
@@ -17,59 +17,6 @@ module Assert::Result
17
17
  }
18
18
  end
19
19
 
20
- class Backtrace < ::Array
21
- # ripped from minitest...
22
-
23
- file = File.expand_path __FILE__
24
- # if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
25
- # File.expand_path __FILE__
26
- # elsif __FILE__ =~ /^[^\.]/ then # assume both relative
27
- # require 'pathname'
28
- # pwd = Pathname.new Dir.pwd
29
- # pn = Pathname.new File.expand_path(__FILE__)
30
- # relpath = pn.relative_path_from(pwd) rescue pn
31
- # pn = File.join ".", relpath unless pn.relative?
32
- # pn.to_s
33
- # else # assume both are expanded
34
- # __FILE__
35
- # end
36
-
37
- # './lib' in project dir, or '/usr/local/blahblah' if installed
38
- ASSERT_DIR = File.dirname(File.dirname(file))
39
-
40
- def initialize(value=nil)
41
- super(value || ["No backtrace"])
42
- end
43
-
44
- def to_s
45
- self.join("\n")
46
- end
47
-
48
- def filtered
49
- new_bt = []
50
-
51
- self.each do |line|
52
- break if filter_out?(line)
53
- new_bt << line
54
- end
55
-
56
- new_bt = self.reject { |line| filter_out?(line) } if new_bt.empty?
57
- new_bt = self.dup if new_bt.empty?
58
-
59
- self.class.new(new_bt)
60
- end
61
-
62
- protected
63
-
64
- def filter_out?(line)
65
- line.rindex(ASSERT_DIR, 0)
66
- end
67
-
68
- end
69
-
70
-
71
- # Result classes...
72
-
73
20
  class Base
74
21
 
75
22
  attr_reader :test, :message, :backtrace
@@ -138,8 +85,7 @@ module Assert::Result
138
85
  end
139
86
 
140
87
  # raised by the 'fail' context helper to break test execution
141
- # (if Test.halt_on_fail?)
142
- class TestFailure < RuntimeError; end
88
+ TestFailure = Class.new(RuntimeError)
143
89
 
144
90
  class Fail < Base
145
91
 
@@ -213,6 +159,70 @@ module Assert::Result
213
159
  def trace
214
160
  self.backtrace.to_s
215
161
  end
162
+
163
+ end
164
+
165
+ # Utility Classes
166
+
167
+ class Set < ::Array
168
+ attr_accessor :callback
169
+
170
+ def initialize(callback=nil)
171
+ @callback = callback
172
+ super()
173
+ end
174
+
175
+ def <<(result)
176
+ super
177
+ @callback.call(result) if @callback
178
+ end
179
+ end
180
+
181
+ class Backtrace < ::Array
182
+ def initialize(value=nil)
183
+ super(value || ["No backtrace"])
184
+ end
185
+
186
+ def to_s; self.join("\n"); end
187
+
188
+ def filtered
189
+ new_bt = []
190
+
191
+ self.each do |line|
192
+ break if filter_out?(line)
193
+ new_bt << line
194
+ end
195
+
196
+ new_bt = self.reject { |line| filter_out?(line) } if new_bt.empty?
197
+ new_bt = self.dup if new_bt.empty?
198
+
199
+ self.class.new(new_bt)
200
+ end
201
+
202
+ protected
203
+
204
+ # filter a line out if it's an assert lib line
205
+
206
+ def filter_out?(line)
207
+ # from minitest (for reference)...
208
+ # file = File.expand_path __FILE__
209
+ # if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
210
+ # File.expand_path __FILE__
211
+ # elsif __FILE__ =~ /^[^\.]/ then # assume both relative
212
+ # require 'pathname'
213
+ # pwd = Pathname.new Dir.pwd
214
+ # pn = Pathname.new File.expand_path(__FILE__)
215
+ # relpath = pn.relative_path_from(pwd) rescue pn
216
+ # pn = File.join ".", relpath unless pn.relative?
217
+ # pn.to_s
218
+ # else # assume both are expanded
219
+ # __FILE__
220
+ # end
221
+
222
+ # './lib' in project dir, or '/usr/local/blahblah' if installed
223
+ assert_lib_path = File.expand_path('../..', __FILE__)
224
+ line.rindex(assert_lib_path, 0)
225
+ end
216
226
  end
217
227
 
218
228
  end
@@ -1,54 +1,35 @@
1
1
  module Assert
2
+
2
3
  class Runner
3
4
 
4
- # a Runner runs a suite of tests.
5
+ # Runner runs a suite of tests.
5
6
 
6
- def initialize(suite, view)
7
+ def run(suite, view)
7
8
  raise ArgumentError if !suite.kind_of?(Suite)
8
- @suite = suite
9
- @view = view
10
- end
11
9
 
12
- def run
13
- @view.fire(:on_start)
14
- @suite.setup
10
+ view.fire(:on_start)
11
+ suite.setup
15
12
 
16
- benchmark { run_suite }
17
-
18
- @suite.teardown
19
- @view.fire(:on_finish)
13
+ suite.start_time = Time.now
14
+ # TODO: parallel running
15
+ tests_to_run(suite).each do |test|
16
+ view.fire(:before_test, test)
17
+ test.run{ |result| view.fire(:on_result, result) }
18
+ view.fire(:after_test, test)
19
+ end
20
+ suite.end_time = Time.now
20
21
 
21
- count(:failed) + count(:errored)
22
- end
22
+ suite.teardown
23
+ view.fire(:on_finish)
23
24
 
24
- def count(type)
25
- @suite.count(type)
25
+ suite.count(:failed) + suite.count(:errored)
26
26
  end
27
27
 
28
28
  protected
29
29
 
30
- def tests_to_run
31
- # order tests randomly
32
- tests = @suite.tests
33
- srand @suite.runner_seed
34
- tests.sort.sort_by { rand tests.size }
35
- end
36
-
37
- private
38
-
39
- def benchmark
40
- @suite.start_time = Time.now
41
- yield if block_given?
42
- @suite.end_time = Time.now
43
- end
44
-
45
- def run_suite
46
- # TODO: parallel running
47
- tests_to_run.each do |test|
48
- @view.fire(:before_test, test)
49
- test.run {|result| @view.fire(:on_result, result)}
50
- @view.fire(:after_test, test)
51
- end
30
+ def tests_to_run(suite)
31
+ srand Assert.config.runner_seed # TODO: secure random??
32
+ suite.tests.sort.sort_by { rand suite.tests.size }
52
33
  end
53
34
 
54
35
  end
@@ -36,13 +36,6 @@ module Assert
36
36
  @end_time - @start_time
37
37
  end
38
38
 
39
- def runner_seed
40
- @run_seed ||= (ENV["runner_seed"] || begin
41
- srand
42
- srand % 0xFFFF
43
- end).to_i
44
- end
45
-
46
39
  alias_method :ordered_tests, :tests
47
40
 
48
41
  def results
@@ -1,20 +1,8 @@
1
- require 'assert/result'
2
- require 'assert/result_set'
3
- require 'assert/options'
4
-
5
1
  require 'stringio'
2
+ require 'assert/result'
6
3
 
7
4
  module Assert
8
5
  class Test
9
- include Assert::Options
10
- options do
11
- default_capture_output false
12
- default_halt_on_fail true
13
- end
14
-
15
- def self.halt_on_fail?
16
- ENV['halt_on_fail'] == 'true' || self.options.halt_on_fail
17
- end
18
6
 
19
7
  # a Test is some code/method to run in the scope of a Context. After a
20
8
  # a test runs, it should have some assertions which are its results.
@@ -26,7 +14,7 @@ module Assert
26
14
  @context_info = suite_context_info
27
15
  @name = name_from_context(name)
28
16
  @code = (code || block)
29
- @results = ResultSet.new
17
+ @results = Result::Set.new
30
18
  @output = ""
31
19
  end
32
20
 
@@ -36,7 +24,7 @@ module Assert
36
24
 
37
25
  def run(&result_callback)
38
26
  # setup the a new test run
39
- @results = ResultSet.new(result_callback)
27
+ @results = Result::Set.new(result_callback)
40
28
  run_scope = self.context_class.new(self)
41
29
 
42
30
  # run the test, capturing its output
@@ -118,7 +106,7 @@ module Assert
118
106
  end
119
107
 
120
108
  def capture_output(&block)
121
- if self.class.options.capture_output
109
+ if Assert.config.show_output == false
122
110
  orig_stdout = $stdout.clone
123
111
  $stdout = capture_io
124
112
  block.call