quality_extensions 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/Readme +54 -0
  2. data/lib/qualitysmith_extensions/all.rb +4 -0
  3. data/lib/qualitysmith_extensions/array/all.rb +2 -0
  4. data/lib/qualitysmith_extensions/array/average.rb +44 -0
  5. data/lib/qualitysmith_extensions/array/classify.rb +97 -0
  6. data/lib/qualitysmith_extensions/array/expand_ranges.rb +52 -0
  7. data/lib/qualitysmith_extensions/array/group_by.rb +134 -0
  8. data/lib/qualitysmith_extensions/array/sequence.rb +66 -0
  9. data/lib/qualitysmith_extensions/array/shell_escape.rb +36 -0
  10. data/lib/qualitysmith_extensions/array/to_a_recursive.rb +41 -0
  11. data/lib/qualitysmith_extensions/array/to_query_string.rb +96 -0
  12. data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
  13. data/lib/qualitysmith_extensions/colored/toggleability.rb +62 -0
  14. data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
  15. data/lib/qualitysmith_extensions/console/command.facets.1.8.54.rb +748 -0
  16. data/lib/qualitysmith_extensions/console/command.rb +944 -0
  17. data/lib/qualitysmith_extensions/date/all.rb +2 -0
  18. data/lib/qualitysmith_extensions/date/deprecated.rb +40 -0
  19. data/lib/qualitysmith_extensions/date/iso8601.rb +31 -0
  20. data/lib/qualitysmith_extensions/date/month_ranges.rb +122 -0
  21. data/lib/qualitysmith_extensions/dir/each_child.rb +58 -0
  22. data/lib/qualitysmith_extensions/enumerable/enum.rb +69 -0
  23. data/lib/qualitysmith_extensions/enumerable/select_until.rb +4 -0
  24. data/lib/qualitysmith_extensions/enumerable/select_while.rb +109 -0
  25. data/lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb +65 -0
  26. data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +34 -0
  27. data/lib/qualitysmith_extensions/file_test/binary_file.rb +110 -0
  28. data/lib/qualitysmith_extensions/find/select.rb +68 -0
  29. data/lib/qualitysmith_extensions/global_variable_set.rb +153 -0
  30. data/lib/qualitysmith_extensions/hash/all.rb +2 -0
  31. data/lib/qualitysmith_extensions/hash/to_date.rb +34 -0
  32. data/lib/qualitysmith_extensions/hash/to_query_string.rb +121 -0
  33. data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
  34. data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
  35. data/lib/qualitysmith_extensions/kernel/backtrace.rb +71 -0
  36. data/lib/qualitysmith_extensions/kernel/capture_output.rb +115 -0
  37. data/lib/qualitysmith_extensions/kernel/die.rb +49 -0
  38. data/lib/qualitysmith_extensions/kernel/example_printer.rb +81 -0
  39. data/lib/qualitysmith_extensions/kernel/filter_output.rb +108 -0
  40. data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
  41. data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
  42. data/lib/qualitysmith_extensions/kernel/require_all.rb +186 -0
  43. data/lib/qualitysmith_extensions/kernel/require_local_all.rb +4 -0
  44. data/lib/qualitysmith_extensions/kernel/require_once.rb +18 -0
  45. data/lib/qualitysmith_extensions/kernel/simulate_input.rb +52 -0
  46. data/lib/qualitysmith_extensions/kernel/trap_chain.rb +61 -0
  47. data/lib/qualitysmith_extensions/kernel/windows_platform.rb +46 -0
  48. data/lib/qualitysmith_extensions/module/alias_method.rb +6 -0
  49. data/lib/qualitysmith_extensions/module/alias_method_chain.rb +165 -0
  50. data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
  51. data/lib/qualitysmith_extensions/module/attribute_accessors.rb +49 -0
  52. data/lib/qualitysmith_extensions/module/basename.rb +76 -0
  53. data/lib/qualitysmith_extensions/module/bool_attr_accessor.rb +497 -0
  54. data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
  55. data/lib/qualitysmith_extensions/module/create.rb +315 -0
  56. data/lib/qualitysmith_extensions/module/create_setter.rb +9 -0
  57. data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
  58. data/lib/qualitysmith_extensions/module/guard_method.rb +312 -0
  59. data/lib/qualitysmith_extensions/module/includable_once.rb +10 -0
  60. data/lib/qualitysmith_extensions/module/join.rb +66 -0
  61. data/lib/qualitysmith_extensions/module/malias_method_chain.rb +92 -0
  62. data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
  63. data/lib/qualitysmith_extensions/module/namespace.rb +112 -0
  64. data/lib/qualitysmith_extensions/module/parents.rb +61 -0
  65. data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
  66. data/lib/qualitysmith_extensions/module/split.rb +55 -0
  67. data/lib/qualitysmith_extensions/month.rb +66 -0
  68. data/lib/qualitysmith_extensions/mutex/if_available.rb +75 -0
  69. data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
  70. data/lib/qualitysmith_extensions/object/default.rb +69 -0
  71. data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
  72. data/lib/qualitysmith_extensions/object/ignore_access.rb +84 -0
  73. data/lib/qualitysmith_extensions/object/mcall.rb +92 -0
  74. data/lib/qualitysmith_extensions/object/methods.rb +63 -0
  75. data/lib/qualitysmith_extensions/object/send_if.rb +151 -0
  76. data/lib/qualitysmith_extensions/object/send_if_not_nil.rb +35 -0
  77. data/lib/qualitysmith_extensions/object/singleton_send.rb +129 -0
  78. data/lib/qualitysmith_extensions/regexp/join.rb +111 -0
  79. data/lib/qualitysmith_extensions/string/all.rb +2 -0
  80. data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
  81. data/lib/qualitysmith_extensions/string/digits_only.rb +27 -0
  82. data/lib/qualitysmith_extensions/string/each_char_with_index.rb +41 -0
  83. data/lib/qualitysmith_extensions/string/md5.rb +29 -0
  84. data/lib/qualitysmith_extensions/string/shell_escape.rb +43 -0
  85. data/lib/qualitysmith_extensions/string/to_underscored_label.rb +37 -0
  86. data/lib/qualitysmith_extensions/string/with_knowledge_of_color.rb +64 -0
  87. data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
  88. data/lib/qualitysmith_extensions/symbol/match.rb +157 -0
  89. data/lib/qualitysmith_extensions/template.rb +33 -0
  90. data/lib/qualitysmith_extensions/test/all.rb +2 -0
  91. data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
  92. data/lib/qualitysmith_extensions/test/assert_changed.rb +66 -0
  93. data/lib/qualitysmith_extensions/test/assert_exception.rb +66 -0
  94. data/lib/qualitysmith_extensions/test/assert_includes.rb +36 -0
  95. data/lib/qualitysmith_extensions/test/assert_user_error.rb +37 -0
  96. data/lib/qualitysmith_extensions/test/difference_highlighting.rb +323 -0
  97. data/lib/qualitysmith_extensions/time/all.rb +2 -0
  98. data/lib/qualitysmith_extensions/time/deprecated.rb +31 -0
  99. data/test/all.rb +16 -0
  100. metadata +148 -0
@@ -0,0 +1,33 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?::
6
+ # Developer notes::
7
+ # Changes::
8
+ #++
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+ # _____ _
19
+ # |_ _|__ ___| |_
20
+ # | |/ _ \/ __| __|
21
+ # | | __/\__ \ |_
22
+ # |_|\___||___/\__|
23
+ #
24
+ =begin test
25
+ require 'test/unit'
26
+
27
+ class TheTest < Test::Unit::TestCase
28
+ def test_1
29
+ end
30
+
31
+ end
32
+ =end
33
+
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/../kernel/require_all"
2
+ require_all File.dirname(__FILE__), :exclude_files => 'all.rb'
@@ -0,0 +1,93 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes.
6
+ # Developer notes::
7
+ # Changes::
8
+ #++
9
+
10
+
11
+ class Test::Unit::TestCase
12
+ # Lets you make an assertion out of any method, without having to write a new assert_ method for it!
13
+ #
14
+ # So as long as the +whatever+ method's return value can be interpreted as a boolean value, you can simply call
15
+ # <tt>assert_whatever a, b</tt>, which will be equivalent to calling <tt>assert a.whatever(b)</tt>
16
+ #
17
+ # Follow this basic pattern:
18
+ # assert_{method} {receiver}, {args}
19
+ # assert_not_{method} {receiver}, {args}
20
+ # assert_{method}_is {receiver}, {args}, {expected_return_value}
21
+ # assert_{method}_returns {receiver}, {args}, {expected_return_value}
22
+ #
23
+ # Examples:
24
+ # assert_include? [1, 2, 3], 2
25
+ # assert_not_include? [1, 2, 3], 4
26
+ # assert_class_is 'foo', String
27
+ #
28
+ def method_missing(name, *args)
29
+ # to do:
30
+ # options = args.pop if args.last.is_a?(Hash)
31
+ # message = options[:message]
32
+ if name.to_s =~ /^assert_(.*)/
33
+ receiver = args.shift
34
+ negated = false
35
+ message_to_pass = $1
36
+
37
+ if name.to_s =~ /^assert_(.*)_is/
38
+ message_to_pass = $1
39
+ expected = args.pop
40
+ if name.to_s =~ /^assert_(.*)_is_not/
41
+ message_to_pass = $1
42
+ negated = true
43
+ end
44
+
45
+ result = receiver.send(message_to_pass, *args)
46
+ if negated
47
+ assert_not_equal expected, result
48
+ else
49
+ assert_equal expected, result
50
+ end
51
+ else
52
+ if name.to_s =~ /^assert_not_(.*)|assert_(.*)_is_not/
53
+ message_to_pass = $1
54
+ negated = true
55
+ end
56
+
57
+ result = receiver.send(message_to_pass, *args)
58
+ result = !result if negated
59
+ assert result
60
+ end
61
+
62
+ else
63
+ super
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+
70
+
71
+ # _____ _
72
+ # |_ _|__ ___| |_
73
+ # | |/ _ \/ __| __|
74
+ # | | __/\__ \ |_
75
+ # |_|\___||___/\__|
76
+ #
77
+ =begin test
78
+ require 'test/unit'
79
+
80
+ class TheTest < Test::Unit::TestCase
81
+ def test_1
82
+ assert_include? [1, 2, 3], 2
83
+ assert_not_include? [1, 2, 3], 4
84
+ end
85
+ def test_is
86
+ assert_class_is 'foo', String
87
+ assert_class_is_not ['foo'], String
88
+ end
89
+
90
+ end
91
+ =end
92
+
93
+
@@ -0,0 +1,66 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes
6
+ #++
7
+
8
+ require 'test/unit'
9
+ class Test::Unit::TestCase
10
+
11
+ # Asserts that the block that is passed in causes the value of the specified variable (+variable+) to change.
12
+ # +variable+ should be a Proc that, when evaluated, returns the current value of the variable.
13
+ #
14
+ # Options:
15
+ # * If the optional +:from+ option is supplied, it also asserts that it had that initial value.
16
+ # * If the optional +:to+ option is supplied, it also asserts that it changed _to_ that value.
17
+ #
18
+ # So instead of doing this:
19
+ # assert_equal 1, Model.count
20
+ # do_something_that_should_cause_count_to_increase
21
+ # assert_equal 2, Model.count
22
+ # we can do this:
23
+ # assert_changed(lambda {ErrorType.count}, :from => 1, :to => 2) do
24
+ # do_something_that_should_cause_count_to_increase
25
+ # end
26
+ # Or, if we don't care what it's changing _from_ as long as it increases in value _by_ 1, we can write this:
27
+ # assert_changed(c = lambda {ErrorType.count}, :to => c.call+1) do
28
+ # do_something_that_should_cause_count_to_increase
29
+ # end
30
+ # instead of this:
31
+ # before = Model.count
32
+ # do_something_that_should_cause_count_to_increase
33
+ # assert_equal before + 1, Model.count
34
+ #
35
+ def assert_changed(variable, options = {}, &block)
36
+ expected_from = options.delete(:from) || variable.call
37
+
38
+ assert_equal expected_from, variable.call
39
+
40
+ failure_message = build_message(failure_message, "The variable was expected to change from <?> to <?> but it didn't", variable.call, options.delete(:to) || "something else")
41
+ assert_block(failure_message) do
42
+ before = variable.call
43
+ yield
44
+ expected_to = options.delete(:to) || variable.call
45
+ before != variable.call and variable.call == expected_to
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ # _____ _
52
+ # |_ _|__ ___| |_
53
+ # | |/ _ \/ __| __|
54
+ # | | __/\__ \ |_
55
+ # |_|\___||___/\__|
56
+ #
57
+ =begin test
58
+ require 'test/unit'
59
+
60
+ class TheTest < Test::Unit::TestCase
61
+ def test_1
62
+ end
63
+ end
64
+ =end
65
+
66
+
@@ -0,0 +1,66 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes
6
+ #++
7
+
8
+ require 'test/unit'
9
+ class Test::Unit::TestCase
10
+
11
+ # Used when you want to make assertions *about* an assertion that you expect to be raised. (With the built-in assert_raise()
12
+ # you can only assert *that* a particular class of exception is raised, not any specifics about it.
13
+ #
14
+ # Before:
15
+ #
16
+ # exception = nil
17
+ # assert_raises(ArgumentError) { SomeCommand.execute("foo '''") }
18
+ # begin
19
+ # SomeCommand.execute("foo -m '''")
20
+ # rescue Exception => _exception
21
+ # exception = _exception
22
+ # end
23
+ # assert_equal "Unmatched single quote: '", exception.message
24
+ #
25
+ # After:
26
+ #
27
+ # assert_exception(ArgumentError, lambda { |exception|
28
+ # assert_match /Unmatched single quote/, exception.message
29
+ # }) do
30
+ # SomeCommand.execute("foo -m 'stuff''")
31
+ # end
32
+ #
33
+ def assert_exception(expected_class, additional_expectations = nil, &block)
34
+ exception = nil
35
+ assert_raise(expected_class) do
36
+ begin
37
+ yield
38
+ rescue Exception => _exception
39
+ exception = _exception
40
+ raise
41
+ end
42
+ end
43
+ additional_expectations.call(exception) if additional_expectations
44
+ end
45
+ end
46
+
47
+ # _____ _
48
+ # |_ _|__ ___| |_
49
+ # | |/ _ \/ __| __|
50
+ # | | __/\__ \ |_
51
+ # |_|\___||___/\__|
52
+ #
53
+ =begin test
54
+ require 'test/unit'
55
+
56
+ class TheTest < Test::Unit::TestCase
57
+ def test_1
58
+ assert_exception(RuntimeError, lambda { |exception|
59
+ assert_match /est/, exception.message
60
+ }) do
61
+ raise "Test"
62
+ end
63
+ end
64
+ end
65
+ =end
66
+
@@ -0,0 +1,36 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes
6
+ #++
7
+
8
+ require 'test/unit'
9
+ class Test::Unit::TestCase
10
+ def assert_includes(container, expected_contents, failure_message = nil)
11
+ failure_message = build_message(failure_message, "Container <?> was expected to contain <?> but it didn't", container, expected_contents)
12
+ assert_block(failure_message) do
13
+ container.include?(expected_contents)
14
+ end
15
+ end
16
+ alias_method :assert_contains, :assert_includes
17
+
18
+ end
19
+
20
+ # _____ _
21
+ # |_ _|__ ___| |_
22
+ # | |/ _ \/ __| __|
23
+ # | | __/\__ \ |_
24
+ # |_|\___||___/\__|
25
+ #
26
+ =begin test
27
+ require 'test/unit'
28
+
29
+ class TheTest < Test::Unit::TestCase
30
+ def test_1
31
+ end
32
+ end
33
+ =end
34
+
35
+
36
+
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: No
6
+ # Context:: Rails
7
+ #++
8
+
9
+ require 'test/unit'
10
+ class Test::Unit::TestCase
11
+ def assert_user_error(error_message)
12
+ assert_tag({
13
+ :attributes => { :id => "errorExplanation" },
14
+ :descendant => {
15
+ :content => error_message
16
+ }
17
+ })
18
+ end
19
+ end
20
+
21
+ # _____ _
22
+ # |_ _|__ ___| |_
23
+ # | |/ _ \/ __| __|
24
+ # | | __/\__ \ |_
25
+ # |_|\___||___/\__|
26
+ #
27
+ =begin test
28
+ require 'test/unit'
29
+
30
+ class TheTest < Test::Unit::TestCase
31
+ def test_1
32
+ end
33
+ end
34
+ =end
35
+
36
+
37
+
@@ -0,0 +1,323 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?::
6
+ # Developer notes::
7
+ #++
8
+ # This file adds a bit of color to your failed string comparisons (assert_equal).
9
+ # Differences will be highlighted for you in color so that you can instantly find them.
10
+
11
+ require 'rubygems'
12
+ gem 'colored'
13
+ require 'colored'
14
+ gem 'facets'
15
+ require 'facets/core/module/alias_method_chain'
16
+ gem 'qualitysmith_extensions', '>=0.0.28'
17
+ require 'qualitysmith_extensions/object/send_if'
18
+ require 'qualitysmith_extensions/string/each_char_with_index'
19
+ require 'qualitysmith_extensions/module/bool_attr_accessor'
20
+ require 'qualitysmith_extensions/module/guard_method'
21
+ require 'qualitysmith_extensions/colored/toggleability'
22
+
23
+ require 'test/unit'
24
+
25
+ class String
26
+ # For all of the next 3 methods, we will underline spaces so that they are actually visible on the screen.
27
+ # Newlines will be replaced with '\n'"\n".
28
+
29
+ # This is a (sub)string that is common to both expected and actual
30
+ def highlight_commonality
31
+ self.
32
+ make_control_characters_visible.
33
+ make_spaces_visible(:green).
34
+ green.bold
35
+ #send_unless(self == ' ', :bold) # spaces are not bold; '_'s (and everything else) are
36
+ end
37
+ # This is a (sub)string that is different between expected and actual
38
+ def highlight_difference
39
+ self.
40
+ make_control_characters_visible.
41
+ make_spaces_visible(:red).
42
+ red.bold
43
+ #send_unless(self == ' ', :bold) # spaces are not bold; '_'s (and everything else) are
44
+ end
45
+ # This is a (sub)string that exists only in *self*, not in the other string
46
+ def highlight_unique
47
+ self.
48
+ make_control_characters_visible.
49
+ make_spaces_visible(:magenta).
50
+ magenta
51
+ end
52
+ # This is a (sub)string that doesn't exist in self, only in the *other* string. It's just a placeholder character (a space) that represents a *missing* character.
53
+ def highlight_absence
54
+ self.white.on_cyan.bold
55
+ end
56
+ def make_spaces_visible(color)
57
+ #:todo: Make this optional? Might be useful if you are comparing things with lots of spaces and underscores and you want to be able to tell the difference between them...?
58
+ self.gsub(' ', ' '.send(:"on_#{color}"))
59
+ end
60
+ def make_control_characters_visible
61
+ self.gsub(/\n/, '\n'+"\n"). # Show '\n' in addition to actually doing the line break
62
+ gsub(/\r/, '\r'). # Just escape it...
63
+ gsub(/\t/, '\t')
64
+ #:todo: Add other control characters?
65
+ end
66
+ end
67
+
68
+ module Test
69
+ module Unit
70
+ module Assertions
71
+
72
+ class AssertionMessage
73
+ @@inspect_strings = false
74
+ mguard_method :inspect_strings!, :@@inspect_strings
75
+
76
+ # The problem with the original convert() is that it always called #inspect on strings... which is fine if you really
77
+ # want to see all those \n's and such. But not so great if you want to visually compare the strings. And if you have
78
+ # ANSI color codes in the strings, it will escape those so that you see the codes (\e[33m1) rather than the nice
79
+ # colored strings that you (sometimes) *want* to see...
80
+ #
81
+ def convert_with_option_to_not_use_inspect_for_strings(object)
82
+ if String === object
83
+ if self.class.inspect_strings?
84
+ # Use the original method, which used pp or inspect
85
+ convert_without_option_to_not_use_inspect_for_strings(object)
86
+ else
87
+ object
88
+ end
89
+ else
90
+ # We only care about strings. Everything else can just keep happening like it was before.
91
+ convert_without_option_to_not_use_inspect_for_strings(object)
92
+ end
93
+ end
94
+ alias_method_chain :convert, :option_to_not_use_inspect_for_strings
95
+ end # class AssertionMessage
96
+
97
+ end
98
+ end
99
+ end
100
+
101
+ module Test
102
+ module Unit
103
+ module Assertions
104
+ @@use_assert_equal_with_highlight = nil
105
+ mguard_method :use_assert_equal_with_highlight!, :@@use_assert_equal_with_highlight
106
+
107
+ # The built-in behavior for <tt>assert_equal</tt> method is great for comparing small strings, but not so great for long strings.
108
+ # If both the strings you are dealing with are both 20 paragraphs long, for example, and they differ by only one character,
109
+ # the task of locating and identifying the one character that is off is akin to finding a (literal) needle in a
110
+ # (literal) haystack (not fun!).
111
+ #
112
+ # link:include/assert_equal_with_difference_highlighting-wheres_waldo.png
113
+ #
114
+ # This replacement/wrapper for <tt>assert_equal</tt> aims to solve all of your string comparison woes (and eventually someday
115
+ # perhaps arrays and hashes as well), helping you to spot differences very quickly and to have fun doing it.
116
+ #
117
+ # Rather than simply showing you the raw (<tt>inspect</tt>ed) +expected+ and +actual+ and expecting you, the poor user, to
118
+ # painstakingly compare the two and figure out exactly which characters are different by yourself this method will *highlight*
119
+ # the differences for you, allowing you to spot them an instant or less!!
120
+ #
121
+ # link:include/assert_equal_with_difference_highlighting-there_he_is.png
122
+ #
123
+ # *Strings*:
124
+ # * Does a characterwise comparison between the two strings. That is, for each index, it will look at the character at that
125
+ # index and decide if it is the same or different than the character at the same location in the other string. There are
126
+ # 3 1/2 cases:
127
+ # * *Common* characters are displayed in _green_,
128
+ # * *Different* characters in _red_,
129
+ # * Characters that exist <b>in only one string</b> but not the other are displayed in _yellow_
130
+ # * A _cyan_ <tt>~</tt> will appear that location in the _other_ string, as a placeholder for the <b>missing character</b>.
131
+ # *Arrays*:
132
+ # * [:todo:]
133
+ # *Hashes*:
134
+ # * [:todo:]
135
+ #
136
+ # <b>Disabling/enabling highlighting</b>:
137
+ #
138
+ # By default, highlighting is only used when one or both of the strings being compared is long or spans multiple lines. You can override the default with the <tt>:higlight</tt> option:
139
+ # assert_equal 'really long string', 'another really long string', :highlight => true
140
+ # You can turn it on for all assert_equal assertions by calling
141
+ # Test::Unit::Assertions::use_assert_equal_with_highlight!
142
+ # Or you can just turn it on or off for the duration of a block only:
143
+ # Test::Unit::Assertions::use_assert_equal_with_highlight! do
144
+ # assert_equal 'really long string', 'another really long string'
145
+ # end
146
+ #
147
+ # *Notes*:
148
+ # * Spaces are displayed as with a bright colored background so that they are actually visible on the screen (so you can distinguish an empty line from a line with spaces on it, for example).
149
+ # * Newlines are displayed as the text <tt>\n</tt> followed by the actual newline. Other control characters (<tt>\t</tt>, <tt>\r</tt>) are escaped as well so that you can tell what character it is.
150
+ #
151
+ # <b>Difference in method signature</b> from <tt>assert_equal_without_difference_highlighting</tt> (the standard behavior):
152
+ # * The last argument (+options+) is expected to be a hash rather than message=nil, since I don't see the use in passing in a message if
153
+ # the _default_ message can be made useful enough.
154
+ # * However, for compatibility with existing assert_equal calls, it will check if the 3rd argument is a string and if it is will use it as the failure message.
155
+ # * If you to pass in a message in combination with other options, use <tt>:message => 'my message'</tt>
156
+ #
157
+ # *Advanced*:
158
+ # * If you want everything to be escaped (so you can see the color _codes_ instead of the color itself, for example), use <tt>:inspect_strings => true</tt>
159
+ #
160
+ def assert_equal_with_highlighting(expected, actual, options = {})
161
+ if options.is_a?(String)
162
+ message = options
163
+ options = {}
164
+ else
165
+ message = options.delete(:message) || nil
166
+ end
167
+ highlight = options.delete(:highlight)
168
+
169
+ Assertions.send_unless(highlight.nil?, :use_assert_equal_with_highlight!, highlight) do
170
+
171
+ if String===expected and String===actual and expected!=actual and
172
+ (Assertions.use_assert_equal_with_highlight? || [expected.length, actual.length].max > 80 || [expected, actual].any? {|a| a.include?("\n")}) and
173
+ !(Assertions.use_assert_equal_with_highlight? == false)
174
+ expected_with_highlighting = ''
175
+ actual_with_highlighting = ''
176
+ full_message = nil
177
+ String.color_on! do
178
+ longest_string = [expected, actual].max {|a, b| a.length <=> b.length}
179
+ longest_string.each_char_with_index do |i, exp|
180
+ exp = expected[i] ? expected[i].chr : nil
181
+ act = actual[i] ? actual[i].chr : nil
182
+ if act.nil?
183
+ expected_with_highlighting << exp.highlight_unique
184
+ actual_with_highlighting << '~'.highlight_absence
185
+ elsif exp.nil?
186
+ expected_with_highlighting << '~'.highlight_absence
187
+ actual_with_highlighting << act.highlight_unique
188
+ elsif exp != act
189
+ expected_with_highlighting << exp.highlight_difference
190
+ actual_with_highlighting << act.highlight_difference
191
+ else
192
+ expected_with_highlighting << exp.highlight_commonality
193
+ actual_with_highlighting << exp.highlight_commonality
194
+ end
195
+
196
+ end
197
+ full_message = build_message(message, <<End, expected_with_highlighting, actual_with_highlighting)
198
+ #{(' '*50 + ' Expected: ' + ' '*50).blue.underline.on_white }
199
+ ?
200
+ #{(' '*50 + ' But was: ' + ' '*50).yellow.underline.on_red }
201
+ ?
202
+ End
203
+ end
204
+ AssertionMessage.inspect_strings!(options.delete(:inspect_strings) || false) do
205
+ assert_block(full_message) { expected == actual }
206
+ end
207
+ else
208
+ assert_equal_without_highlighting(expected, actual, message)
209
+ end
210
+
211
+ end # use_assert_equal_with_highlight!
212
+
213
+ end # def assert_equal_with_highlighting
214
+ alias_method_chain :assert_equal, :highlighting
215
+
216
+ end
217
+ end
218
+ end
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+ # _____ _
228
+ # |_ _|__ ___| |_
229
+ # | |/ _ \/ __| __|
230
+ # | | __/\__ \ |_
231
+ # |_|\___||___/\__|
232
+ #
233
+ =begin test
234
+ require 'test/unit'
235
+ #Test::Unit::Assertions::use_assert_equal_with_highlight!
236
+
237
+ # :todo: Currently these (intentionally failing) tests are just manual and require visual inspection. If possible it would be
238
+ # nice to capture the output of the failure and make an assertion against that. But I'm not sure how to do that...
239
+
240
+ class TheTest < Test::Unit::TestCase
241
+ def test01_single_character_differences
242
+ assert_equal <<End, <<End
243
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat mi. In sagittis, augue non eleifend sodales, arcu urna congue sapien, aliquet molestie pede urna sit amet dolor. Etiam diam. Vestibulum ornare, felis et porta faucibus, magna sapien vulputate arcu, vel facilisis lectus ipsum et ipsum.
244
+
245
+ Vivamus massa odio, lacinia eu, euismod vitae, lobortis eu, erat. Duis tincidunt, neque ac_tincidunt convallis, nibh tellus sodales eros, ut tristique nunc purus in urna. Nullam semper. Fusce quis augue ut metus interdum congue. Duis id dolor eu mi pellentesque sagittis. Quisque imperdiet orci a odio.
246
+ End
247
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat mi. In sagittis, augue non eleifend sodales, arcu urna congue sapien, aliquet molestie pede urna sit amet dolor. Etiam diam. Vestibulum ornare, felis et porta faucibus, magna sapien vulputate arcu, vel facilisis lectus ipsum et ipsum.
248
+
249
+ Vivamus massa odio, lacinia eu, euismod vitae, lobortis eu, erat. Duis tincidunt, neque ac tincidunt convallis, nibh tellus sodales eros, ut tristique nunc purus in urna. Nullam semper. Fusce quis augue ut metus interdum congue. Duis id color eu mi pellentesque sagittis. Quisque imperdiet orci a odio.
250
+ End
251
+ end
252
+
253
+ def test02_difference_in_control_characters
254
+ assert_equal "Lorem ipsum dolor sit amet,\nconsectetuer adipiscing elit.\nSed feugiat mi.",
255
+ "Lorem ipsum_dolor sit amet, consectetuer\tadipiscing elit.\n\rSed feugiat mi.", :highlight => true
256
+ end
257
+
258
+ def test03_expected_is_longer
259
+ assert_equal '1234567890', '123', :highlight => true
260
+ end
261
+
262
+ def test04_actual_is_longer
263
+ assert_equal '123', '1234567890', :highlight => true
264
+ end
265
+
266
+ # Use the ones above this line as screenshot material...
267
+
268
+ def test05_one_is_much_longer
269
+ assert_equal <<End, <<End
270
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat mi. In sagittis, augue non eleifend sodales, arcu urna congue sapien, aliquet molestie pede urna sit amet dolor. Etiam diam. Vestibulum ornare, felis et porta faucibus, magna sapien vulputate arcu, vel facilisis lectus ipsum et ipsum. Sed dictum, dolor suscipit malesuada pharetra, orci augue lobortis lectus, porta porta magna magna ut dui. Duis viverra enim sed felis. Mauris semper volutpat pede. Integer lectus lorem, lacinia in, iaculis ut, euismod non, nulla. Nunc non libero eget diam congue ornare. Nunc dictum tellus sed turpis. Sed venenatis, pede non ultricies pharetra, dolor felis malesuada nisl, id imperdiet lorem dui vel velit.
271
+ End
272
+ Lorem ipsum dolor sit amet
273
+ End
274
+ end
275
+
276
+ def test06_only_minor_single_character_differences_but_then_it_gets_out_of_sync
277
+ assert_equal <<End, <<End
278
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat mi. In sagittis, augue non eleifend sodales, arcu urna congue sapien.
279
+
280
+ Vivamus massa odio, lacinia eu, euismod vitae, lobortis eu, erat. Duis tincidunt, neque ac tincidunt convallis, nibh tellus sodales eros, ut tristique nunc purus in urna. Nullam semper. Fusce quis augue ut metus interdum congue. Duis id dolor eu mi pellentesque sagittis. Quisque imperdiet orci a odio.
281
+ End
282
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat mi. In sagittis, argue non eleifend sodales, arcu urna conque sapien.
283
+
284
+ Vivamus massa odio, lacinia eu, euismod vitae, lobortis eu, erat. Duis tincidunt, neque ac tincidunt convallis, nibh tellus sodales eros, ut tristique nunc purus in urna. Nullam semper. Fusce quis augue ut metus interdum congue. Duis id dolor eu mi pellentesque sagittis. Quisque imperdiet orci a odio.
285
+ End
286
+ end
287
+
288
+ def test07_underscores_versus_underlines
289
+ assert_equal <<End, <<End
290
+ ___[Underscores]___[Underscores] [Spaces] _ _ _ _ _ [Mix]
291
+ End
292
+ [Spaces] ___[Underscores] [Spaces] _ _ __ _ _[Mix]
293
+ End
294
+ end
295
+
296
+ def test08_inspect_strings_true
297
+ assert_equal '1234567890', '123', :inspect_strings => true
298
+ end
299
+ def test09_inspect_highlight_false
300
+ assert_equal '1234567890', '123', :highlight => false
301
+ end
302
+ def test10_highlight_false
303
+ Test::Unit::Assertions::use_assert_equal_with_highlight! false do
304
+ assert_equal 'really long string', 'another really long string'
305
+ end
306
+ end
307
+ def test11_highlight_true
308
+ Test::Unit::Assertions::use_assert_equal_with_highlight! do
309
+ assert_equal 'really long string', 'another really long string'
310
+ end
311
+ end
312
+ def test12_compatibility__using_arg3_as_message
313
+ assert_equal 'really long string', 'another really long string', 'This is my message! Can you see it?'
314
+ end
315
+ def test13_that_assert_nil_still_works
316
+ # Exposed a bug that existed previously, where it tried to do "".delete(:message)
317
+ assert_nil nil
318
+ end
319
+
320
+ end
321
+ =end
322
+
323
+