minitest_lucid 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/CODE_OF_CONDUCT.md +74 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +28 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +574 -0
  8. data/Rakefile +36 -0
  9. data/lib/lorem.rb +37 -0
  10. data/lib/minitest_lucid.rb +245 -0
  11. data/lib/minitest_lucid/version.rb +3 -0
  12. data/markdown/readme/README.md +102 -0
  13. data/markdown/readme/array/assert_equal/better.txt +31 -0
  14. data/markdown/readme/array/assert_equal/data.rb +48 -0
  15. data/markdown/readme/array/assert_equal/default.txt +5 -0
  16. data/markdown/readme/array/assert_equal/example.rb +35 -0
  17. data/markdown/readme/array/assert_equal/lucid.txt +31 -0
  18. data/markdown/readme/array/assert_equal/template.md +17 -0
  19. data/markdown/readme/array/template.md +3 -0
  20. data/markdown/readme/hash/assert_equal/better.txt +31 -0
  21. data/markdown/readme/hash/assert_equal/data.rb +46 -0
  22. data/markdown/readme/hash/assert_equal/default.txt +5 -0
  23. data/markdown/readme/hash/assert_equal/example.rb +35 -0
  24. data/markdown/readme/hash/assert_equal/lucid.txt +57 -0
  25. data/markdown/readme/hash/assert_equal/template.md +17 -0
  26. data/markdown/readme/hash/template.md +3 -0
  27. data/markdown/readme/set/assert_equal/better.txt +34 -0
  28. data/markdown/readme/set/assert_equal/data.rb +44 -0
  29. data/markdown/readme/set/assert_equal/default.txt +5 -0
  30. data/markdown/readme/set/assert_equal/example.rb +36 -0
  31. data/markdown/readme/set/assert_equal/lucid.txt +43 -0
  32. data/markdown/readme/set/assert_equal/template.md +17 -0
  33. data/markdown/readme/set/template.md +3 -0
  34. data/markdown/readme/struct/assert_equal/better.txt +42 -0
  35. data/markdown/readme/struct/assert_equal/data.rb +85 -0
  36. data/markdown/readme/struct/assert_equal/default.txt +5 -0
  37. data/markdown/readme/struct/assert_equal/example.rb +35 -0
  38. data/markdown/readme/struct/assert_equal/lucid.txt +81 -0
  39. data/markdown/readme/struct/assert_equal/template.md +17 -0
  40. data/markdown/readme/struct/template.md +3 -0
  41. data/markdown/readme/template.md +19 -0
  42. data/minitest_lucid.gemspec +39 -0
  43. 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,3 @@
1
+ module MinitestLucid
2
+ VERSION = '0.1.0'
3
+ 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.",