wrong 0.1.0 → 0.2.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 +114 -25
- data/lib/predicated/Gemfile +15 -0
- data/lib/predicated/LICENSE +20 -0
- data/lib/predicated/README.markdown +191 -0
- data/lib/predicated/Rakefile +51 -0
- data/lib/predicated/lib/predicated.rb +4 -0
- data/lib/predicated/lib/predicated/autogen_call.rb +37 -0
- data/lib/predicated/lib/predicated/constrain.rb +66 -0
- data/lib/predicated/lib/predicated/evaluate.rb +94 -0
- data/lib/predicated/lib/predicated/from/callable_object.rb +108 -0
- data/lib/predicated/lib/predicated/from/json.rb +59 -0
- data/lib/predicated/lib/predicated/from/ruby_code_string.rb +73 -0
- data/lib/predicated/lib/predicated/from/url_part.rb +104 -0
- data/lib/predicated/lib/predicated/from/xml.rb +61 -0
- data/lib/predicated/lib/predicated/gem_check.rb +34 -0
- data/lib/predicated/lib/predicated/predicate.rb +111 -0
- data/lib/predicated/lib/predicated/print.rb +62 -0
- data/lib/predicated/lib/predicated/selectable.rb +102 -0
- data/lib/predicated/lib/predicated/simple_templated_predicate.rb +79 -0
- data/lib/predicated/lib/predicated/string_utils.rb +20 -0
- data/lib/predicated/lib/predicated/to/arel.rb +41 -0
- data/lib/predicated/lib/predicated/to/json.rb +48 -0
- data/lib/predicated/lib/predicated/to/sentence.rb +94 -0
- data/lib/predicated/lib/predicated/to/solr.rb +15 -0
- data/lib/predicated/lib/predicated/to/xml.rb +67 -0
- data/lib/predicated/lib/predicated/version.rb +3 -0
- data/lib/predicated/predicated.gemspec +22 -0
- data/lib/predicated/test/autogen_call_test.rb +40 -0
- data/lib/predicated/test/canonical_transform_cases.rb +63 -0
- data/lib/predicated/test/constrain_test.rb +86 -0
- data/lib/predicated/test/enumerable_test.rb +32 -0
- data/lib/predicated/test/equality_test.rb +32 -0
- data/lib/predicated/test/evaluate_test.rb +149 -0
- data/lib/predicated/test/from/callable_object_canonical_test.rb +43 -0
- data/lib/predicated/test/from/callable_object_test.rb +78 -0
- data/lib/predicated/test/from/json_test.rb +83 -0
- data/lib/predicated/test/from/ruby_code_string_canonical_test.rb +37 -0
- data/lib/predicated/test/from/ruby_code_string_test.rb +103 -0
- data/lib/predicated/test/from/url_part_parser_test.rb +123 -0
- data/lib/predicated/test/from/url_part_test.rb +48 -0
- data/lib/predicated/test/from/xml_test.rb +57 -0
- data/lib/predicated/test/json_conversion_test.rb +33 -0
- data/lib/predicated/test/print_test.rb +66 -0
- data/lib/predicated/test/selectable_test.rb +123 -0
- data/lib/predicated/test/simple_templated_predicate_test.rb +39 -0
- data/lib/predicated/test/suite.rb +2 -0
- data/lib/predicated/test/test_helper.rb +64 -0
- data/lib/predicated/test/test_helper_with_wrong.rb +6 -0
- data/lib/predicated/test/to/arel_test.rb +85 -0
- data/lib/predicated/test/to/json_test.rb +74 -0
- data/lib/predicated/test/to/sentence_test.rb +90 -0
- data/lib/predicated/test/to/solr_test.rb +39 -0
- data/lib/predicated/test/to/xml_test.rb +72 -0
- data/lib/predicated/test/xml_conversion_test.rb +34 -0
- data/lib/predicated/test_integration/arel_integration_test.rb +52 -0
- data/lib/predicated/test_integration/canonical_integration_cases.rb +66 -0
- data/lib/predicated/test_integration/schema.xml +83 -0
- data/lib/predicated/test_integration/solr_integration_test.rb +71 -0
- data/lib/predicated/test_integration/sqlite_db +0 -0
- data/lib/predicated/test_integration/suite.rb +2 -0
- data/lib/predicated/test_integration/usage_test.rb +252 -0
- data/lib/wrong.rb +3 -1
- data/lib/wrong/adapters/test_unit.rb +1 -3
- data/lib/wrong/assert.rb +81 -24
- data/lib/wrong/chunk.rb +145 -0
- data/lib/wrong/message/string_diff.rb +2 -4
- data/lib/wrong/message/test_context.rb +2 -2
- data/lib/wrong/version.rb +2 -2
- data/test/adapters/minitest_test.rb +16 -9
- data/test/adapters/test_unit_test.rb +1 -1
- data/test/assert_test.rb +90 -0
- data/test/catch_raise_test.rb +2 -2
- data/test/chunk_test.rb +236 -0
- data/test/failures_test.rb +109 -74
- data/test/message/array_diff_test.rb +35 -19
- data/test/message/string_diff_test.rb +39 -15
- data/test/message/test_context_text.rb +2 -2
- data/test/test_helper.rb +25 -7
- metadata +86 -33
- data/test/basic_assert_test.rb +0 -38
data/test/catch_raise_test.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require "test/test_helper"
|
1
|
+
require "./test/test_helper"
|
2
2
|
|
3
3
|
require "wrong/assert"
|
4
4
|
require "wrong/adapters/minitest"
|
5
5
|
|
6
|
-
|
6
|
+
regarding "a tool for rescuing errors" do
|
7
7
|
|
8
8
|
class RedError < StandardError; end
|
9
9
|
class BlueError < StandardError; end
|
data/test/chunk_test.rb
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
require "wrong/chunk"
|
3
|
+
|
4
|
+
unless Object.const_defined?(:Chunk)
|
5
|
+
Chunk = Wrong::Chunk
|
6
|
+
end
|
7
|
+
|
8
|
+
regarding Chunk do
|
9
|
+
regarding "#from_block" do
|
10
|
+
test "reads the source location" do
|
11
|
+
file, line = __FILE__, __LINE__
|
12
|
+
chunk = Chunk.from_block(proc { "hi" })
|
13
|
+
assert(chunk.file == file)
|
14
|
+
assert(chunk.line_number == line+1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
regarding "line numbers" do
|
19
|
+
before do
|
20
|
+
@chunk = Wrong::Chunk.new("foo.rb", 10)
|
21
|
+
end
|
22
|
+
test "#line_index is zero-based" do
|
23
|
+
assert(@chunk.line_index == 9)
|
24
|
+
end
|
25
|
+
test "#location is one-based" do
|
26
|
+
assert(@chunk.location == "foo.rb:10")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
regarding "#parse" do
|
31
|
+
test "reads a statement on a line by itself" do
|
32
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
33
|
+
"hi"
|
34
|
+
CODE
|
35
|
+
code = chunk.parse.to_ruby
|
36
|
+
assert(code == '"hi"')
|
37
|
+
end
|
38
|
+
|
39
|
+
test "reads a statement on multiple lines" do
|
40
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
41
|
+
proc do
|
42
|
+
"hi"
|
43
|
+
end
|
44
|
+
CODE
|
45
|
+
code = chunk.parse.to_ruby
|
46
|
+
assert(code == "proc { \"hi\" }")
|
47
|
+
end
|
48
|
+
|
49
|
+
test "fails if there's a stray close-paren symbol on the last line (sorry)" do
|
50
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
51
|
+
"hi" )
|
52
|
+
CODE
|
53
|
+
assert(chunk.parse.nil?)
|
54
|
+
end
|
55
|
+
|
56
|
+
test "fails if there's a stray close-block symbol on the last line (sorry)" do
|
57
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
58
|
+
"hi" }
|
59
|
+
CODE
|
60
|
+
assert(chunk.parse.nil?)
|
61
|
+
end
|
62
|
+
|
63
|
+
test "fails if it can't parse the code" do
|
64
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
65
|
+
}
|
66
|
+
CODE
|
67
|
+
assert(chunk.parse.nil?)
|
68
|
+
end
|
69
|
+
|
70
|
+
test "fails if it can't find the file" do
|
71
|
+
chunk = Chunk.new("nonexistent_file.rb", 0)
|
72
|
+
error = get_error { chunk.parse }
|
73
|
+
assert error.is_a? Errno::ENOENT
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
regarding "#claim" do
|
79
|
+
test "returns the part of the assertion statement inside the curly braces" do
|
80
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
81
|
+
assert { x == 5 }
|
82
|
+
CODE
|
83
|
+
full_code = chunk.parse.to_ruby
|
84
|
+
assert(full_code == "assert { (x == 5) }")
|
85
|
+
claim_code = chunk.claim.to_ruby
|
86
|
+
assert claim_code == "(x == 5)"
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
test "reads an assert statement on a line by itself" do
|
91
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
92
|
+
assert { x == 5 }
|
93
|
+
CODE
|
94
|
+
claim_code = chunk.claim.to_ruby
|
95
|
+
assert claim_code == "(x == 5)"
|
96
|
+
end
|
97
|
+
|
98
|
+
test "reads an assert statement on multiple lines" do
|
99
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
100
|
+
assert do
|
101
|
+
x == 5
|
102
|
+
end
|
103
|
+
CODE
|
104
|
+
claim_code = chunk.claim.to_ruby
|
105
|
+
assert claim_code == "(x == 5)"
|
106
|
+
end
|
107
|
+
|
108
|
+
def yielding
|
109
|
+
yield
|
110
|
+
end
|
111
|
+
|
112
|
+
if RUBY_VERSION > "1.9"
|
113
|
+
test "reads an assert statement that's nested inside another yield block on the same line (Ruby 1.9 only)" do
|
114
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
115
|
+
yielding { assert { x == 5 }}
|
116
|
+
CODE
|
117
|
+
code = chunk.claim.to_ruby
|
118
|
+
assert code == "(x == 5)"
|
119
|
+
end
|
120
|
+
|
121
|
+
# test "goes crazy if you try to nest two asserts on the same line"
|
122
|
+
end
|
123
|
+
|
124
|
+
test "if it can't find an assertion, it uses the whole chunk" do
|
125
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
126
|
+
yielding { x == 5 }
|
127
|
+
CODE
|
128
|
+
code = chunk.claim.to_ruby
|
129
|
+
assert code == "yielding { (x == 5) }"
|
130
|
+
end
|
131
|
+
|
132
|
+
test "fails if it can't parse the code" do
|
133
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
134
|
+
}
|
135
|
+
CODE
|
136
|
+
error = get_error {
|
137
|
+
chunk.claim
|
138
|
+
}
|
139
|
+
assert error.message.include?("Could not parse")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
regarding "#parts" do
|
144
|
+
test "returns all unique sub-expressions of the main sexpression" do
|
145
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
146
|
+
assert { (x == 5) && (y == (z + 10)) }
|
147
|
+
CODE
|
148
|
+
code_parts = chunk.parts
|
149
|
+
assert code_parts == <<-PARTS.split("\n")
|
150
|
+
((x == 5) and (y == (z + 10)))
|
151
|
+
(x == 5)
|
152
|
+
x
|
153
|
+
5
|
154
|
+
(y == (z + 10))
|
155
|
+
y
|
156
|
+
(z + 10)
|
157
|
+
z
|
158
|
+
10
|
159
|
+
PARTS
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
regarding Sexp do
|
165
|
+
regarding "#doop" do
|
166
|
+
test "deeply duplicates the sexp" do
|
167
|
+
original = RubyParser.new.parse("x == 5")
|
168
|
+
duplicate = original.doop
|
169
|
+
assert(original.object_id != duplicate.object_id)
|
170
|
+
assert(original[1].object_id != duplicate[1].object_id)
|
171
|
+
assert(original[1][3].object_id != duplicate[1][3].object_id)
|
172
|
+
assert(original[3].object_id != duplicate[3].object_id)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
regarding "#to_ruby" do
|
177
|
+
test "converts the sexp to ruby code" do
|
178
|
+
sexp = RubyParser.new.parse("x == 5")
|
179
|
+
assert sexp.to_ruby == "(x == 5)"
|
180
|
+
end
|
181
|
+
|
182
|
+
test "leaves the original sexp alone" do
|
183
|
+
sexp = RubyParser.new.parse("x == 5")
|
184
|
+
assert sexp.to_ruby == "(x == 5)"
|
185
|
+
assert sexp.to_ruby == "(x == 5)"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
regarding "#assertion? with a question mark" do
|
190
|
+
test "matches an sexp that looks like assert { }" do
|
191
|
+
sexp = RubyParser.new.parse("assert { true }")
|
192
|
+
assert sexp.assertion?
|
193
|
+
end
|
194
|
+
|
195
|
+
test "matches an sexp that looks like assert(message) { }" do
|
196
|
+
sexp = RubyParser.new.parse("assert('hi') { true }")
|
197
|
+
assert sexp.assertion?
|
198
|
+
end
|
199
|
+
|
200
|
+
test "matches an sexp that looks like deny { }" do
|
201
|
+
sexp = RubyParser.new.parse("deny { false }")
|
202
|
+
assert sexp.assertion?
|
203
|
+
end
|
204
|
+
|
205
|
+
test "doesn't match an sexp that calls assert without a block" do
|
206
|
+
sexp = RubyParser.new.parse("assert(true)")
|
207
|
+
assert !sexp.assertion?
|
208
|
+
end
|
209
|
+
|
210
|
+
test "doesn't match a normal sexp" do
|
211
|
+
sexp = RubyParser.new.parse("x == 5")
|
212
|
+
assert !sexp.assertion?
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
regarding "#assertion" do
|
217
|
+
test "matches a top-level sexp that looks like assert { }" do
|
218
|
+
sexp = RubyParser.new.parse("assert { true }")
|
219
|
+
code = sexp.assertion.to_ruby
|
220
|
+
assert code == "assert { true }"
|
221
|
+
end
|
222
|
+
|
223
|
+
test "matches a nested sexp that looks like assert { }" do
|
224
|
+
sexp = RubyParser.new.parse("nesting { assert { true } }")
|
225
|
+
code = sexp.assertion.to_ruby
|
226
|
+
assert code == "assert { true }"
|
227
|
+
end
|
228
|
+
|
229
|
+
test "matches the first nested sexp that looks like assert { }" do
|
230
|
+
sexp = RubyParser.new.parse("nesting { assert { true } or assert { false } }")
|
231
|
+
code = sexp.assertion.to_ruby
|
232
|
+
assert code == "assert { true }"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
data/test/failures_test.rb
CHANGED
@@ -1,113 +1,148 @@
|
|
1
|
-
require "test/test_helper"
|
1
|
+
require "./test/test_helper"
|
2
2
|
|
3
3
|
require "wrong/assert"
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
regarding "failures" do
|
6
|
+
|
7
7
|
before do
|
8
8
|
@m = Module.new do
|
9
9
|
extend Wrong::Assert
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
|
13
|
+
regarding "simple" do
|
14
|
+
|
15
|
+
test "raw boolean assert failure" do
|
16
|
+
error = get_error { @m.assert { false } }
|
17
|
+
# puts error.message
|
18
|
+
assert_match "false", error.message
|
19
|
+
end
|
20
|
+
|
21
|
+
test "raw boolean deny failure" do
|
22
|
+
error = get_error {
|
23
|
+
@m.deny { true }
|
24
|
+
}
|
25
|
+
# puts error.message
|
26
|
+
assert_match "true", error.message
|
17
27
|
end
|
18
|
-
|
28
|
+
|
19
29
|
test "equality failure" do
|
20
|
-
assert_match "1 is not equal to 2", get_error{
|
21
|
-
|
30
|
+
assert_match "1 is not equal to 2", get_error {
|
31
|
+
@m.assert { 1==2 }
|
32
|
+
}.message
|
33
|
+
assert_match "1 is equal to 1", get_error {
|
34
|
+
@m.deny { 1==1 }
|
35
|
+
}.message
|
22
36
|
end
|
23
|
-
|
37
|
+
|
24
38
|
test "failure of basic operations" do
|
25
|
-
assert_match "1 is not greater than 2", get_error{
|
26
|
-
|
27
|
-
|
28
|
-
assert_match "2 is not less than
|
29
|
-
|
30
|
-
|
31
|
-
assert_match "1 is
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
assert_match "1 is not greater than 2", get_error {
|
40
|
+
@m.assert { 1>2 }
|
41
|
+
}.message
|
42
|
+
assert_match "2 is not less than 1", get_error {
|
43
|
+
@m.assert { 2<1 }
|
44
|
+
}.message
|
45
|
+
assert_match "1 is not greater than or equal to 2", get_error {
|
46
|
+
@m.assert { 1>=2 }
|
47
|
+
}.message
|
48
|
+
assert_match "2 is not less than or equal to 1", get_error {
|
49
|
+
@m.assert { 2<=1 }
|
50
|
+
}.message
|
51
|
+
|
52
|
+
assert_match "2 is greater than 1", get_error {
|
53
|
+
@m.deny { 2>1 }
|
54
|
+
}.message
|
55
|
+
assert_match "1 is less than 2", get_error {
|
56
|
+
@m.deny { 1<2 }
|
57
|
+
}.message
|
58
|
+
assert_match "2 is greater than or equal to 1", get_error {
|
59
|
+
@m.deny { 2>=1 }
|
60
|
+
}.message
|
61
|
+
assert_match "1 is less than or equal to 2", get_error {
|
62
|
+
@m.deny { 1<=2 }
|
63
|
+
}.message
|
49
64
|
end
|
50
|
-
|
65
|
+
|
51
66
|
test "object failure" do
|
52
|
-
assert_match "
|
67
|
+
assert_match "Color:red is not equal to 2", get_error {
|
68
|
+
@m.assert { Color.new("red")==2 }
|
69
|
+
}.message
|
53
70
|
end
|
54
|
-
|
55
|
-
test %{multiline assert block shouldn't look any different
|
71
|
+
|
72
|
+
test %{multiline assert block shouldn't look any different
|
56
73
|
than when there everything is on one line} do
|
57
|
-
assert_match("1 is not equal to 2", get_error{
|
58
|
-
|
59
|
-
|
60
|
-
|
74
|
+
assert_match("1 is not equal to 2", get_error {
|
75
|
+
@m.assert {
|
76
|
+
1==
|
77
|
+
2
|
78
|
+
}
|
79
|
+
}.message)
|
61
80
|
end
|
62
81
|
|
63
82
|
end
|
64
|
-
|
65
|
-
|
83
|
+
|
84
|
+
regarding "accessing and printing values set outside of the assert" do
|
66
85
|
test "use a value in the assert defined outside of it" do
|
67
86
|
a = 1
|
68
|
-
assert_match "1 is not equal to 2", get_error{
|
69
|
-
|
87
|
+
assert_match "1 is not equal to 2", get_error {
|
88
|
+
@m.assert { a==2 }
|
89
|
+
}.message
|
90
|
+
assert_match "1 is equal to 1", get_error {
|
91
|
+
@m.deny { a==1 }
|
92
|
+
}.message
|
70
93
|
end
|
71
94
|
end
|
72
|
-
|
73
|
-
|
95
|
+
|
96
|
+
regarding "the assert block has many statements" do
|
74
97
|
test "only pay attention to the final statement" do
|
75
|
-
assert_match("1 is not equal to 2", get_error{
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
98
|
+
assert_match("1 is not equal to 2", get_error {
|
99
|
+
@m.assert {
|
100
|
+
a = "aaa"
|
101
|
+
b = 1 + 2
|
102
|
+
c = ["foo", "bar"].length / 3
|
103
|
+
if a=="aaa"
|
104
|
+
b = 4
|
105
|
+
end; 1==2
|
106
|
+
}
|
107
|
+
}.message)
|
83
108
|
end
|
84
109
|
|
85
110
|
test "works even if the assertion is based on stuff set previously in the block" do
|
86
|
-
assert_match("
|
87
|
-
|
88
|
-
|
89
|
-
|
111
|
+
assert_match("\"aaa\" is not equal to \"bbb\"", get_error {
|
112
|
+
@m.assert {
|
113
|
+
a = "aaa"
|
114
|
+
a=="bbb"
|
115
|
+
}
|
116
|
+
}.message)
|
90
117
|
end
|
91
118
|
end
|
92
|
-
|
93
|
-
|
119
|
+
|
120
|
+
regarding "array comparisons" do
|
94
121
|
test "basic" do
|
95
|
-
assert_match %{
|
122
|
+
assert_match %{[1, 2] is not equal to ["a", "b"]}, get_error {
|
123
|
+
@m.assert { [1, 2]==%w{a b} }
|
124
|
+
}.message
|
96
125
|
end
|
97
126
|
end
|
98
|
-
|
99
|
-
|
127
|
+
|
128
|
+
regarding "hash comparisons" do
|
100
129
|
test "basic" do
|
101
|
-
assert_match
|
102
|
-
|
130
|
+
assert_match '{1=>2} is not equal to {"a"=>"b"}',
|
131
|
+
get_error {
|
132
|
+
@m.assert { {1=>2}=={"a"=>"b"} }
|
133
|
+
}.message
|
103
134
|
end
|
104
135
|
end
|
105
|
-
|
106
|
-
|
136
|
+
|
137
|
+
regarding "methods that result in a boolean. this might be hard." do
|
107
138
|
test "string include" do
|
108
|
-
assert_match "
|
109
|
-
|
139
|
+
assert_match "\"abc\" does not include \"cd\"", get_error {
|
140
|
+
@m.assert { "abc".include?("cd") }
|
141
|
+
}.message
|
142
|
+
assert_match "\"abc\" includes \"bc\"", get_error {
|
143
|
+
@m.deny { "abc".include?("bc") }
|
144
|
+
}.message
|
110
145
|
end
|
111
146
|
end
|
112
147
|
|
113
|
-
end
|
148
|
+
end
|