wrong 0.4.0-java

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.
Files changed (44) hide show
  1. data/README.markdown +300 -0
  2. data/lib/wrong.rb +27 -0
  3. data/lib/wrong/adapters/minitest.rb +14 -0
  4. data/lib/wrong/adapters/rspec.rb +21 -0
  5. data/lib/wrong/adapters/test_unit.rb +9 -0
  6. data/lib/wrong/assert.rb +105 -0
  7. data/lib/wrong/chunk.rb +233 -0
  8. data/lib/wrong/close_to.rb +9 -0
  9. data/lib/wrong/config.rb +29 -0
  10. data/lib/wrong/d.rb +42 -0
  11. data/lib/wrong/failure_message.rb +43 -0
  12. data/lib/wrong/helpers.rb +66 -0
  13. data/lib/wrong/irb.rb +16 -0
  14. data/lib/wrong/message/array_diff.rb +69 -0
  15. data/lib/wrong/message/string_comparison.rb +88 -0
  16. data/lib/wrong/message/test_context.rb +28 -0
  17. data/lib/wrong/rainbow.rb +127 -0
  18. data/lib/wrong/ruby2ruby_patch.rb +37 -0
  19. data/lib/wrong/sexp_ext.rb +49 -0
  20. data/lib/wrong/version.rb +3 -0
  21. data/test/adapters/minitest_test.rb +97 -0
  22. data/test/adapters/rspec1/failing_spec.rb +23 -0
  23. data/test/adapters/rspec2/failing_spec.rb +26 -0
  24. data/test/adapters/rspec_test.rb +104 -0
  25. data/test/adapters/test_unit_test.rb +59 -0
  26. data/test/assert_advanced_test.rb +51 -0
  27. data/test/assert_test.rb +76 -0
  28. data/test/capturing_test.rb +59 -0
  29. data/test/chunk_test.rb +264 -0
  30. data/test/close_to_test.rb +39 -0
  31. data/test/config_test.rb +89 -0
  32. data/test/d_test.rb +64 -0
  33. data/test/failure_message_test.rb +40 -0
  34. data/test/failures_test.rb +157 -0
  35. data/test/message/array_diff_test.rb +79 -0
  36. data/test/message/test_context_test.rb +69 -0
  37. data/test/rescuing_test.rb +17 -0
  38. data/test/separate.rb +4 -0
  39. data/test/sexp_ext_test.rb +80 -0
  40. data/test/string_comparison_test.rb +159 -0
  41. data/test/suite.rb +7 -0
  42. data/test/test_helper.rb +64 -0
  43. data/test/wrong_test.rb +60 -0
  44. metadata +215 -0
@@ -0,0 +1,69 @@
1
+ require "diff/lcs"
2
+ require "wrong/failure_message"
3
+
4
+ module Wrong
5
+ class ArrayDiff < FailureMessage::Formatter
6
+ register # tell FailureMessage::Formatter about us
7
+
8
+ def match?
9
+ predicate.is_a?(Predicated::Equal) &&
10
+ arrayish?(predicate.left) &&
11
+ arrayish?(predicate.right)
12
+ end
13
+
14
+ def arrayish?(object)
15
+ # in some Rubies, String is Enumerable
16
+ object.is_a?(Enumerable) && !object.is_a?(String)
17
+ end
18
+
19
+ def describe
20
+ left_str, right_str, diff_str = compute_and_format(predicate.left, predicate.right)
21
+
22
+ message = "\n"
23
+ message << left_str + "\n"
24
+ message << right_str + "\n"
25
+ message << diff_str + "\n"
26
+ message
27
+
28
+ end
29
+
30
+ def compute_and_format(left, right)
31
+ diffs = Diff::LCS.sdiff(left, right)
32
+
33
+ left_arr = []
34
+ right_arr = []
35
+ diff_arr = []
36
+
37
+ diffs.each do |diff|
38
+ left_elem = diff.old_element.nil? ? "nil" : diff.old_element.inspect
39
+ right_elem = diff.new_element.nil? ? "nil" : diff.new_element.inspect
40
+
41
+ max_length = [left_elem.length, right_elem.length].max
42
+ left_arr << left_elem.ljust(max_length) unless diff.action == "+"
43
+ right_arr << right_elem.ljust(max_length) unless diff.action == "-"
44
+ diff_arr << (diff.action == "=" ? " ".ljust(max_length) : "^".ljust(max_length))
45
+ end
46
+
47
+
48
+ diff_str = " " + diff_arr.join(" ") + " "
49
+
50
+ [format(left_arr), format(right_arr), diff_str]
51
+ end
52
+
53
+ def format(thing)
54
+ str = ""
55
+ if thing.is_a?(Array)
56
+ str << "["
57
+ thing.each_with_index do |item, i|
58
+ str << format(item)
59
+ str << ", " unless i == thing.length-1
60
+ end
61
+ str << "]"
62
+ else
63
+ str << thing
64
+ end
65
+ str
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,88 @@
1
+ require "wrong/failure_message"
2
+
3
+ module Wrong
4
+ class StringComparison
5
+ @@window = 64
6
+ @@prelude = 12
7
+
8
+ def self.window
9
+ @@window
10
+ end
11
+
12
+ def self.window=(val)
13
+ @@window = val
14
+ end
15
+
16
+ def self.prelude
17
+ @@prelude
18
+ end
19
+
20
+ def self.prelude=(val)
21
+ @@prelude = val
22
+ end
23
+
24
+ def initialize(first, second)
25
+ @first = first
26
+ @second = second
27
+ end
28
+
29
+ def same?
30
+ @first == @second
31
+ end
32
+
33
+ def different_at
34
+ if (@first.nil? || @second.nil?)
35
+ 0
36
+ else
37
+ i = 0
38
+ while (i < @first.size && i < @second.size)
39
+ if @first[i] != @second[i]
40
+ break
41
+ end
42
+ i += 1
43
+ end
44
+ return i
45
+ end
46
+ end
47
+
48
+ def message
49
+ "Strings differ at position #{different_at}:\n" +
50
+ " first: #{chunk(@first)}\n" +
51
+ "second: #{chunk(@second)}"
52
+ end
53
+
54
+ def chunk(s)
55
+ prefix, middle, suffix = "...", "", "..."
56
+
57
+ start = different_at - @@prelude
58
+ if start < 0
59
+ prefix = ""
60
+ start = 0
61
+ end
62
+
63
+ stop = start + @@window
64
+ if stop >= s.size
65
+ suffix = ""
66
+ stop = s.size
67
+ end
68
+
69
+ [prefix, s[start...stop].inspect, suffix].join
70
+ end
71
+ end
72
+
73
+ class StringComparisonFormatter < FailureMessage::Formatter
74
+ register # tell FailureMessage::Formatter about us
75
+
76
+ def match?
77
+ predicate.is_a?(Predicated::Equal) &&
78
+ predicate.left.is_a?(String) &&
79
+ predicate.right.is_a?(String)
80
+ end
81
+
82
+ def describe
83
+ comparison = Wrong::StringComparison.new(predicate.left, predicate.right)
84
+ "\n" + comparison.message
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,28 @@
1
+ module Wrong
2
+ module Assert
3
+ # todo: integrate with / use Chunk somehow?
4
+ #
5
+ def failure_message(method_sym, block, predicate)
6
+ upper_portion = super
7
+
8
+ first_test_line = caller.find{|line|line =~ /(_test.rb|_spec.rb)/}
9
+ raise "Can't find test or spec in call chain: #{caller.join('|')}" if first_test_line.nil?
10
+ file, failure_line_number = first_test_line.split(":",2)
11
+
12
+ lines = File.readlines(file)
13
+ line_number = failure_line_number.to_i - 1
14
+ to_show = []
15
+ begin
16
+ line = lines[line_number]
17
+ to_show.unshift(line)
18
+ line_number -= 1
19
+ end while !(line =~ /^\s+(test|it)[ ]+/ || line =~ /^\s+def test_\w+/)
20
+
21
+ to_show[to_show.length-1] = to_show[to_show.length-1].chomp +
22
+ " ASSERTION FAILURE #{file}:#{failure_line_number.to_i}\n"
23
+
24
+ upper_portion + "\n\n" + to_show.join
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,127 @@
1
+ # Lifted from Rainbow gem, http://sickill.net/blog/2009/03/24/colorizing-console-output-with-rainbow-ruby-gem.html
2
+
3
+ module Sickill
4
+ module Rainbow
5
+ class << self; attr_accessor :enabled; end
6
+ @enabled = STDOUT.tty? && ENV['TERM'] != 'dumb'
7
+
8
+ TERM_COLORS = {
9
+ :black => 0,
10
+ :red => 1,
11
+ :green => 2,
12
+ :yellow => 3,
13
+ :blue => 4,
14
+ :magenta => 5,
15
+ :cyan => 6,
16
+ :white => 7,
17
+ :default => 9,
18
+ }
19
+
20
+ TERM_EFFECTS = {
21
+ :reset => 0,
22
+ :bright => 1,
23
+ :italic => 3,
24
+ :underline => 4,
25
+ :blink => 5,
26
+ :inverse => 7,
27
+ :hide => 8,
28
+ }
29
+
30
+ # Sets foreground color of this text.
31
+ def foreground(*color)
32
+ color = color.first if color.size == 1
33
+ wrap_with_code(get_color_code(color, :foreground))
34
+ end
35
+ alias_method :color, :foreground
36
+ alias_method :colour, :foreground
37
+
38
+ # Sets background color of this text.
39
+ def background(*color)
40
+ color = color.first if color.size == 1
41
+ wrap_with_code(get_color_code(color, :background))
42
+ end
43
+
44
+ # Resets terminal to default colors/backgrounds.
45
+ #
46
+ # It shouldn't be needed to use this method because all methods append terminal reset code to end of string.
47
+ def reset
48
+ wrap_with_code(TERM_EFFECTS[:reset])
49
+ end
50
+
51
+ # Turns on bright/bold for this text.
52
+ def bright
53
+ wrap_with_code(TERM_EFFECTS[:bright])
54
+ end
55
+ alias_method :bold, :bright
56
+
57
+ # Turns on italic style for this text (not well supported by terminal emulators).
58
+ def italic
59
+ wrap_with_code(TERM_EFFECTS[:italic])
60
+ end
61
+
62
+ # Turns on underline decoration for this text.
63
+ def underline
64
+ wrap_with_code(TERM_EFFECTS[:underline])
65
+ end
66
+
67
+ # Turns on blinking attribute for this text (not well supported by terminal emulators).
68
+ def blink
69
+ wrap_with_code(TERM_EFFECTS[:blink])
70
+ end
71
+
72
+ # Inverses current foreground/background colors.
73
+ def inverse
74
+ wrap_with_code(TERM_EFFECTS[:inverse])
75
+ end
76
+
77
+ # Hides this text (set its color to the same as background).
78
+ def hide
79
+ wrap_with_code(TERM_EFFECTS[:hide])
80
+ end
81
+
82
+ protected
83
+ def wrap_with_code(code) #:nodoc:
84
+ return self unless Sickill::Rainbow.enabled
85
+
86
+ out = "#{self}"
87
+ match = out.match(/^(\e\[([\d;]+)m)*/)
88
+ out.insert(match.end(0), "\e[#{code}m")
89
+ out.concat("\e[0m") unless out =~ /\e\[0m$/
90
+ out
91
+ end
92
+
93
+ def get_color_code(color, type) #:nodoc:
94
+ case color
95
+ when Symbol
96
+ validate_color(color)
97
+ TERM_COLORS[color] + (type == :foreground ? 30 : 40)
98
+ when String
99
+ color = color.gsub("#", "")
100
+ r, g, b = color[0..1].to_i(16), color[2..3].to_i(16), color[4..5].to_i(16)
101
+ get_rgb_code(r, g, b, type)
102
+ when Array
103
+ raise ArgumentError.new("Bad number of arguments for RGB color definition, should be 3") unless color.size == 3
104
+ get_rgb_code(color[0], color[1], color[2], type)
105
+ end
106
+ end
107
+
108
+ def get_rgb_code(r, g, b, type) #:nodoc:
109
+ raise ArgumentError.new("RGB value outside 0-255 range") if [r, g, b].min < 0 || [r, g, b].max > 255
110
+ code = { :foreground => 38, :background => 48 }[type]
111
+ index = 16 + (6 * (r / 256.0)).to_i * 36 + (6 * (g / 256.0)).to_i * 6 + (6 * (b / 256.0)).to_i
112
+ "#{code};5;#{index}"
113
+ end
114
+
115
+ def validate_color(color) #:nodoc:
116
+ raise ArgumentError.new("Unknown color, valid colors: #{TERM_COLORS.keys.join(', ')}") unless TERM_COLORS.keys.include?(color)
117
+ end
118
+ end
119
+ end
120
+
121
+ String.send(:include, Sickill::Rainbow)
122
+
123
+ begin
124
+ require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/
125
+ rescue LoadError
126
+ Sickill::Rainbow.enabled = false
127
+ end
@@ -0,0 +1,37 @@
1
+ class ::Ruby2Ruby < ::SexpProcessor
2
+ # see http://gist.github.com/321038
3
+ # Monkey-patch to have Ruby2Ruby#translate with r2r >= 1.2.3, from
4
+ # http://seattlerb.rubyforge.org/svn/ruby2ruby/1.2.2/lib/ruby2ruby.rb
5
+ def self.translate(klass_or_str, method = nil)
6
+ sexp = ParseTree.translate(klass_or_str, method)
7
+ unifier = Unifier.new
8
+ unifier.processors.each do |p|
9
+ p.unsupported.delete :cfunc # HACK
10
+ end
11
+ sexp = unifier.process(sexp)
12
+ self.new.process(sexp)
13
+ end
14
+
15
+ #sconover - 7/2010 - monkey-patch
16
+ #{1=>2}=={1=>2}
17
+ #The right side was having its braces cut off because of
18
+ #special handling of hashes within arglists within the seattlerb code.
19
+ #I tried to fork r2r and add a test, but a lot of other tests
20
+ #broke, and I just dont understand the test in ruby2ruby.
21
+ #So I'm emailing the author...
22
+ def process_hash(exp)
23
+ result = []
24
+ until exp.empty?
25
+ lhs = process(exp.shift)
26
+ rhs = exp.shift
27
+ t = rhs.first
28
+ rhs = process rhs
29
+ rhs = "(#{rhs})" unless [:lit, :str].include? t # TODO: verify better!
30
+
31
+ result << "#{lhs} => #{rhs}"
32
+ end
33
+
34
+ return "{ #{result.join(', ')} }"
35
+ end
36
+
37
+ end
@@ -0,0 +1,49 @@
1
+ require 'ruby_parser'
2
+ require 'ruby2ruby'
3
+ require 'wrong/config'
4
+
5
+ class Sexp < Array
6
+
7
+ def to_ruby
8
+ d = self.deep_clone
9
+ ruby = Ruby2Ruby.new.process(d)
10
+ ruby
11
+ end
12
+
13
+ # visit every node in the tree, including the root, that is an Sexp
14
+ # todo: test
15
+ def each_subexp(&block)
16
+ yield self
17
+ each do |child|
18
+ if child.is_a?(Sexp)
19
+ child.each_subexp(&block)
20
+ end
21
+ end
22
+ end
23
+
24
+ def assertion?
25
+ self.is_a? Sexp and
26
+ self[0] == :iter and
27
+ self[1].is_a? Sexp and
28
+ self[1][0] == :call and
29
+ Wrong.config.assert_methods.include? self[1][2] # todo: allow aliases for assert (e.g. "is")
30
+ end
31
+
32
+ def assertion
33
+ sexp = self
34
+ assertion = if sexp.assertion?
35
+ sexp
36
+ else
37
+ nested_assertions.first
38
+ end
39
+ assertion
40
+ end
41
+
42
+ private
43
+ def nested_assertions
44
+ assertions = []
45
+ self.each_of_type(:iter) { |sexp| assertions << sexp if sexp.assertion? }
46
+ assertions
47
+ end
48
+
49
+ end
@@ -0,0 +1,3 @@
1
+ module Wrong
2
+ VERSION = "0.4.0" unless defined?(Wrong::VERSION)
3
+ end
@@ -0,0 +1,97 @@
1
+ require "./test/test_helper"
2
+
3
+ require "minitest/spec"
4
+ require "minitest/unit"
5
+
6
+ require "wrong/assert"
7
+ require "wrong/adapters/minitest"
8
+
9
+ describe "basic assert features" do
10
+
11
+ before do
12
+ @test_case_instance = Class.new(MiniTest::Unit::TestCase).new("x")
13
+ end
14
+
15
+ it "raises minitest assertion failures" do
16
+ test_case_instance = Class.new(MiniTest::Unit::TestCase).new("x")
17
+ assert {
18
+ rescuing {
19
+ test_case_instance.assert { 1==2 }
20
+ }.is_a?(MiniTest::Assertion)
21
+ }
22
+ end
23
+
24
+ it "passes asserts with no block up to the framework's assert method" do
25
+ e = rescuing { assert(1 == 2) }
26
+ assert { e.message == "Failed assertion, no message given." }
27
+
28
+ e = rescuing { assert(1 == 2, "black is white") }
29
+ assert { e.message == "black is white" }
30
+ end
31
+
32
+ it "passes denys with no block up to the framework's assert method" do
33
+ e = rescuing { deny(2 + 2 == 4) }
34
+ assert { e.message == "Failed assertion, no message given." }
35
+
36
+ e = rescuing { deny(2 + 2 == 4, "up is down") }
37
+ assert { e.message == "up is down" }
38
+ end
39
+
40
+ # TODO: optionally print a warning when calling the framework assert
41
+
42
+ it "makes Wrong's assert and deny available to minitest tests" do
43
+ class MyFailingAssertTest < MiniTest::Unit::TestCase
44
+ def initialize
45
+ super("assert test")
46
+ end
47
+
48
+ def test_fail
49
+ assert { 1==2 }
50
+ end
51
+ end
52
+
53
+ class MyFailingDenyTest < MiniTest::Unit::TestCase
54
+ def initialize
55
+ super("deny test")
56
+ end
57
+
58
+ def test_fail
59
+ deny { 1==1 }
60
+ end
61
+ end
62
+
63
+ msg = rescuing { MyFailingAssertTest.new.test_fail }.message
64
+
65
+ assert { msg.include?("1 is not equal to 2") }
66
+
67
+ msg = rescuing { MyFailingDenyTest.new.test_fail }.message
68
+ assert { msg.include?("1 is equal to 1") }
69
+ end
70
+ end
71
+
72
+ describe 'reports number of assertions' do
73
+ before do
74
+ @test = Class.new(MiniTest::Unit::TestCase).new("x")
75
+ end
76
+
77
+ it 'assert{} should bump number of assertions' do
78
+ @test.assert {true}
79
+ assert {@test._assertions == 1}
80
+ end
81
+
82
+ it 'assert() should not bump twice number of assertions' do
83
+ @test.assert(true)
84
+ assert {@test._assertions == 1}
85
+ end
86
+
87
+ it 'deny{} should bump number of assertions' do
88
+ @test.deny {false}
89
+ assert {@test._assertions == 1}
90
+ end
91
+
92
+ it 'deny() should bump once number of assertions' do
93
+ @test.deny(false)
94
+ assert {@test._assertions == 1}
95
+ end
96
+ end
97
+