minitest_lucid 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.
- 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.",
|