wrong 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|