minitest_lucid 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +21 -0
- data/README.md +574 -0
- data/Rakefile +36 -0
- data/lib/lorem.rb +37 -0
- data/lib/minitest_lucid.rb +245 -0
- data/lib/minitest_lucid/version.rb +3 -0
- data/markdown/readme/README.md +102 -0
- data/markdown/readme/array/assert_equal/better.txt +31 -0
- data/markdown/readme/array/assert_equal/data.rb +48 -0
- data/markdown/readme/array/assert_equal/default.txt +5 -0
- data/markdown/readme/array/assert_equal/example.rb +35 -0
- data/markdown/readme/array/assert_equal/lucid.txt +31 -0
- data/markdown/readme/array/assert_equal/template.md +17 -0
- data/markdown/readme/array/template.md +3 -0
- data/markdown/readme/hash/assert_equal/better.txt +31 -0
- data/markdown/readme/hash/assert_equal/data.rb +46 -0
- data/markdown/readme/hash/assert_equal/default.txt +5 -0
- data/markdown/readme/hash/assert_equal/example.rb +35 -0
- data/markdown/readme/hash/assert_equal/lucid.txt +57 -0
- data/markdown/readme/hash/assert_equal/template.md +17 -0
- data/markdown/readme/hash/template.md +3 -0
- data/markdown/readme/set/assert_equal/better.txt +34 -0
- data/markdown/readme/set/assert_equal/data.rb +44 -0
- data/markdown/readme/set/assert_equal/default.txt +5 -0
- data/markdown/readme/set/assert_equal/example.rb +36 -0
- data/markdown/readme/set/assert_equal/lucid.txt +43 -0
- data/markdown/readme/set/assert_equal/template.md +17 -0
- data/markdown/readme/set/template.md +3 -0
- data/markdown/readme/struct/assert_equal/better.txt +42 -0
- data/markdown/readme/struct/assert_equal/data.rb +85 -0
- data/markdown/readme/struct/assert_equal/default.txt +5 -0
- data/markdown/readme/struct/assert_equal/example.rb +35 -0
- data/markdown/readme/struct/assert_equal/lucid.txt +81 -0
- data/markdown/readme/struct/assert_equal/template.md +17 -0
- data/markdown/readme/struct/template.md +3 -0
- data/markdown/readme/template.md +19 -0
- data/minitest_lucid.gemspec +39 -0
- metadata +169 -0
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << 'test'
|
6
|
+
t.libs << 'lib'
|
7
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :build do
|
11
|
+
|
12
|
+
desc 'Build README pages'
|
13
|
+
task :readme do
|
14
|
+
project_dir_path = File.dirname(__FILE__ )
|
15
|
+
readme_dir_path = File.join(
|
16
|
+
project_dir_path,
|
17
|
+
'markdown',
|
18
|
+
'readme',
|
19
|
+
)
|
20
|
+
Dir.chdir(readme_dir_path) do
|
21
|
+
ruby_file_paths = Dir.glob('./**/*.rb')
|
22
|
+
ruby_file_paths.each do |ruby_file_path|
|
23
|
+
Dir.chdir(File.dirname(ruby_file_path)) do
|
24
|
+
ruby_file_name = File.basename(ruby_file_path)
|
25
|
+
command = "ruby #{ruby_file_name}"
|
26
|
+
system(command)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
command = "markdown_helper include --pristine template.md ../../README.md"
|
30
|
+
system(command)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :test
|
data/lib/lorem.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'lorem-ipsum'
|
2
|
+
|
3
|
+
include LoremIpsum
|
4
|
+
|
5
|
+
spec = Gem::Specification.find_by_name('lorem-ipsum')
|
6
|
+
gem_root = spec.gem_dir
|
7
|
+
lorem_file_path = File.join(gem_root, 'data', 'lorem.txt')
|
8
|
+
lorem = Generator.new
|
9
|
+
lorem.analyze(lorem_file_path)
|
10
|
+
|
11
|
+
# puts '['
|
12
|
+
# (0...24).each do
|
13
|
+
# value = lorem.next_sentence(4).strip
|
14
|
+
# puts "'#{value}',"
|
15
|
+
# end
|
16
|
+
# puts ']'
|
17
|
+
|
18
|
+
# puts '{'
|
19
|
+
# (0..24).each do
|
20
|
+
# key = lorem.next_sentence(1).strip.gsub('.', '').downcase
|
21
|
+
# value = lorem.next_sentence(4).strip
|
22
|
+
# puts ":#{key} => '#{value}',"
|
23
|
+
# end
|
24
|
+
# puts '}'
|
25
|
+
|
26
|
+
hash = {}
|
27
|
+
(0..24).each do
|
28
|
+
key = lorem.next_sentence(1).strip.gsub('.', '').downcase
|
29
|
+
value = lorem.next_sentence(4).strip
|
30
|
+
hash.store(key, value)
|
31
|
+
end
|
32
|
+
hash.keys.each do |key|
|
33
|
+
puts ":#{key},"
|
34
|
+
end
|
35
|
+
hash.values.each do |value|
|
36
|
+
puts "'#{value}',"
|
37
|
+
end
|
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
require 'diff/lcs'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Minitest
|
6
|
+
|
7
|
+
module Assertions
|
8
|
+
|
9
|
+
alias :old_assert_equal :assert_equal
|
10
|
+
|
11
|
+
def assert_equal(expected, actual, msg=nil)
|
12
|
+
begin
|
13
|
+
old_assert_equal(expected, actual, msg)
|
14
|
+
rescue Minitest::Assertion => x
|
15
|
+
elucidate(x, expected, actual, msg)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
METHOD_FOR_CLASS = {
|
20
|
+
Hash => :elucidate_hash,
|
21
|
+
Set => :elucidate_set,
|
22
|
+
Struct => :elucidate_struct,
|
23
|
+
# Array => :elucidate_array,
|
24
|
+
}
|
25
|
+
ELUCIDATABLE_CLASSES = METHOD_FOR_CLASS.keys
|
26
|
+
|
27
|
+
# Lookup objects in hash.
|
28
|
+
def lookup(one_object, other_object)
|
29
|
+
if ELUCIDATABLE_CLASSES.include?(one_object.class)
|
30
|
+
if other_object.kind_of?(one_object.class)
|
31
|
+
return METHOD_FOR_CLASS.fetch(one_object.class)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
# Poll with kind_of?.
|
38
|
+
def poll(expected, actual)
|
39
|
+
METHOD_FOR_CLASS.each_pair do |klass, method|
|
40
|
+
next unless expected.kind_of?(klass)
|
41
|
+
next unless actual.kind_of?(klass)
|
42
|
+
return method
|
43
|
+
end
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def elucidate(exception, expected, actual, msg)
|
48
|
+
elucidation_method =
|
49
|
+
lookup(expected, actual) ||
|
50
|
+
lookup(actual, expected) ||
|
51
|
+
poll(expected, actual)
|
52
|
+
if elucidation_method
|
53
|
+
lines = ['']
|
54
|
+
lines.push('{')
|
55
|
+
lines.push(" :message => '#{msg}',") if msg
|
56
|
+
send(elucidation_method, exception, expected, actual, lines)
|
57
|
+
lines.push('}')
|
58
|
+
lines.push('')
|
59
|
+
message = lines.join("\n")
|
60
|
+
new_exception = exception.exception(message)
|
61
|
+
new_exception.set_backtrace(exception.backtrace)
|
62
|
+
raise new_exception
|
63
|
+
else
|
64
|
+
raise
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def elucidate_array(exception, expected, actual, lines)
|
69
|
+
sdiff = Diff::LCS.sdiff(expected, actual)
|
70
|
+
changes = {}
|
71
|
+
statuses = {
|
72
|
+
'!' => 'changed',
|
73
|
+
'+' => 'unexpected',
|
74
|
+
'-' => 'missing',
|
75
|
+
'=' => 'unchanged'
|
76
|
+
}
|
77
|
+
sdiff.each_with_index do |change, i|
|
78
|
+
status = statuses.fetch(change.action)
|
79
|
+
key = "change_#{i}"
|
80
|
+
change_data = {
|
81
|
+
:status => status,
|
82
|
+
:"old_index_#{change.old_position}" => change.old_element.inspect,
|
83
|
+
:"new_index_#{change.new_position}" => change.new_element.inspect,
|
84
|
+
}
|
85
|
+
changes.store(key, change_data)
|
86
|
+
end
|
87
|
+
lines.push('elucidation = [')
|
88
|
+
changes.each_pair do |category, change_data|
|
89
|
+
status = change_data.delete(:status)
|
90
|
+
if status == 'unexpected'
|
91
|
+
change_data.delete_if {|key, value| key.match(/old/) }
|
92
|
+
end
|
93
|
+
if status == 'missing'
|
94
|
+
change_data.delete_if {|key, value| key.match(/new/) }
|
95
|
+
end
|
96
|
+
lines.push(' {')
|
97
|
+
lines.push(" :status => :#{status},")
|
98
|
+
change_data.each_pair do |k, v|
|
99
|
+
lines.push(" :#{k} => #{v},")
|
100
|
+
end
|
101
|
+
lines.push(' },')
|
102
|
+
end
|
103
|
+
lines.push(']')
|
104
|
+
end
|
105
|
+
|
106
|
+
def elucidate_hash(exception, expected, actual, lines)
|
107
|
+
expected_keys = expected.keys
|
108
|
+
actual_keys = actual.keys
|
109
|
+
keys = Set.new(expected_keys + actual_keys)
|
110
|
+
h = {
|
111
|
+
:missing_pairs => {},
|
112
|
+
:unexpected_pairs => {},
|
113
|
+
:changed_values => {},
|
114
|
+
:ok_pairs => {},
|
115
|
+
}
|
116
|
+
keys.each do |key|
|
117
|
+
expected_value = expected[key]
|
118
|
+
actual_value = actual[key]
|
119
|
+
case
|
120
|
+
when expected_value && actual_value
|
121
|
+
if expected_value == actual_value
|
122
|
+
h[:ok_pairs].store(key, expected_value)
|
123
|
+
else
|
124
|
+
h[:changed_values].store(key, [expected_value, actual_value])
|
125
|
+
end
|
126
|
+
when expected_value
|
127
|
+
h[:missing_pairs].store(key, expected_value)
|
128
|
+
when actual_value
|
129
|
+
h[:unexpected_pairs].store(key, actual_value)
|
130
|
+
else
|
131
|
+
fail [expected_value, actual_value].inspect
|
132
|
+
end
|
133
|
+
end
|
134
|
+
lines.push(' :expected => {')
|
135
|
+
lines.push(" :class => #{expected.class},")
|
136
|
+
lines.push(" :size => #{expected.size},")
|
137
|
+
lines.push(' },')
|
138
|
+
lines.push(' :actual => {')
|
139
|
+
lines.push(" :class => #{actual.class},")
|
140
|
+
lines.push(" :size => #{actual.size},")
|
141
|
+
lines.push(' },')
|
142
|
+
lines.push(' :elucidation => {')
|
143
|
+
h.each_pair do |category, items|
|
144
|
+
lines.push(" #{pretty(category)} => {")
|
145
|
+
items.each_pair do |key, value|
|
146
|
+
if value.instance_of?(Array)
|
147
|
+
expected, actual = *value
|
148
|
+
lines.push(" #{pretty(key)} => {")
|
149
|
+
lines.push(" :expected => #{pretty(expected)},")
|
150
|
+
lines.push(" :got => #{pretty(actual)},")
|
151
|
+
lines.push(' },')
|
152
|
+
else
|
153
|
+
lines.push(" #{pretty(key)} => #{pretty(value)},")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
lines.push(' },')
|
157
|
+
end
|
158
|
+
lines.push(' }')
|
159
|
+
end
|
160
|
+
|
161
|
+
def elucidate_set(exception, expected, actual, lines)
|
162
|
+
result = {
|
163
|
+
:missing => expected.difference(actual),
|
164
|
+
:unexpected => actual.difference(expected),
|
165
|
+
:ok => expected.intersection(actual),
|
166
|
+
}
|
167
|
+
lines.push(' :expected => {')
|
168
|
+
lines.push(" :class => #{expected.class},")
|
169
|
+
lines.push(" :size => #{expected.size},")
|
170
|
+
lines.push(' },')
|
171
|
+
lines.push(' :actual => {')
|
172
|
+
lines.push(" :class => #{actual.class},")
|
173
|
+
lines.push(" :size => #{actual.size},")
|
174
|
+
lines.push(' },')
|
175
|
+
lines.push(' :elucidation => {')
|
176
|
+
result.each_pair do |category, items|
|
177
|
+
lines.push(" #{pretty(category)} => {")
|
178
|
+
items.each do |member|
|
179
|
+
lines.push(" #{pretty(member)},")
|
180
|
+
end
|
181
|
+
lines.push(' },')
|
182
|
+
end
|
183
|
+
lines.push(' }')
|
184
|
+
end
|
185
|
+
|
186
|
+
def elucidate_struct(exception, expected, actual, lines)
|
187
|
+
expected_members = expected.members
|
188
|
+
actual_members = actual.members
|
189
|
+
members = Set.new(expected_members + actual_members)
|
190
|
+
h = {
|
191
|
+
:changed_values => {},
|
192
|
+
:ok_values => {},
|
193
|
+
}
|
194
|
+
members.each do |member|
|
195
|
+
expected_value = expected[member]
|
196
|
+
actual_value = actual[member]
|
197
|
+
if expected_value == actual_value
|
198
|
+
h[:ok_values].store(member, expected_value)
|
199
|
+
else
|
200
|
+
h[:changed_values].store(member, [expected_value, actual_value])
|
201
|
+
end
|
202
|
+
end
|
203
|
+
lines.push(' :expected => {')
|
204
|
+
lines.push(" :class => #{expected.class},")
|
205
|
+
lines.push(" :size => #{expected.size},")
|
206
|
+
lines.push(' },')
|
207
|
+
lines.push(' :actual => {')
|
208
|
+
lines.push(" :class => #{actual.class},")
|
209
|
+
lines.push(" :size => #{actual.size},")
|
210
|
+
lines.push(' },')
|
211
|
+
lines.push(' :elucidation => {')
|
212
|
+
h.each_pair do |category, items|
|
213
|
+
lines.push(" #{pretty(category)} => {")
|
214
|
+
items.each_pair do |member, value|
|
215
|
+
if value.instance_of?(Array)
|
216
|
+
expected, actual = *value
|
217
|
+
lines.push(" #{pretty(member)} => {")
|
218
|
+
lines.push(" :expected => #{pretty(expected)},")
|
219
|
+
lines.push(" :got => #{pretty(actual)},")
|
220
|
+
lines.push(' },')
|
221
|
+
else
|
222
|
+
lines.push(" #{pretty(member)} => #{pretty(value)},")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
lines.push(' },')
|
226
|
+
end
|
227
|
+
lines.push(' }')
|
228
|
+
end
|
229
|
+
|
230
|
+
def pretty(arg)
|
231
|
+
case
|
232
|
+
when arg.kind_of?(Symbol)
|
233
|
+
":#{arg}"
|
234
|
+
when arg.kind_of?(String)
|
235
|
+
"'#{arg}'"
|
236
|
+
when arg.kind_of?(Numeric)
|
237
|
+
arg
|
238
|
+
else
|
239
|
+
arg.inspect
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Minitest Lucid
|
2
|
+
|
3
|
+
Use ```minitest_lucid``` to improve error messages from ```minitest```.
|
4
|
+
|
5
|
+
|
6
|
+
## Supported Classes
|
7
|
+
|
8
|
+
- [Hash](#hash)
|
9
|
+
|
10
|
+
### Hash
|
11
|
+
|
12
|
+
#### assert_equal
|
13
|
+
|
14
|
+
Here are the hashes, expected and actual, that we'll use for comparison:
|
15
|
+
|
16
|
+
```data.rb```:
|
17
|
+
```ruby
|
18
|
+
def expected
|
19
|
+
{
|
20
|
+
:tauro => 'Cia ina do ip ocat doat.',
|
21
|
+
:loquens => 'Dua sarat rad noad maat caea.',
|
22
|
+
:lor => 'Eser in dolo eaata labor ut.',
|
23
|
+
:dolo => 'Ipaat paal doat iruat ala magabor.',
|
24
|
+
:offab => 'Ut dolore ua consal vaba caea.',
|
25
|
+
:moam => 'Sunt sed te coma teu alaaame.',
|
26
|
+
}
|
27
|
+
end
|
28
|
+
def actual
|
29
|
+
{
|
30
|
+
:laboru => 'Laboab vaga dat maaua in venima.',
|
31
|
+
:dolo => 'Ipaat paal doat iruat ala magabor.',
|
32
|
+
:loquens => 'dua sarat rad noad maat caea.',
|
33
|
+
:lor => 'Eser in dolo eaata labor ut.',
|
34
|
+
:tauro => 'cia ina do ip ocat doat.',
|
35
|
+
:amcae => 'Utatu cilaa cit siat commag seqa.',
|
36
|
+
}
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
The default message:
|
41
|
+
|
42
|
+
```default.txt```:
|
43
|
+
```
|
44
|
+
--- expected
|
45
|
+
+++ actual
|
46
|
+
@@ -1 +1 @@
|
47
|
+
-{:tauro=>"Cia ina do ip ocat doat.", :loquens=>"Dua sarat rad noad maat caea.", :lor=>"Eser in dolo eaata labor ut.", :dolo=>"Ipaat paal doat iruat ala magabor.", :offab=>"Ut dolore ua consal vaba caea.", :moam=>"Sunt sed te coma teu alaaame."}
|
48
|
+
+{:laboru=>"Laboab vaga dat maaua in venima.", :dolo=>"Ipaat paal doat iruat ala magabor.", :loquens=>"dua sarat rad noad maat caea.", :lor=>"Eser in dolo eaata labor ut.", :tauro=>"cia ina do ip ocat doat.", :amcae=>"Utatu cilaa cit siat commag seqa."}
|
49
|
+
```
|
50
|
+
|
51
|
+
Message using ```make_my_diffs_pretty!```:
|
52
|
+
|
53
|
+
```better.txt```:
|
54
|
+
```
|
55
|
+
--- expected
|
56
|
+
+++ actual
|
57
|
+
@@ -1,6 +1,6 @@
|
58
|
+
-{:tauro=>"Cia ina do ip ocat doat.",
|
59
|
+
- :loquens=>"Dua sarat rad noad maat caea.",
|
60
|
+
- :lor=>"Eser in dolo eaata labor ut.",
|
61
|
+
+{:laboru=>"Laboab vaga dat maaua in venima.",
|
62
|
+
:dolo=>"Ipaat paal doat iruat ala magabor.",
|
63
|
+
- :offab=>"Ut dolore ua consal vaba caea.",
|
64
|
+
- :moam=>"Sunt sed te coma teu alaaame."}
|
65
|
+
+ :loquens=>"dua sarat rad noad maat caea.",
|
66
|
+
+ :lor=>"Eser in dolo eaata labor ut.",
|
67
|
+
+ :tauro=>"cia ina do ip ocat doat.",
|
68
|
+
+ :amcae=>"Utatu cilaa cit siat commag seqa."}
|
69
|
+
```
|
70
|
+
|
71
|
+
Message using ```minitest_lucid```
|
72
|
+
|
73
|
+
```lucid.txt```:
|
74
|
+
```
|
75
|
+
|
76
|
+
elucidation = {
|
77
|
+
:missing_pairs => {
|
78
|
+
:offab => 'Ut dolore ua consal vaba caea.',
|
79
|
+
:moam => 'Sunt sed te coma teu alaaame.',
|
80
|
+
},
|
81
|
+
:unexpected_pairs => {
|
82
|
+
:laboru => 'Laboab vaga dat maaua in venima.',
|
83
|
+
:amcae => 'Utatu cilaa cit siat commag seqa.',
|
84
|
+
},
|
85
|
+
:changed_values => {
|
86
|
+
:tauro => {
|
87
|
+
:expected => 'Cia ina do ip ocat doat.',
|
88
|
+
:got => 'cia ina do ip ocat doat.',
|
89
|
+
},
|
90
|
+
:loquens => {
|
91
|
+
:expected => 'Dua sarat rad noad maat caea.',
|
92
|
+
:got => 'dua sarat rad noad maat caea.',
|
93
|
+
},
|
94
|
+
},
|
95
|
+
:ok_pairs => {
|
96
|
+
:lor => 'Eser in dolo eaata labor ut.',
|
97
|
+
:dolo => 'Ipaat paal doat iruat ala magabor.',
|
98
|
+
},
|
99
|
+
}
|
100
|
+
```
|
101
|
+
|
102
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
--- expected
|
2
|
+
+++ actual
|
3
|
+
@@ -1,19 +1,19 @@
|
4
|
+
-["Si alit vagna nonse.",
|
5
|
+
- "Serci nosa deaaboat iama.",
|
6
|
+
- "Pa ipsab occata seqa.",
|
7
|
+
- "Oaba dunt sicid eur.",
|
8
|
+
- "Esam est tat sumaan.",
|
9
|
+
+["Esam est tat sumaan.",
|
10
|
+
"Ad do ea labat.",
|
11
|
+
"Cupis doluaan adat duat.",
|
12
|
+
"Dolla aua am maab.",
|
13
|
+
- "In na idat nonsa.",
|
14
|
+
- "Eniat noaeaa in venia.",
|
15
|
+
- "Non utat rad et.",
|
16
|
+
- "Volu siamc moloab cupi.",
|
17
|
+
+ "Si alit vagna nonse.",
|
18
|
+
+ "Serci nosa deaaboat iama.",
|
19
|
+
+ "Fugame cupis do iramaa.",
|
20
|
+
+ "Eiusmagat do labore utatur.",
|
21
|
+
"Lababor rat vent essa.",
|
22
|
+
"Modola cula ocaadia amea.",
|
23
|
+
"Ania est exeaat sicid.",
|
24
|
+
"Adipsu miate eiuat naam.",
|
25
|
+
+ "In na idat nonsa.",
|
26
|
+
+ "Eniat noaeaa in venia.",
|
27
|
+
+ "Non utat rad et.",
|
28
|
+
+ "Volu siamc moloab cupi.",
|
29
|
+
"Dolor eaae doat volu.",
|
30
|
+
"Adiatur anaaa qui eius.",
|
31
|
+
"Ad laam utet seri.",
|