assert 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +16 -4
  2. data/{CHANGELOG.rdoc → CHANGELOG.md} +14 -3
  3. data/LICENSE +22 -0
  4. data/README.md +261 -0
  5. data/Rakefile +1 -1
  6. data/assert.gemspec +2 -1
  7. data/lib/assert/assertions.rb +16 -0
  8. data/lib/assert/autorun.rb +11 -7
  9. data/lib/assert/macros/methods.rb +49 -3
  10. data/lib/assert/rake_tasks.rb +13 -7
  11. data/lib/assert/rake_tasks/irb.rb +1 -1
  12. data/lib/assert/rake_tasks/scope.rb +55 -28
  13. data/lib/assert/rake_tasks/test_task.rb +4 -1
  14. data/lib/assert/result.rb +7 -9
  15. data/lib/assert/result_set.rb +7 -4
  16. data/lib/assert/runner.rb +10 -10
  17. data/lib/assert/setup/helpers.rb +5 -3
  18. data/lib/assert/setup/runner.rb +2 -3
  19. data/lib/assert/setup/suite.rb +2 -5
  20. data/lib/assert/setup/view.rb +26 -3
  21. data/lib/assert/test.rb +56 -37
  22. data/lib/assert/version.rb +1 -1
  23. data/lib/assert/view/base.rb +75 -0
  24. data/lib/assert/view/default_view.rb +75 -0
  25. data/lib/assert/view/helpers/ansi_styles.rb +25 -0
  26. data/lib/assert/view/helpers/capture_output.rb +23 -0
  27. data/lib/assert/view/helpers/common.rb +154 -0
  28. data/test/assertions/assert_file_exists_test.rb +43 -0
  29. data/test/assertions/assert_not_file_exists_test.rb +43 -0
  30. data/test/assertions_test.rb +4 -1
  31. data/test/macro_test.rb +25 -0
  32. data/test/rake_tasks/irb_test.rb +2 -2
  33. data/test/rake_tasks/scope_test.rb +9 -9
  34. data/test/result_set_test.rb +13 -23
  35. data/test/runner_test.rb +1 -1
  36. data/test/test/{running_test.rb → running_tests.rb} +14 -14
  37. data/test/view/base_tests.rb +65 -0
  38. metadata +29 -18
  39. data/Gemfile.lock +0 -23
  40. data/README.rdoc +0 -183
@@ -9,18 +9,24 @@ require 'assert/rake_tasks/test_task'
9
9
 
10
10
  module Assert::RakeTasks
11
11
 
12
- FILE_SUFFIX = "_test.rb"
13
-
14
12
  # Setup the rake tasks for testing
15
13
  # * add 'include Assert::RakeTasks' to your Rakefile
16
14
  def self.included(receiver)
17
- # auto-build rake tasks for the ./test files (if defined in ./test)
18
- self.for('test') if File.exists?(File.expand_path('./test', Dir.pwd))
15
+ # auto-install rake tasks
16
+ self.install
17
+ end
18
+
19
+ def self.install
20
+ assert_test_root = ENV['ASSERT_TEST_ROOT'] || './test'
21
+
22
+ if File.exists?(assert_test_root)
23
+ self.irb_task(Assert::RakeTasks::Irb.new(assert_test_root))
24
+ self.to_tasks(Assert::RakeTasks::Scope.new(assert_test_root))
25
+ end
19
26
  end
20
27
 
21
- def self.for(test_root='test')
22
- self.irb_task(Assert::RakeTasks::Irb.new(test_root.to_s))
23
- self.to_tasks(Assert::RakeTasks::Scope.new(test_root.to_s))
28
+ def self.for(test_root_name)
29
+ warn "[DEPRECATED] `Assert::RakeTasts.for` has been deprecated. Use `Assert::RakeTasks.install` instead."
24
30
  end
25
31
 
26
32
  class << self
@@ -26,7 +26,7 @@ module Assert::RakeTasks
26
26
  end
27
27
 
28
28
  def cmd
29
- "irb -rubygems -r ./#{self.file_path}"
29
+ "irb -rubygems -r #{self.file_path}"
30
30
  end
31
31
 
32
32
  end
@@ -4,29 +4,25 @@ require 'assert/rake_tasks/test_task'
4
4
  module Assert::RakeTasks
5
5
  class Scope
6
6
 
7
- def self.test_file_suffix
8
- "_test.rb"
7
+ def self.test_file_suffixes
8
+ ['_test.rb', '_tests.rb']
9
9
  end
10
10
 
11
+ attr_reader :path, :nested_files, :path_file_list, :test_tasks, :scopes
12
+
11
13
  def initialize(path)
12
14
  @path = path
15
+
16
+ @nested_files = get_nested_files
17
+ @path_file_list = build_path_file_list
18
+ @test_tasks = build_test_tasks
19
+ @scopes = build_scopes
13
20
  end
14
21
 
15
22
  def namespace
16
23
  File.basename(@path).to_sym
17
24
  end
18
25
 
19
- # nested test files under the path
20
- def nested_files
21
- nested_files = Rake::FileList["#{@path}/**/*#{self.class.test_file_suffix}"]
22
- end
23
-
24
- # a list with the path test file "#{path}_test.rb" (if it exists)
25
- def path_file_list
26
- path_file_name = @path+self.class.test_file_suffix
27
- (File.exists?(path_file_name) ? Rake::FileList[path_file_name] : [])
28
- end
29
-
30
26
  # return a test task covering the scopes nested files plus path file
31
27
  # but only if there are nested files
32
28
  def to_test_task
@@ -37,32 +33,63 @@ module Assert::RakeTasks
37
33
  end
38
34
  end
39
35
 
36
+ protected
37
+
38
+ # nested test files under the path
39
+
40
+ def get_nested_files
41
+ self.class.test_file_suffixes.map do |suffix|
42
+ Rake::FileList["#{@path}/**/*#{suffix}"]
43
+ end.flatten
44
+ end
45
+
46
+ # a list with the path test file "#{path}_test.rb" (if it exists)
47
+
48
+ def build_path_file_list
49
+ self.class.test_file_suffixes.map do |suffix|
50
+ path_file_name = "#{@path}#{suffix}"
51
+ File.exists?(path_file_name) ? Rake::FileList[path_file_name] : []
52
+ end.flatten
53
+ end
54
+
40
55
  # a collection of test tasks for every standalone child test file
41
- def test_tasks
42
- # get immediate child test files
43
- Dir.glob("#{@path}/*#{self.class.test_file_suffix}").collect do |f|
44
- # get just the path name for each file
45
- File.join(File.dirname(f), File.basename(f, self.class.test_file_suffix))
46
- end.reject do |p|
56
+
57
+ def build_test_tasks
58
+ self.class.test_file_suffixes.map do |suffix|
59
+ # get immediate child test files
60
+ Dir.glob("#{@path}/*#{suffix}").collect do |f|
61
+ # get just the path name for each file
62
+ File.join(File.dirname(f), File.basename(f, suffix))
63
+ end
64
+ end.flatten.reject do |p|
47
65
  # reject any that have deeply nested test files
48
- !Dir.glob("#{p}/**/*#{self.class.test_file_suffix}").empty?
66
+ self.class.test_file_suffixes.inject(false) do |result, suffix|
67
+ result || !Dir.glob("#{p}/**/*#{suffix}").empty?
68
+ end
49
69
  end.collect do |p|
50
70
  # build a test task for the standalone test file of the path
51
71
  TestTask.new(p) do |tt|
52
- tt.files = Rake::FileList[p+self.class.test_file_suffix]
72
+ tt.files = self.class.test_file_suffixes.map do |suffix|
73
+ (File.exists?("#{p}#{suffix}") ? Rake::FileList["#{p}#{suffix}"] : [])
74
+ end.flatten
53
75
  end
54
76
  end
55
77
  end
56
78
 
57
79
  # a collection of scopes for every child test dir or test dir/file combo
58
- def scopes
59
- # get immediate child paths
60
- Dir.glob("#{@path}/*").collect do |p|
61
- # get just the path name for each dir/file and uniq it
62
- File.join(File.dirname(p), File.basename(p, self.class.test_file_suffix))
63
- end.uniq.select do |p|
80
+
81
+ def build_scopes
82
+ self.class.test_file_suffixes.map do |suffix|
83
+ # get immediate child paths
84
+ Dir.glob("#{@path}/*").collect do |p|
85
+ # get just the path name for each dir/file and uniq it
86
+ File.join(File.dirname(p), File.basename(p, suffix))
87
+ end
88
+ end.flatten.uniq.select do |p|
64
89
  # select any that have deeply nested test files
65
- !Dir.glob("#{p}/**/*#{self.class.test_file_suffix}").empty?
90
+ self.class.test_file_suffixes.inject(false) do |result, suffix|
91
+ result || !Dir.glob("#{p}/**/*#{suffix}").empty?
92
+ end
66
93
  end.collect do |p|
67
94
  # build a scope for each path
68
95
  self.class.new(p)
@@ -26,7 +26,10 @@ module Assert::RakeTasks
26
26
  end
27
27
 
28
28
  def name
29
- File.basename(@path, Scope.test_file_suffix).to_sym
29
+ # File.basename(@path, Scope.test_file_suffix).to_sym
30
+ @name ||= File.basename(@path).tap do |bname|
31
+ Scope.test_file_suffixes.each { |suffix| bname.gsub(suffix, '') }
32
+ end.to_sym
30
33
  end
31
34
 
32
35
  def file_list # :nodoc:
@@ -8,15 +8,13 @@ module Assert::Result
8
8
  class Error < Base; end
9
9
  class Skip < Base; end
10
10
 
11
- class << self
12
- def types
13
- { :pass => Pass,
14
- :fail => Fail,
15
- :ignore => Ignore,
16
- :skip => Skip,
17
- :error => Error
18
- }
19
- end
11
+ def self.types
12
+ { :pass => Pass,
13
+ :fail => Fail,
14
+ :ignore => Ignore,
15
+ :skip => Skip,
16
+ :error => Error
17
+ }
20
18
  end
21
19
 
22
20
  class Backtrace < ::Array
@@ -1,13 +1,16 @@
1
1
  module Assert
2
2
  class ResultSet < ::Array
3
3
 
4
- attr_accessor :view
4
+ attr_accessor :callback
5
+
6
+ def initialize(callback=nil)
7
+ @callback = callback
8
+ super()
9
+ end
5
10
 
6
11
  def <<(result)
7
12
  super
8
- if @view && @view.respond_to?(:handle_runtime_result)
9
- @view.handle_runtime_result(result)
10
- end
13
+ @callback.call(result) if @callback
11
14
  end
12
15
 
13
16
  end
@@ -9,19 +9,15 @@ module Assert
9
9
  @view = view
10
10
  end
11
11
 
12
- def run(render=true)
12
+ def run
13
+ @view.fire(:on_start)
13
14
  @suite.setup
14
15
 
15
- if render
16
- # render the view, passing it a callback block to run the test suite
17
- @view.render do
18
- benchmark { run_suite }
19
- end
20
- else
21
- benchmark { run_suite }
22
- end
16
+ benchmark { run_suite }
23
17
 
24
18
  @suite.teardown
19
+ @view.fire(:on_finish)
20
+
25
21
  count(:failed) + count(:errored)
26
22
  end
27
23
 
@@ -48,7 +44,11 @@ module Assert
48
44
 
49
45
  def run_suite
50
46
  # TODO: parallel running
51
- tests_to_run.each {|test| test.run(@view)}
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
52
52
  end
53
53
 
54
54
  end
@@ -8,9 +8,10 @@ module Assert
8
8
  # the user-specific helper file will always be required in after the
9
9
  # package-specific one
10
10
 
11
- class << self
11
+ USER_TEST_DIR = './.assert'
12
+ USER_TEST_HELPER = 'options'
12
13
 
13
- USER_TEST_HELPER = "./.assert/options"
14
+ class << self
14
15
 
15
16
  # assume the test dir path is ./test and look for helpers in ./test/helper.rb
16
17
  def package_test_dir
@@ -34,7 +35,8 @@ module Assert
34
35
 
35
36
  def require_user_test_helper
36
37
  if ENV['HOME']
37
- safe_require File.expand_path(USER_TEST_HELPER, ENV['HOME'])
38
+ helper_path = File.join(USER_TEST_DIR, USER_TEST_HELPER)
39
+ safe_require File.expand_path(helper_path, ENV['HOME'])
38
40
  end
39
41
  end
40
42
 
@@ -2,13 +2,12 @@ require 'assert/options'
2
2
  require 'assert/runner'
3
3
 
4
4
  module Assert
5
+
5
6
  # Setup the default global runner for running tests
6
7
  options do
7
8
  default_runner Runner
8
9
  end
9
10
 
10
- class << self
11
- def runner; self.options.runner; end
12
- end
11
+ def self.runner; self.options.runner; end
13
12
 
14
13
  end
@@ -2,15 +2,12 @@ require 'assert/context'
2
2
  require 'assert/suite'
3
3
 
4
4
  module Assert
5
+
5
6
  # Setup the default global suite for collecting tests as contexts are defined
6
7
  options do
7
8
  default_suite Suite.new
8
9
  end
9
10
 
10
- class << self
11
- def suite
12
- self.options.suite
13
- end
14
- end
11
+ def self.suite; self.options.suite; end
15
12
 
16
13
  end
@@ -1,3 +1,4 @@
1
+ require 'assert/setup/helpers'
1
2
  require 'assert/view/default_view'
2
3
 
3
4
  module Assert
@@ -8,9 +9,31 @@ module Assert
8
9
  default_view View::DefaultView.new($stdout)
9
10
  end
10
11
 
11
- # setup the global Assert.view method
12
- class << self
13
- def view; self.options.view; end
12
+ def self.view; self.options.view; end
13
+
14
+ module View
15
+
16
+ # this method is used to bring in custom user-specific views
17
+ # require views by passing either a full path to the view ruby file
18
+ # or passing the name of a view installed in ~/.assert/views
19
+
20
+ def self.require_user_view(view)
21
+ user_test_root = File.expand_path(Assert::Helpers::USER_TEST_DIR, ENV['HOME'])
22
+ views_file = File.join(user_test_root, 'views', view, 'lib', view)
23
+
24
+ if File.exists?(view) || File.exists?(view+'.rb')
25
+ require view
26
+ elsif ENV['HOME'] && File.exists?(views_file+'.rb')
27
+ require views_file
28
+ else
29
+ msg = "[WARN] Can't find or require #{view.inspect} view."
30
+ if !view.match(/\A\//)
31
+ msg << " Did you install it in `~/.assert/views`?"
32
+ end
33
+ warn msg
34
+ end
35
+ end
36
+
14
37
  end
15
38
 
16
39
  end
@@ -34,44 +34,29 @@ module Assert
34
34
  self.context_info.klass
35
35
  end
36
36
 
37
- def run(view=nil)
38
- @results.view = view
37
+ def run(&result_callback)
38
+ # setup the a new test run
39
+ @results = ResultSet.new(result_callback)
39
40
  run_scope = self.context_class.new(self)
40
- capture_output(StringIO.new(@output, "w+")) do
41
+
42
+ # run the test, capturing its output
43
+ begin
44
+ run_test_setup(run_scope)
45
+ run_test_code(run_scope)
46
+ rescue Result::TestFailure => err
47
+ @results << Result::Fail.new(self, err)
48
+ rescue Result::TestSkipped => err
49
+ @results << Result::Skip.new(self, err)
50
+ rescue Exception => err
51
+ @results << Result::Error.new(self, err)
52
+ ensure
41
53
  begin
42
- # run any assert style 'setup do' setups
43
- self.context_class.setup(run_scope)
44
- # run any classic test/unit style 'def setup' setups
45
- if run_scope.respond_to?(:setup)
46
- run_scope.setup
47
- end
48
-
49
- # run the actual test code
50
- if @code.kind_of?(::Proc)
51
- run_scope.instance_eval(&@code)
52
- elsif run_scope.respond_to?(@code.to_s)
53
- run_scope.send(@code.to_s)
54
- end
55
- rescue Result::TestFailure => err
56
- @results << Result::Fail.new(self, err)
57
- rescue Result::TestSkipped => err
58
- @results << Result::Skip.new(self, err)
59
- rescue Exception => err
60
- @results << Result::Error.new(self, err)
61
- ensure
62
- begin
63
- # run any classic test/unit style 'def teardown' teardowns
64
- if run_scope.respond_to?(:teardown)
65
- run_scope.teardown
66
- end
67
- # run any assert style 'teardown do' teardowns
68
- self.context_class.teardown(run_scope)
69
- rescue Exception => teardown_err
70
- @results << Result::Error.new(self, teardown_err)
71
- end
54
+ run_test_teardown(run_scope)
55
+ rescue Exception => teardown_err
56
+ @results << Result::Error.new(self, teardown_err)
72
57
  end
73
58
  end
74
- @results.view = nil
59
+ # return the results of the test run
75
60
  @results
76
61
  end
77
62
 
@@ -102,10 +87,40 @@ module Assert
102
87
 
103
88
  protected
104
89
 
105
- def capture_output(io, &block)
106
- if self.class.options.capture_output && io
90
+ def run_test_setup(scope)
91
+ capture_output do
92
+ # run any assert style 'setup do' setups
93
+ self.context_class.setup(scope)
94
+
95
+ # run any classic test/unit style 'def setup' setups
96
+ scope.setup if scope.respond_to?(:setup)
97
+ end
98
+ end
99
+
100
+ def run_test_code(scope)
101
+ capture_output do
102
+ if @code.kind_of?(::Proc)
103
+ scope.instance_eval(&@code)
104
+ elsif scope.respond_to?(@code.to_s)
105
+ scope.send(@code.to_s)
106
+ end
107
+ end
108
+ end
109
+
110
+ def run_test_teardown(scope)
111
+ capture_output do
112
+ # run any classic test/unit style 'def teardown' teardowns
113
+ scope.teardown if scope.respond_to?(:teardown)
114
+
115
+ # run any assert style 'teardown do' teardowns
116
+ self.context_class.teardown(scope)
117
+ end
118
+ end
119
+
120
+ def capture_output(&block)
121
+ if self.class.options.capture_output
107
122
  orig_stdout = $stdout.clone
108
- $stdout = io
123
+ $stdout = capture_io
109
124
  block.call
110
125
  $stdout = orig_stdout
111
126
  else
@@ -113,6 +128,10 @@ module Assert
113
128
  end
114
129
  end
115
130
 
131
+ def capture_io
132
+ StringIO.new(@output, "a+")
133
+ end
134
+
116
135
  def name_from_context(name)
117
136
  [ self.context_class.description,
118
137
  name