assert 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ == Assert Changes
2
+
3
+ === v0.7.0
4
+ * tests know context info (klass, called_from, file) (#62)
5
+ * suites track tests ungrouped
6
+ * fixed issue where method macros display incorrect fail traces
7
+ * fixed bug where 'assert_raises' and 'assert_nothing_raised' generate fail messages with trailing newlines
8
+ * default halt on failed assertions (#68)
9
+ * fixed for setup error when no $HOME env var (#76)
10
+ * changelog tracking (#79)
11
+ * removed past tense from Result model #to_sym (#75)
12
+ * showing exception class in Error result message (#64)
13
+ * don't show verbose loading statement when running rake tasks (#72)
14
+ * forced loading rubygems when running rake tasks (#65)
15
+ * removed warning if no test/helper present (#66)
16
+ * fix to not load helpers twice (#67)
17
+ * overhaul to how the rake tasks are generated and handled (#69)
18
+ * added name attr to Result model (#61)
19
+
20
+ === v0.6.0
21
+ * everything prior to changelog tracking...
@@ -1,18 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- assert (0.6.0)
5
- assert-view (~> 0.3)
4
+ assert (0.7.0)
5
+ assert-view (~> 0.4)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
10
  ansi (1.3.0)
11
- assert-view (0.3.0)
11
+ assert-view (0.4.0)
12
12
  ansi (~> 1.3)
13
13
  undies (~> 1.1)
14
14
  rake (0.9.2)
15
- undies (1.1.0)
15
+ undies (1.2.0)
16
16
 
17
17
  PLATFORMS
18
18
  ruby
@@ -65,13 +65,18 @@ Result defines the data related to a test result. There are a few kinds of test
65
65
  * Skip
66
66
  * Ignore
67
67
 
68
- Tests can have many results of varying types.
68
+ Tests produce results as they are executed. Every assert statement produces a result. Some results, like Error and Skip, will halt execution. Pass and Ignore results do not halt execution. Fail results, by default, halt execution but there is an option to have them not halt execution. Therefore, tests can have many results of varying types.
69
69
 
70
70
  === Macro
71
71
  Macros are procs that define sets of test code and make it available for easy reuse. Macros work nicely with the 'should' and 'test' context methods.
72
72
 
73
73
 
74
74
 
75
+ == User Options and Helpers
76
+ Assert provides ways for setting user-specfic options and helpers. When Assert is setting itself up, the last setup step is to look for and require the file ~/.assert/options.rb. This file is essentially a user level test helper file. Use it to set options, configure assert extensions, setup or define how to view test results, etc.
77
+
78
+
79
+
75
80
  == Running Tests
76
81
  Assert uses a Runner object to run tests. Any runner object should take the test suite and view as arguments and should provide a 'run' method that runs the tests and renders the view.
77
82
 
@@ -84,6 +89,14 @@ The default Runner object runs tests in random order and the default Terminal vi
84
89
  $ rake test # run tests in random order
85
90
  $ rake test runner_seed=1234 # run tests seeding with '1234'
86
91
 
92
+ === Failure Handling
93
+ Assert, by default, will halt test execution when a test produces a Fail result. However, Assert provides an option to not halt when Fail results are produced. You can control how assert handles fails by either setting an option (in your user .assert/options.rb file) or by setting an env variable:
94
+
95
+ Assert::Test.options.halt_on_fail false # force not halting on fail results
96
+
97
+ $ rake test halt_on_fail=true # force halt on failure using an env var
98
+
99
+
87
100
  === Rake Tasks
88
101
  Assert provides some rake task helpers that will scan your test folder and recursively generate rake tasks for each one of your test folders or files ending in '_test'. Use this as an alternative to running ruby on each one of your test files individually.
89
102
 
@@ -110,6 +123,10 @@ This would generate following rake tasks:
110
123
  rake test:complex:fast # Run tests for assertions:assert_block
111
124
  rake test:complex:slow # Run tests for assertions:assert_empty
112
125
 
126
+ By default, the rake tasks do not show which test files are being loaded. If you want to see this output from the rake tasks, set a "show_loaded_files" environment variable at the rake command line:
127
+
128
+ $ rake test show_loaded_files=true # run the tests showing which files were loaded
129
+
113
130
  === IRB with your environment loaded
114
131
  Assert provides a rake task for running irb with your test environment loaded. Create an irb.rb file in your test file directory and have it require 'assert/setup'. See https://github.com/teaminsight/assert/blob/master/test/irb.rb for an example. Here's how you could use it:
115
132
 
@@ -18,5 +18,5 @@ Gem::Specification.new do |s|
18
18
  s.require_paths = ["lib"]
19
19
 
20
20
  s.add_development_dependency("bundler", ["~> 1.0"])
21
- s.add_dependency("assert-view", ["~> 0.3"])
21
+ s.add_dependency("assert-view", ["~> 0.4"])
22
22
  end
@@ -15,14 +15,14 @@ module Assert
15
15
 
16
16
 
17
17
  def assert_raises(*args, &block)
18
- assertion, fail_desc = check_exception(args, :raises, &block)
19
- assert(assertion, fail_desc, "")
18
+ assertion, what_failed_msg = check_exception(args, :raises, &block)
19
+ assert(assertion, nil, what_failed_msg)
20
20
  end
21
21
  alias_method :assert_raise, :assert_raises
22
22
 
23
23
  def assert_nothing_raised(*args, &block)
24
- assertion, fail_desc = check_exception(args, :not_raises, &block)
25
- assert(!assertion, fail_desc, "")
24
+ assertion, what_failed_msg = check_exception(args, :not_raises, &block)
25
+ assert(!assertion, nil, what_failed_msg)
26
26
  end
27
27
  alias_method :assert_not_raises, :assert_nothing_raised
28
28
  alias_method :assert_not_raise, :assert_nothing_raised
@@ -1,4 +1,4 @@
1
- require 'assert/setup'
1
+ require 'assert/setup/all'
2
2
 
3
3
  module Assert
4
4
 
@@ -14,9 +14,23 @@ module Assert
14
14
  # minimal base logic/methods/instance_vars. The instance should remain
15
15
  # pure to not pollute test scopes.
16
16
 
17
- # if a class subclasses Context, add it to the suite
18
- def self.inherited(klass)
19
- Assert.suite << klass
17
+ # if a test method is added to a context manually (not using a context helper):
18
+ # capture any context info, build a test obj, and add it to the suite
19
+ def self.method_added(method_name)
20
+ if method_name.to_s =~ Suite::TEST_METHOD_REGEX
21
+ called_from = caller.first
22
+ klass_method_name = "#{self}##{method_name}"
23
+
24
+ if Assert.suite.test_methods.include?(klass_method_name)
25
+ puts "WARNING: redefining '#{klass_method_name}'"
26
+ puts " from: #{called_from}"
27
+ else
28
+ Assert.suite.test_methods << klass_method_name
29
+ end
30
+
31
+ ci = Suite::ContextInfo.new(self, called_from)
32
+ Assert.suite.tests << Test.new(method_name.to_s, ci, method_name)
33
+ end
20
34
  end
21
35
 
22
36
  # put all logic here to keep context instances pure for running tests
@@ -99,7 +113,8 @@ module Assert
99
113
  end
100
114
  end
101
115
 
102
- def test(desc_or_macro, &block)
116
+ def test(desc_or_macro, called_from=nil, &block)
117
+ called_from ||= caller.first
103
118
  if desc_or_macro.kind_of?(Macro)
104
119
  instance_eval(&desc_or_macro)
105
120
  else
@@ -108,34 +123,27 @@ module Assert
108
123
  # if no block given, create a test that just skips
109
124
  method_block = block_given? ? block : (Proc.new { skip })
110
125
 
111
- # instead of using the typical 'method_defined?' pattern (which) checks
112
- # all parent contexts, we really just need to make sure the method_name
113
- # is not part of self's local_pulic_test_methods for this check
114
- if Assert.suite.send(:local_public_test_methods, self).include?(method_name)
115
- from = caller.first
116
- puts "WARNING: should #{desc_or_macro.inspect} is redefining #{method_name}!"
117
- puts " from: #{from}"
118
- puts " self: #{self.inspect}"
119
- end
120
-
121
- define_method(method_name, &method_block)
126
+ ci = Suite::ContextInfo.new(self, called_from)
127
+ Assert.suite.tests << Test.new(method_name, ci, &method_block)
122
128
  end
123
129
  end
124
130
 
125
- def test_eventually(desc, &block)
126
- test(desc)
131
+ def test_eventually(desc_or_macro, called_from=nil, &block)
132
+ called_from ||= caller.first
133
+ test(desc_or_macro, called_from)
127
134
  end
128
135
  alias_method :test_skip, :test_eventually
129
136
 
130
- def should(desc_or_macro, &block)
137
+ def should(desc_or_macro, called_from=nil, &block)
138
+ called_from ||= caller.first
131
139
  if !desc_or_macro.kind_of?(Macro)
132
140
  desc_or_macro = "should #{desc_or_macro}"
133
141
  end
134
- test(desc_or_macro, &block)
142
+ test(desc_or_macro, called_from, &block)
135
143
  end
136
144
 
137
- def should_eventually(desc, &block)
138
- should(desc)
145
+ def should_eventually(desc_or_macro, called_from=nil, &block)
146
+ should(desc_or_macro, called_from)
139
147
  end
140
148
  alias_method :should_skip, :should_eventually
141
149
 
@@ -176,35 +184,39 @@ module Assert
176
184
  end
177
185
  alias_method :refute, :assert_not
178
186
 
179
- # adds a Skip result to the end of the test's results and breaks test execution
180
- def skip(skip_msg=nil)
181
- raise(Result::TestSkipped, skip_msg || "")
182
- end
183
-
184
187
  # adds a Pass result to the end of the test's results
185
188
  # does not break test execution
186
189
  def pass(pass_msg=nil)
187
- capture_result do |test_name, backtrace|
188
- Assert::Result::Pass.new(test_name, pass_msg, backtrace)
190
+ capture_result do |test, backtrace|
191
+ Assert::Result::Pass.new(test, pass_msg, backtrace)
192
+ end
193
+ end
194
+
195
+ # adds an Ignore result to the end of the test's results
196
+ # does not break test execution
197
+ def ignore(ignore_msg=nil)
198
+ capture_result do |test, backtrace|
199
+ Assert::Result::Ignore.new(test, ignore_msg, backtrace)
189
200
  end
190
201
  end
191
202
 
192
203
  # adds a Fail result to the end of the test's results
193
204
  # does not break test execution
194
205
  def fail(fail_msg=nil)
195
- capture_result do |test_name, backtrace|
196
- message = (fail_message(fail_msg) { }).call
197
- Assert::Result::Fail.new(test_name, message, backtrace)
206
+ message = (fail_message(fail_msg) { }).call
207
+ if Assert::Test.halt_on_fail?
208
+ raise(Result::TestFailure, message)
209
+ else
210
+ capture_result do |test, backtrace|
211
+ Assert::Result::Fail.new(test, message, backtrace)
212
+ end
198
213
  end
199
214
  end
200
215
  alias_method :flunk, :fail
201
216
 
202
- # adds an Ignore result to the end of the test's results
203
- # does not break test execution
204
- def ignore(ignore_msg=nil)
205
- capture_result do |test_name, backtrace|
206
- Assert::Result::Ignore.new(test_name, ignore_msg, backtrace)
207
- end
217
+ # adds a Skip result to the end of the test's results and breaks test execution
218
+ def skip(skip_msg=nil)
219
+ raise(Result::TestSkipped, skip_msg || "")
208
220
  end
209
221
 
210
222
  def subject
@@ -230,7 +242,7 @@ module Assert
230
242
 
231
243
  def capture_result
232
244
  if block_given?
233
- result = yield @__running_test__.name, caller
245
+ result = yield @__running_test__, caller
234
246
  @__running_test__.results << result
235
247
  result
236
248
  end
@@ -10,9 +10,10 @@ module Assert::Macros
10
10
  module ClassMethods
11
11
 
12
12
  def have_instance_method(*methods)
13
+ called_from = (methods.last.kind_of?(Array) ? methods.pop : caller).first
13
14
  Assert::Macro.new do
14
15
  methods.each do |method|
15
- should "respond to instance method ##{method}" do
16
+ should "respond to instance method ##{method}", called_from do
16
17
  assert_respond_to method, subject, "#{subject.class.name} does not have instance method ##{method}"
17
18
  end
18
19
  end
@@ -21,9 +22,10 @@ module Assert::Macros
21
22
  alias_method :have_instance_methods, :have_instance_method
22
23
 
23
24
  def have_class_method(*methods)
25
+ called_from = (methods.last.kind_of?(Array) ? methods.pop : caller).first
24
26
  Assert::Macro.new do
25
27
  methods.each do |method|
26
- should "respond to class method ##{method}" do
28
+ should "respond to class method ##{method}", called_from do
27
29
  assert_respond_to method, subject.class, "#{subject.class.name} does not have class method ##{method}"
28
30
  end
29
31
  end
@@ -32,17 +34,26 @@ module Assert::Macros
32
34
  alias_method :have_class_methods, :have_class_method
33
35
 
34
36
  def have_reader(*methods)
37
+ unless methods.last.kind_of?(Array)
38
+ methods << caller
39
+ end
35
40
  have_instance_methods(*methods)
36
41
  end
37
42
  alias_method :have_readers, :have_reader
38
43
 
39
44
  def have_writer(*methods)
40
- have_instance_methods(*methods.collect{|m| "#{m}="})
45
+ called = methods.last.kind_of?(Array) ? methods.pop : caller
46
+ writer_meths = methods.collect{|m| "#{m}="}
47
+ writer_meths << called
48
+ have_instance_methods(*writer_meths)
41
49
  end
42
50
  alias_method :have_writers, :have_writer
43
51
 
44
52
  def have_accessor(*methods)
45
- have_instance_methods(*methods.collect{|m| [m, "#{m}="]}.flatten)
53
+ called = methods.last.kind_of?(Array) ? methods.pop : caller
54
+ accessor_meths = methods.collect{|m| [m, "#{m}="]}.flatten
55
+ accessor_meths << called
56
+ have_instance_methods(*accessor_meths)
46
57
  end
47
58
  alias_method :have_accessors, :have_accessor
48
59
 
@@ -1,7 +1,12 @@
1
1
  require 'rake'
2
- require 'rake/tasklib'
3
2
 
4
3
  module Assert; end
4
+ module Assert::RakeTasks; end
5
+
6
+ require 'assert/rake_tasks/irb'
7
+ require 'assert/rake_tasks/scope'
8
+ require 'assert/rake_tasks/test_task'
9
+
5
10
  module Assert::RakeTasks
6
11
 
7
12
  FILE_SUFFIX = "_test.rb"
@@ -10,101 +15,52 @@ module Assert::RakeTasks
10
15
  # * add 'include Assert::RakeTasks' to your Rakefile
11
16
  def self.included(receiver)
12
17
  # auto-build rake tasks for the ./test files (if defined in ./test)
13
- self.for(:test) if File.exists?(File.expand_path('./test', Dir.pwd))
18
+ self.for('test') if File.exists?(File.expand_path('./test', Dir.pwd))
14
19
  end
15
20
 
16
- def self.for(test_namespace = :test)
17
- self.irb_task(test_namespace.to_s)
18
- self.to_tasks(test_namespace.to_s)
19
- end
20
-
21
-
22
-
23
-
24
- class TestTask < Rake::TaskLib
25
-
26
- attr_accessor :name, :description, :test_files
27
-
28
- # Create a testing task.
29
- def initialize(name=:test)
30
- @name = name
31
- @description = "Run tests" + (@name==:test ? "" : " for #{@name}")
32
- @test_files = []
33
- yield self if block_given?
34
- end
35
-
36
- # Define the rake task to run this test suite
37
- def to_task
38
- desc @description
39
- task @name do
40
- RakeFileUtils.verbose(true) { ruby "\"#{rake_loader}\" " + file_list }
41
- end
42
- end
43
-
44
- def file_list # :nodoc:
45
- @test_files.collect{|f| "\"#{f}\""}.join(' ')
46
- end
47
-
48
- protected
49
-
50
- def rake_loader # :nodoc:
51
- find_file('rake/rake_test_loader') or
52
- fail "unable to find rake test loader"
53
- end
54
-
55
- def find_file(fn) # :nodoc:
56
- $LOAD_PATH.each do |path|
57
- file_path = File.join(path, "#{fn}.rb")
58
- return file_path if File.exist? file_path
59
- end
60
- nil
61
- end
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))
62
24
  end
63
25
 
64
26
  class << self
65
27
  include Rake::DSL if defined? Rake::DSL
66
28
 
67
- def irb_task(path)
68
- irb_file = File.join(path, "irb.rb")
69
- if File.exist?(irb_file)
70
- desc "Open irb preloaded with #{irb_file}"
71
- task :irb do
72
- sh "irb -rubygems -r ./#{irb_file}"
29
+ def irb_task(irb)
30
+ if irb.helper_exists?
31
+ desc irb.description
32
+ task irb.class.task_name do
33
+ sh irb.cmd
73
34
  end
74
35
  end
75
36
  end
76
37
 
77
- def to_tasks(path)
78
- suite_name = File.basename(path)
79
-
80
- # define a rake test task for all test files that have addional sub-folder tests
81
- if !Dir.glob(File.join(path, "**/*#{FILE_SUFFIX}")).empty?
82
- TestTask.new(suite_name.to_sym) do |t|
83
- file_location = suite_name == path ? '' : " for #{File.join(path.split(File::SEPARATOR)[1..-1])}"
84
- t.description = "Run all tests#{file_location}"
85
- t.test_files = (File.exists?(p = (path+FILE_SUFFIX)) ? FileList[p] : []) + FileList["#{path}/**/*#{FILE_SUFFIX}"]
86
- end.to_task
38
+ def to_tasks(scope)
39
+ # if there is a test task for the scope
40
+ if (scope_tt = scope.to_test_task)
41
+ # create a rake task to run it
42
+ desc scope_tt.description
43
+ task scope_tt.name do
44
+ RakeFileUtils.verbose(scope_tt.show_loaded_files?) { ruby scope_tt.ruby_args }
45
+ end
87
46
  end
88
47
 
89
- namespace suite_name.to_s do
90
- Dir.glob(File.join(path, "*#{FILE_SUFFIX}")).each do |test_file|
91
- test_name = File.basename(test_file, FILE_SUFFIX)
92
-
93
- # define rake test task for all test files without sub-folder tests
94
- if Dir.glob(File.join(path, test_name, "*#{FILE_SUFFIX}")).empty?
95
- TestTask.new(test_name.to_sym) do |t|
96
- t.description = "Run tests for #{[path.split(File::SEPARATOR), test_name].flatten[1..-1].join(':')}"
97
- t.test_files = FileList[test_file]
98
- end.to_task
48
+ # create a namespace for the scope
49
+ namespace scope.namespace do
50
+ # for each test task in the scope, create a rake task to run it
51
+ scope.test_tasks.each do |test_file_tt|
52
+ desc test_file_tt.description
53
+ task test_file_tt.name do
54
+ RakeFileUtils.verbose(test_file_tt.show_loaded_files?) { ruby test_file_tt.ruby_args }
99
55
  end
100
56
  end
101
57
 
102
- # recursively define rake test tasks for each file
103
- # in each top-level directory
104
- Dir.glob(File.join(path, "*")).each do |test_dir|
105
- self.to_tasks(test_dir)
58
+ # recusively generate rake tasks for each sub-scope in the scope
59
+ scope.scopes.each do |sub_scope|
60
+ self.to_tasks(sub_scope)
106
61
  end
107
62
  end
63
+
108
64
  end
109
65
  end
110
66