wrong 0.1.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.
- data/README.markdown +56 -0
- data/lib/wrong.rb +3 -0
- data/lib/wrong/adapters/minitest.rb +11 -0
- data/lib/wrong/adapters/test_unit.rb +13 -0
- data/lib/wrong/assert.rb +67 -0
- data/lib/wrong/message/array_diff.rb +87 -0
- data/lib/wrong/message/string_diff.rb +44 -0
- data/lib/wrong/message/test_context.rb +26 -0
- data/lib/wrong/version.rb +3 -0
- data/test/adapters/minitest_test.rb +53 -0
- data/test/adapters/test_unit_test.rb +50 -0
- data/test/basic_assert_test.rb +38 -0
- data/test/catch_raise_test.rb +16 -0
- data/test/failures_test.rb +113 -0
- data/test/message/array_diff_test.rb +59 -0
- data/test/message/string_diff_test.rb +65 -0
- data/test/message/test_context_text.rb +68 -0
- data/test/suite.rb +4 -0
- data/test/test_helper.rb +44 -0
- metadata +189 -0
data/README.markdown
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
## Abstract ##
|
2
|
+
|
3
|
+
Wrong provides a general assert method that takes a predicate block. Assertion failure messages are rich in detail.
|
4
|
+
|
5
|
+
Wrong is alpha-quality - I'd very much appreciate feedback and bug reports.
|
6
|
+
|
7
|
+
It's an offshoot of predicated.
|
8
|
+
[http://github.com/sconover/predicated](http://github.com/sconover/predicated)
|
9
|
+
|
10
|
+
Inspired by assert { 2.0 }
|
11
|
+
[http://assert2.rubyforge.org/](http://assert2.rubyforge.org/)
|
12
|
+
|
13
|
+
## Usage ##
|
14
|
+
|
15
|
+
Wrong provides a simple assert method:
|
16
|
+
|
17
|
+
require "wrong"
|
18
|
+
|
19
|
+
include Wrong::Assert
|
20
|
+
|
21
|
+
assert{1==1}
|
22
|
+
==> nil
|
23
|
+
|
24
|
+
assert{2==1}
|
25
|
+
==> Wrong::Assert::AssertionFailedError: 2 is not equal to 1
|
26
|
+
|
27
|
+
And a companion, 'deny':
|
28
|
+
|
29
|
+
deny{'abc'.include?('bc')}
|
30
|
+
==> Wrong::Assert::AssertionFailedError: 'abc' includes 'bc'
|
31
|
+
|
32
|
+
There's a convenience method for catching errors:
|
33
|
+
|
34
|
+
assert{ catch_raise{raise "boom!"}.message == "boom!" }
|
35
|
+
==> nil
|
36
|
+
|
37
|
+
## Adapters ##
|
38
|
+
|
39
|
+
Adapters for various test frameworks sit under wrong/adapters.
|
40
|
+
TODO
|
41
|
+
|
42
|
+
## Message ##
|
43
|
+
|
44
|
+
Enhancements for error messages sit under wrong/message.
|
45
|
+
TODO
|
46
|
+
|
47
|
+
## Etc ##
|
48
|
+
|
49
|
+
Tracker project:
|
50
|
+
[http://www.pivotaltracker.com/projects/95014](http://www.pivotaltracker.com/projects/95014)
|
51
|
+
|
52
|
+
“I think it's wrong that only one company makes the game Monopoly.” -Steven Wright
|
53
|
+
|
54
|
+
"And it really doesn't matter if I'm wrong
|
55
|
+
I'm right where I belong"
|
56
|
+
-Fixing a Hole
|
data/lib/wrong.rb
ADDED
data/lib/wrong/assert.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "predicated/predicate"
|
2
|
+
require "predicated/from/callable_object"
|
3
|
+
require "predicated/to/sentence"
|
4
|
+
|
5
|
+
#see http://yehudakatz.com/2009/01/18/other-ways-to-wrap-a-method/
|
6
|
+
class Module
|
7
|
+
def overridable(&blk)
|
8
|
+
mod = Module.new(&blk)
|
9
|
+
include mod
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Wrong
|
14
|
+
module Assert
|
15
|
+
|
16
|
+
class AssertionFailedError < RuntimeError; end
|
17
|
+
|
18
|
+
def failure_class
|
19
|
+
AssertionFailedError
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert(&block)
|
23
|
+
unless block.call
|
24
|
+
raise failure_class.new(
|
25
|
+
failure_message(:assert, block, Predicated::Predicate.from_callable_object(block))
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def deny(&block)
|
32
|
+
if block.call
|
33
|
+
raise failure_class.new(
|
34
|
+
failure_message(:deny, block, Predicated::Predicate.from_callable_object(block))
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def catch_raise
|
40
|
+
error = nil
|
41
|
+
begin
|
42
|
+
yield
|
43
|
+
rescue Exception, RuntimeError => e
|
44
|
+
error = e
|
45
|
+
end
|
46
|
+
e
|
47
|
+
end
|
48
|
+
|
49
|
+
overridable do
|
50
|
+
def failure_message(method_sym, block, predicate)
|
51
|
+
method_sym == :deny ? predicate.to_sentence : predicate.to_negative_sentence
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.disable_existing_assert_methods(the_class)
|
56
|
+
(the_class.public_instance_methods.
|
57
|
+
select{|m|m =~ /^assert/} - ["assert"]).each do |old_assert_method|
|
58
|
+
the_class.class_eval(%{
|
59
|
+
def #{old_assert_method}(*args)
|
60
|
+
raise "#{old_assert_method} has been disabled. When you use Wrong, it overrides 'assert', which most test frameworks have defined, and use internally."
|
61
|
+
end
|
62
|
+
})
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "diff/lcs"
|
2
|
+
|
3
|
+
module Wrong
|
4
|
+
module Assert
|
5
|
+
|
6
|
+
def failure_message(method_sym, block, predicate)
|
7
|
+
message = super
|
8
|
+
|
9
|
+
if predicate.is_a?(Predicated::Equal) &&
|
10
|
+
predicate.left.is_a?(Enumerable) &&
|
11
|
+
predicate.right.is_a?(Enumerable)
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
diffs = Diff::LCS.sdiff(predicate.left, predicate.right)
|
16
|
+
# left_offset = 0
|
17
|
+
left_arr = []
|
18
|
+
right_arr = []
|
19
|
+
diff_arr = []
|
20
|
+
|
21
|
+
diffs.each do |diff|
|
22
|
+
left_elem = diff.old_element.nil? ? "nil" : diff.old_element.inspect
|
23
|
+
right_elem = diff.new_element.nil? ? "nil" : diff.new_element.inspect
|
24
|
+
|
25
|
+
max_length = [left_elem.length, right_elem.length].max
|
26
|
+
left_arr << left_elem.ljust(max_length) unless diff.action == "+"
|
27
|
+
right_arr << right_elem.ljust(max_length) unless diff.action == "-"
|
28
|
+
diff_arr << (diff.action == "=" ? " ".ljust(max_length) : "^".ljust(max_length))
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
left_str, right_str, diff_str = ArrayDiff.compute_and_format(predicate.left, predicate.right)
|
33
|
+
|
34
|
+
message << "\n\narray diff:\n"
|
35
|
+
message << left_str + "\n"
|
36
|
+
message << right_str + "\n"
|
37
|
+
message << diff_str + "\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
message
|
41
|
+
end
|
42
|
+
|
43
|
+
module ArrayDiff
|
44
|
+
def self.compute_and_format(left, right)
|
45
|
+
diffs = Diff::LCS.sdiff(left, right)
|
46
|
+
|
47
|
+
left_arr = []
|
48
|
+
right_arr = []
|
49
|
+
diff_arr = []
|
50
|
+
|
51
|
+
diffs.each do |diff|
|
52
|
+
left_elem = diff.old_element.nil? ? "nil" : diff.old_element.inspect
|
53
|
+
right_elem = diff.new_element.nil? ? "nil" : diff.new_element.inspect
|
54
|
+
|
55
|
+
max_length = [left_elem.length, right_elem.length].max
|
56
|
+
left_arr << left_elem.ljust(max_length) unless diff.action == "+"
|
57
|
+
right_arr << right_elem.ljust(max_length) unless diff.action == "-"
|
58
|
+
diff_arr << (diff.action == "=" ? " ".ljust(max_length) : "^".ljust(max_length))
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
[format(left_arr),
|
63
|
+
format(right_arr),
|
64
|
+
" " + diff_arr.join(" ") + " "]
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.format(thing)
|
68
|
+
str = ""
|
69
|
+
if thing.is_a?(Array)
|
70
|
+
str << "["
|
71
|
+
thing.each_with_index do |item, i|
|
72
|
+
str << format(item)
|
73
|
+
str << ", " unless i == thing.length-1
|
74
|
+
end
|
75
|
+
str << "]"
|
76
|
+
else
|
77
|
+
str << thing
|
78
|
+
end
|
79
|
+
str
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "diff"
|
2
|
+
|
3
|
+
module Wrong
|
4
|
+
module Assert
|
5
|
+
|
6
|
+
def failure_message(method_sym, block, predicate)
|
7
|
+
message = super
|
8
|
+
|
9
|
+
if predicate.is_a?(Predicated::Equal) &&
|
10
|
+
predicate.left.is_a?(String) &&
|
11
|
+
predicate.right.is_a?(String)
|
12
|
+
|
13
|
+
problems = predicate.left.diff(predicate.right)
|
14
|
+
max_length = [predicate.left.length, predicate.right.length].max
|
15
|
+
|
16
|
+
message << "\n\nstring diff:\n"
|
17
|
+
message << StringDiff.string_with_diff(predicate.left, problems, max_length, "-")
|
18
|
+
message << StringDiff.string_with_diff(predicate.right, problems, max_length, "+")
|
19
|
+
end
|
20
|
+
|
21
|
+
message
|
22
|
+
end
|
23
|
+
|
24
|
+
module StringDiff
|
25
|
+
def self.string_with_diff(original_str, problems, max_length, sign)
|
26
|
+
str = ""
|
27
|
+
str << original_str.gsub("\n", "\\n").gsub("\t", "\\t").gsub("\r", "\\r") + "\n"
|
28
|
+
str << StringDiff.problems_to_carrot_string(problems, max_length, sign) + "\n"
|
29
|
+
str
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.problems_to_carrot_string(problems, length, sign)
|
33
|
+
carrot_string = " " * length
|
34
|
+
problems.diffs.first.each do |add_subtract, position, character_code|
|
35
|
+
carrot_string[position] = "^" if sign == add_subtract
|
36
|
+
end
|
37
|
+
carrot_string
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Wrong
|
2
|
+
module Assert
|
3
|
+
|
4
|
+
def failure_message(method_sym, block, predicate)
|
5
|
+
upper_portion = super
|
6
|
+
|
7
|
+
first_test_line = caller.find{|line|line =~ /(_test.rb|_spec.rb)/}
|
8
|
+
file, failure_line_number = first_test_line.split(":",2)
|
9
|
+
|
10
|
+
lines = File.readlines(file)
|
11
|
+
line_number = failure_line_number.to_i - 1
|
12
|
+
to_show = []
|
13
|
+
begin
|
14
|
+
line = lines[line_number]
|
15
|
+
to_show.unshift(line)
|
16
|
+
line_number -= 1
|
17
|
+
end while !(line =~ /^\s+(test|it)[ ]+/ || line =~ /^\s+def test_\w+/)
|
18
|
+
|
19
|
+
to_show[to_show.length-1] = to_show[to_show.length-1].chomp +
|
20
|
+
" ASSERTION FAILURE #{file}:#{failure_line_number.to_i}\n"
|
21
|
+
|
22
|
+
upper_portion + "\n\n" + to_show.join
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
require "minitest/spec"
|
4
|
+
require "minitest/unit"
|
5
|
+
|
6
|
+
require "wrong/assert"
|
7
|
+
require "wrong/adapters/minitest"
|
8
|
+
|
9
|
+
apropos "basic assert features" do
|
10
|
+
|
11
|
+
apropos "pass/fail basics" do
|
12
|
+
test "disables other assert methods" do
|
13
|
+
test_case_instance = Class.new(MiniTest::Unit::TestCase).new("x")
|
14
|
+
assert{ catch_raise{test_case_instance.assert_equal(1,1)}.
|
15
|
+
message.include?("has been disabled") }
|
16
|
+
end
|
17
|
+
|
18
|
+
test "raises minitest assertion failures" do
|
19
|
+
test_case_instance = Class.new(MiniTest::Unit::TestCase).new("x")
|
20
|
+
assert{ catch_raise{test_case_instance.assert{1==2}}.is_a?(MiniTest::Assertion)}
|
21
|
+
end
|
22
|
+
|
23
|
+
test "assert and deny are available to minitest tests" do
|
24
|
+
class MyFailingAssertTest < MiniTest::Unit::TestCase
|
25
|
+
def initialize
|
26
|
+
super("assert test")
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_fail
|
30
|
+
assert{1==2}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class MyFailingDenyTest < MiniTest::Unit::TestCase
|
35
|
+
def initialize
|
36
|
+
super("deny test")
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_fail
|
40
|
+
deny{1==1}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
msg = catch_raise{MyFailingAssertTest.new.test_fail}.message
|
45
|
+
assert{ "1 is not equal to 2" == msg }
|
46
|
+
|
47
|
+
msg = catch_raise{MyFailingDenyTest.new.test_fail}.message
|
48
|
+
assert{ "1 is equal to 1" == msg }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
|
5
|
+
require "wrong/assert"
|
6
|
+
require "wrong/adapters/test_unit"
|
7
|
+
|
8
|
+
class MyFailingAssertTest < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_strip_out_other_assert_methods
|
11
|
+
#because they call into assert and we're redfining that method so it's potentially confusing
|
12
|
+
|
13
|
+
begin
|
14
|
+
Class.new(Test::Unit::TestCase).assert_equal(1, 1)
|
15
|
+
rescue StandardError => e
|
16
|
+
e.message.include?("has been disabled")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def test_assert_and_deny_are_available_to_test_unit_tests
|
22
|
+
my_failing_assert_test = Class.new(Test::Unit::TestCase)
|
23
|
+
my_failing_assert_test.class_eval do
|
24
|
+
def test_fail
|
25
|
+
assert{1==2}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
my_failing_deny_test = Class.new(Test::Unit::TestCase)
|
30
|
+
my_failing_deny_test.class_eval do
|
31
|
+
def test_fail
|
32
|
+
deny{1==1}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
result = Test::Unit::TestResult.new
|
37
|
+
my_failing_assert_test.new("test_fail").run(result) {|started, name| }
|
38
|
+
#I can do without all the TU Listener business, thank you
|
39
|
+
failures = result.instance_variable_get("@failures".to_sym)
|
40
|
+
assert{ failures.length==1 }
|
41
|
+
assert{ failures.first.long_display.include?("1 is not equal to 2") }
|
42
|
+
|
43
|
+
result = Test::Unit::TestResult.new
|
44
|
+
failures = result.instance_variable_get("@failures".to_sym)
|
45
|
+
my_failing_deny_test.new("test_fail").run(result) {|started, name| }
|
46
|
+
assert{ failures.length==1 }
|
47
|
+
assert{ failures.first.long_display.include?("1 is equal to 1") }
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
require "wrong/assert"
|
4
|
+
|
5
|
+
apropos "basic assert features" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@m = Module.new do
|
9
|
+
extend Wrong::Assert
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
apropos "pass/fail basics" do
|
14
|
+
test "passes when the result is true. deny does the reverse" do
|
15
|
+
@m.assert{true}
|
16
|
+
@m.assert{1==1}
|
17
|
+
|
18
|
+
@m.deny{false}
|
19
|
+
@m.deny{1==2}
|
20
|
+
end
|
21
|
+
|
22
|
+
test "fails when result is false. deny does the reverse" do
|
23
|
+
get_error{@m.assert{false}} || fail
|
24
|
+
get_error{@m.assert{1==2}} || fail
|
25
|
+
|
26
|
+
get_error{@m.deny{true}} || fail
|
27
|
+
get_error{@m.deny{1==1}} || fail
|
28
|
+
end
|
29
|
+
|
30
|
+
class MyError < StandardError; end
|
31
|
+
|
32
|
+
test "both deny and assert fail when an error is thrown. bubbles up the error." do
|
33
|
+
assert_raises(MyError) { @m.assert{ raise MyError.new } }
|
34
|
+
assert_raises(MyError) { @m.deny{ raise MyError.new } }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
require "wrong/assert"
|
4
|
+
require "wrong/adapters/minitest"
|
5
|
+
|
6
|
+
apropos "a tool for rescuing errors" do
|
7
|
+
|
8
|
+
class RedError < StandardError; end
|
9
|
+
class BlueError < StandardError; end
|
10
|
+
|
11
|
+
test "catch the error and assert on it" do
|
12
|
+
assert{ catch_raise{raise RedError.new}.is_a?(RedError) }
|
13
|
+
assert{ catch_raise{"x"}.nil? }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
require "wrong/assert"
|
4
|
+
|
5
|
+
apropos "failures" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@m = Module.new do
|
9
|
+
extend Wrong::Assert
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
apropos "simple" do
|
14
|
+
test "raw boolean failure" do
|
15
|
+
assert_match "false", get_error{@m.assert{false}}.message
|
16
|
+
assert_match "true", get_error{@m.deny{true}}.message
|
17
|
+
end
|
18
|
+
|
19
|
+
test "equality failure" do
|
20
|
+
assert_match "1 is not equal to 2", get_error{@m.assert{1==2}}.message
|
21
|
+
assert_match "1 is equal to 1", get_error{@m.deny{1==1}}.message
|
22
|
+
end
|
23
|
+
|
24
|
+
test "failure of basic operations" do
|
25
|
+
assert_match "1 is not greater than 2", get_error{@m.assert{1>2}}.message
|
26
|
+
assert_match "2 is not less than 1", get_error{@m.assert{2<1}}.message
|
27
|
+
assert_match "1 is not greater than or equal to 2", get_error{@m.assert{1>=2}}.message
|
28
|
+
assert_match "2 is not less than or equal to 1", get_error{@m.assert{2<=1}}.message
|
29
|
+
|
30
|
+
assert_match "2 is greater than 1", get_error{@m.deny{2>1}}.message
|
31
|
+
assert_match "1 is less than 2", get_error{@m.deny{1<2}}.message
|
32
|
+
assert_match "2 is greater than or equal to 1", get_error{@m.deny{2>=1}}.message
|
33
|
+
assert_match "1 is less than or equal to 2", get_error{@m.deny{1<=2}}.message
|
34
|
+
end
|
35
|
+
|
36
|
+
class Color
|
37
|
+
attr_reader :name
|
38
|
+
def initialize(name)
|
39
|
+
@name = name
|
40
|
+
end
|
41
|
+
|
42
|
+
def ==(other)
|
43
|
+
other.is_a?(Color) && @name == other.name
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"Color:#{@name}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test "object failure" do
|
52
|
+
assert_match "'Color:red' is not equal to 2", get_error{@m.assert{Color.new("red")==2}}.message
|
53
|
+
end
|
54
|
+
|
55
|
+
test %{multiline assert block shouldn't look any different
|
56
|
+
than when there everything is on one line} do
|
57
|
+
assert_match("1 is not equal to 2", get_error{@m.assert{
|
58
|
+
1==
|
59
|
+
2
|
60
|
+
}}.message)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
apropos "accessing and printing values set outside of the assert" do
|
66
|
+
test "use a value in the assert defined outside of it" do
|
67
|
+
a = 1
|
68
|
+
assert_match "1 is not equal to 2", get_error{@m.assert{a==2}}.message
|
69
|
+
assert_match "1 is equal to 1", get_error{@m.deny{a==1}}.message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
apropos "the assert block has many statements" do
|
74
|
+
test "only pay attention to the final statement" do
|
75
|
+
assert_match("1 is not equal to 2", get_error{@m.assert{
|
76
|
+
a = "aaa"
|
77
|
+
b = 1 + 2
|
78
|
+
c = ["foo", "bar"].length / 3
|
79
|
+
if a=="aaa"
|
80
|
+
b = 4
|
81
|
+
end; 1==2
|
82
|
+
}}.message)
|
83
|
+
end
|
84
|
+
|
85
|
+
test "works even if the assertion is based on stuff set previously in the block" do
|
86
|
+
assert_match("'aaa' is not equal to 'bbb'", get_error{@m.assert{
|
87
|
+
a = "aaa"
|
88
|
+
a=="bbb"
|
89
|
+
}}.message)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
apropos "array comparisons" do
|
94
|
+
test "basic" do
|
95
|
+
assert_match %{'[1, 2]' is not equal to '["a", "b"]'}, get_error{@m.assert{[1,2]==%w{a b}}}.message
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
apropos "hash comparisons" do
|
100
|
+
test "basic" do
|
101
|
+
assert_match %{'{1=>2}' is not equal to '{"a"=>"b"}'},
|
102
|
+
get_error{@m.assert{{1=>2}=={"a"=>"b"}}}.message
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
apropos "methods that result in a boolean. this might be hard." do
|
107
|
+
test "string include" do
|
108
|
+
assert_match "'abc' does not include 'cd'", get_error{@m.assert{"abc".include?("cd")}}.message
|
109
|
+
assert_match "'abc' includes 'bc'", get_error{@m.deny{"abc".include?("bc")}}.message
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
require "wrong/assert"
|
3
|
+
require "wrong/message/array_diff"
|
4
|
+
require "wrong/adapters/minitest"
|
5
|
+
|
6
|
+
apropos "when you're comparing strings and they don't match, show me the diff message" do
|
7
|
+
|
8
|
+
def assert_string_diff_message(block, str)
|
9
|
+
assert{catch_raise{assert(&block)}.message.include?(str)}
|
10
|
+
end
|
11
|
+
|
12
|
+
test "don't attempt to do this if the assertion is not of the form a_array==b_array" do
|
13
|
+
deny{catch_raise{assert{[1]==2}}.message.include?("diff")}
|
14
|
+
deny{catch_raise{assert{nil==[1]}}.message.include?("diff")}
|
15
|
+
end
|
16
|
+
|
17
|
+
test "simple" do
|
18
|
+
assert{catch_raise{assert{["a"]==["b"]}}.message.include?("diff")}
|
19
|
+
|
20
|
+
assert_string_diff_message(proc{["a", "b"]==["a", "c", "c"]}, %{
|
21
|
+
["a", "b"]
|
22
|
+
["a", "c", "c"]
|
23
|
+
^ ^
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
test "elements align properly" do
|
28
|
+
assert_string_diff_message(proc{["a", "b", "c"]==["a", "cccc", "c"]}, %{
|
29
|
+
["a", "b" , "c"]
|
30
|
+
["a", "cccc", "c"]
|
31
|
+
^
|
32
|
+
})
|
33
|
+
|
34
|
+
assert_string_diff_message(proc{["a", "b", "c", "d"]==["a", "cccc", "xxx", "d"]}, %{
|
35
|
+
["a", "b" , "c" , "d"]
|
36
|
+
["a", "cccc", "xxx", "d"]
|
37
|
+
^ ^
|
38
|
+
})
|
39
|
+
end
|
40
|
+
|
41
|
+
test "different primitive types" do
|
42
|
+
assert_string_diff_message(proc{[1, true]==[2, true, nil]}, %{
|
43
|
+
[1, true]
|
44
|
+
[2, true, nil]
|
45
|
+
^ ^
|
46
|
+
})
|
47
|
+
end
|
48
|
+
|
49
|
+
test "2d array - just inspects the inner array like it would any other element" do
|
50
|
+
assert{[1, [2, 3]]==[1, [2, 3]]}
|
51
|
+
assert_string_diff_message(proc{[1, [2]]==[1, [2, 3]]}, %{
|
52
|
+
[1, [2] ]
|
53
|
+
[1, [2, 3]]
|
54
|
+
^
|
55
|
+
})
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
require "wrong/assert"
|
3
|
+
require "wrong/message/string_diff"
|
4
|
+
require "wrong/adapters/minitest"
|
5
|
+
|
6
|
+
apropos "when you're comparing strings and they don't match, show me the diff message" do
|
7
|
+
|
8
|
+
def assert_string_diff_message(block, str)
|
9
|
+
assert{catch_raise{assert(&block)}.message.include?(str)}
|
10
|
+
end
|
11
|
+
|
12
|
+
test "don't attempt to do this if the assertion is not of the form a_string==b_string" do
|
13
|
+
deny{catch_raise{assert{1==2}}.message.include?("diff")}
|
14
|
+
deny{catch_raise{assert{"a"==2}}.message.include?("diff")}
|
15
|
+
deny{catch_raise{assert{1=="a"}}.message.include?("diff")}
|
16
|
+
deny{catch_raise{assert{nil=="a"}}.message.include?("diff")}
|
17
|
+
end
|
18
|
+
|
19
|
+
test "simple" do
|
20
|
+
assert{catch_raise{assert{"a"=="b"}}.message.include?("diff")}
|
21
|
+
|
22
|
+
assert_string_diff_message(proc{"ab"=="acc"}, %{
|
23
|
+
ab
|
24
|
+
^
|
25
|
+
acc
|
26
|
+
^^
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
test "whitespace" do
|
31
|
+
assert_string_diff_message(proc{"a\nb"=="a\ncc"}, %{
|
32
|
+
a\\nb
|
33
|
+
^
|
34
|
+
a\\ncc
|
35
|
+
^^
|
36
|
+
})
|
37
|
+
|
38
|
+
assert_string_diff_message(proc{"a\tb"=="a\tcc"}, %{
|
39
|
+
a\\tb
|
40
|
+
^
|
41
|
+
a\\tcc
|
42
|
+
^^
|
43
|
+
})
|
44
|
+
assert_string_diff_message(proc{"a\rb"=="a\rcc"}, %{
|
45
|
+
a\\rb
|
46
|
+
^
|
47
|
+
a\\rcc
|
48
|
+
^^
|
49
|
+
})
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
xtest "elides really long matching sections" do
|
54
|
+
left = "x"*100 + "ab" + "y"*100 + "AB" + "z"*100
|
55
|
+
right = "x"*100 + "acc" + "y"*100 + "ACC" + "z"*100
|
56
|
+
|
57
|
+
assert_string_diff_message(proc{"ab"=="acc"}, %{
|
58
|
+
...xxabyyy....yyABzzz....
|
59
|
+
^ ^
|
60
|
+
...xxaccyyy...yyACCzzz...
|
61
|
+
^^ ^^
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
require "wrong/assert"
|
3
|
+
require "wrong/message/test_context"
|
4
|
+
|
5
|
+
apropos "test failures" do
|
6
|
+
|
7
|
+
include Wrong::Assert
|
8
|
+
|
9
|
+
test "you can see test method all the way back to the start of the test, plus an indication of where the failure was" do
|
10
|
+
a = 1
|
11
|
+
b = 2
|
12
|
+
c = 1
|
13
|
+
assert{ a == c }
|
14
|
+
begin
|
15
|
+
assert{ a == b }
|
16
|
+
rescue Wrong::Assert::AssertionFailedError => e
|
17
|
+
assert do
|
18
|
+
e.message.include?(
|
19
|
+
%{ test "you can see test method all the way back to the start of the test, plus an indication of where the failure was" do
|
20
|
+
a = 1
|
21
|
+
b = 2
|
22
|
+
c = 1
|
23
|
+
assert{ a == c }
|
24
|
+
begin
|
25
|
+
assert{ a == b } ASSERTION FAILURE test/include_test_context_test.rb:15}
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
deny {e.message.include?("works with it too")}
|
30
|
+
deny {e.message.include?("test_works_with_test_undercore")}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "works with it too" do
|
35
|
+
begin
|
36
|
+
assert{ 1 == 2 }
|
37
|
+
rescue Wrong::Assert::AssertionFailedError => e
|
38
|
+
assert do
|
39
|
+
e.message.include?(
|
40
|
+
%{ it "works with it too" do
|
41
|
+
begin
|
42
|
+
assert{ 1 == 2 } ASSERTION FAILURE test/include_test_context_test.rb:36}
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
deny {e.message.include?("you can see test method")}
|
47
|
+
deny {e.message.include?("test_works_with_test_undercore")}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_works_with_test_undercore_too
|
52
|
+
begin
|
53
|
+
assert{ 1 == 2 }
|
54
|
+
rescue Wrong::Assert::AssertionFailedError => e
|
55
|
+
assert do
|
56
|
+
e.message.include?(
|
57
|
+
%{ def test_works_with_test_undercore_too
|
58
|
+
begin
|
59
|
+
assert{ 1 == 2 } ASSERTION FAILURE test/include_test_context_test.rb:53}
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
deny {e.message.include?("you can see test method")}
|
64
|
+
deny {e.message.include?("works with it too")}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/test/suite.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
$LOAD_PATH.unshift "#{dir}/../lib"
|
3
|
+
$LOAD_PATH.unshift "../predicated/lib"
|
4
|
+
require "rubygems"
|
5
|
+
require "minitest/spec"
|
6
|
+
require "minitest/unit"
|
7
|
+
require "pp"
|
8
|
+
|
9
|
+
def get_error
|
10
|
+
error = nil
|
11
|
+
begin
|
12
|
+
yield
|
13
|
+
rescue Exception, RuntimeError => e
|
14
|
+
error = e
|
15
|
+
end
|
16
|
+
e
|
17
|
+
end
|
18
|
+
|
19
|
+
class MiniTest::Unit::TestCase
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module Kernel
|
24
|
+
alias_method :apropos, :describe
|
25
|
+
|
26
|
+
def xapropos(str)
|
27
|
+
puts "x'd out 'apropos \"#{str}\"'"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class MiniTest::Spec
|
32
|
+
include MiniTest::Assertions
|
33
|
+
|
34
|
+
class << self
|
35
|
+
alias_method :test, :it
|
36
|
+
|
37
|
+
def xtest(str)
|
38
|
+
puts "x'd out 'test \"#{str}\"'"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
MiniTest::Unit.autorun
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wrong
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Steve Conover
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-06 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: predicated
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 27
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 1
|
33
|
+
- 0
|
34
|
+
version: 0.1.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: ParseTree
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 13
|
46
|
+
segments:
|
47
|
+
- 3
|
48
|
+
- 0
|
49
|
+
- 5
|
50
|
+
version: 3.0.5
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: ruby_parser
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 7
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 0
|
65
|
+
- 4
|
66
|
+
version: 2.0.4
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: ruby2ruby
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 23
|
78
|
+
segments:
|
79
|
+
- 1
|
80
|
+
- 2
|
81
|
+
- 4
|
82
|
+
version: 1.2.4
|
83
|
+
type: :runtime
|
84
|
+
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: diff
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 31
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 3
|
97
|
+
- 6
|
98
|
+
version: 0.3.6
|
99
|
+
type: :runtime
|
100
|
+
version_requirements: *id005
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: diff-lcs
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 23
|
110
|
+
segments:
|
111
|
+
- 1
|
112
|
+
- 1
|
113
|
+
- 2
|
114
|
+
version: 1.1.2
|
115
|
+
type: :runtime
|
116
|
+
version_requirements: *id006
|
117
|
+
description: Wrong provides a general assert method that takes a predicate block. Assertion failure messages are rich in detail.
|
118
|
+
email: sconover@gmail.com
|
119
|
+
executables: []
|
120
|
+
|
121
|
+
extensions: []
|
122
|
+
|
123
|
+
extra_rdoc_files:
|
124
|
+
- README.markdown
|
125
|
+
files:
|
126
|
+
- lib/wrong/adapters/minitest.rb
|
127
|
+
- lib/wrong/adapters/test_unit.rb
|
128
|
+
- lib/wrong/assert.rb
|
129
|
+
- lib/wrong/message/array_diff.rb
|
130
|
+
- lib/wrong/message/string_diff.rb
|
131
|
+
- lib/wrong/message/test_context.rb
|
132
|
+
- lib/wrong/version.rb
|
133
|
+
- lib/wrong.rb
|
134
|
+
- README.markdown
|
135
|
+
- test/adapters/minitest_test.rb
|
136
|
+
- test/adapters/test_unit_test.rb
|
137
|
+
- test/basic_assert_test.rb
|
138
|
+
- test/catch_raise_test.rb
|
139
|
+
- test/failures_test.rb
|
140
|
+
- test/message/array_diff_test.rb
|
141
|
+
- test/message/string_diff_test.rb
|
142
|
+
- test/message/test_context_text.rb
|
143
|
+
- test/suite.rb
|
144
|
+
- test/test_helper.rb
|
145
|
+
has_rdoc: true
|
146
|
+
homepage: http://github.com/sconover/wrong
|
147
|
+
licenses: []
|
148
|
+
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
hash: 3
|
160
|
+
segments:
|
161
|
+
- 0
|
162
|
+
version: "0"
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
hash: 3
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
version: "0"
|
172
|
+
requirements: []
|
173
|
+
|
174
|
+
rubyforge_project: wrong
|
175
|
+
rubygems_version: 1.3.7
|
176
|
+
signing_key:
|
177
|
+
specification_version: 3
|
178
|
+
summary: Wrong provides a general assert method that takes a predicate block. Assertion failure messages are rich in detail.
|
179
|
+
test_files:
|
180
|
+
- test/adapters/minitest_test.rb
|
181
|
+
- test/adapters/test_unit_test.rb
|
182
|
+
- test/basic_assert_test.rb
|
183
|
+
- test/catch_raise_test.rb
|
184
|
+
- test/failures_test.rb
|
185
|
+
- test/message/array_diff_test.rb
|
186
|
+
- test/message/string_diff_test.rb
|
187
|
+
- test/message/test_context_text.rb
|
188
|
+
- test/suite.rb
|
189
|
+
- test/test_helper.rb
|