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.
- data/README.markdown +300 -0
- data/lib/wrong.rb +27 -0
- data/lib/wrong/adapters/minitest.rb +14 -0
- data/lib/wrong/adapters/rspec.rb +21 -0
- data/lib/wrong/adapters/test_unit.rb +9 -0
- data/lib/wrong/assert.rb +105 -0
- data/lib/wrong/chunk.rb +233 -0
- data/lib/wrong/close_to.rb +9 -0
- data/lib/wrong/config.rb +29 -0
- data/lib/wrong/d.rb +42 -0
- data/lib/wrong/failure_message.rb +43 -0
- data/lib/wrong/helpers.rb +66 -0
- data/lib/wrong/irb.rb +16 -0
- data/lib/wrong/message/array_diff.rb +69 -0
- data/lib/wrong/message/string_comparison.rb +88 -0
- data/lib/wrong/message/test_context.rb +28 -0
- data/lib/wrong/rainbow.rb +127 -0
- data/lib/wrong/ruby2ruby_patch.rb +37 -0
- data/lib/wrong/sexp_ext.rb +49 -0
- data/lib/wrong/version.rb +3 -0
- data/test/adapters/minitest_test.rb +97 -0
- data/test/adapters/rspec1/failing_spec.rb +23 -0
- data/test/adapters/rspec2/failing_spec.rb +26 -0
- data/test/adapters/rspec_test.rb +104 -0
- data/test/adapters/test_unit_test.rb +59 -0
- data/test/assert_advanced_test.rb +51 -0
- data/test/assert_test.rb +76 -0
- data/test/capturing_test.rb +59 -0
- data/test/chunk_test.rb +264 -0
- data/test/close_to_test.rb +39 -0
- data/test/config_test.rb +89 -0
- data/test/d_test.rb +64 -0
- data/test/failure_message_test.rb +40 -0
- data/test/failures_test.rb +157 -0
- data/test/message/array_diff_test.rb +79 -0
- data/test/message/test_context_test.rb +69 -0
- data/test/rescuing_test.rb +17 -0
- data/test/separate.rb +4 -0
- data/test/sexp_ext_test.rb +80 -0
- data/test/string_comparison_test.rb +159 -0
- data/test/suite.rb +7 -0
- data/test/test_helper.rb +64 -0
- data/test/wrong_test.rb +60 -0
- metadata +215 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# This is a failing spec for testing RSpec 1.3 integration
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler"
|
5
|
+
Bundler.setup
|
6
|
+
|
7
|
+
require "spec"
|
8
|
+
|
9
|
+
here = File.expand_path(File.dirname(__FILE__))
|
10
|
+
$:.unshift "#{here}/../../../lib"
|
11
|
+
require "wrong/adapters/rspec"
|
12
|
+
|
13
|
+
# since we're not running 'spec' we have to do some stuff ourselves
|
14
|
+
include Spec::DSL::Main
|
15
|
+
|
16
|
+
describe "arithmetic" do
|
17
|
+
it "should not work like this" do
|
18
|
+
assert { 2 + 2 == 5 }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Spec::Runner.options.parse_format("nested")
|
23
|
+
Spec::Runner.options.run_examples
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This is a failing spec for testing RSpec 2 integration
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler"
|
5
|
+
Bundler.setup
|
6
|
+
|
7
|
+
require "rspec"
|
8
|
+
|
9
|
+
here = File.expand_path(File.dirname(__FILE__))
|
10
|
+
$:.unshift "#{here}/../../../lib"
|
11
|
+
|
12
|
+
# since we're not running 'rspec' we have to do some stuff ourselves
|
13
|
+
require 'rspec'
|
14
|
+
require 'rspec/core'
|
15
|
+
puts RSpec::Core::Version::STRING
|
16
|
+
|
17
|
+
require 'rspec/autorun'
|
18
|
+
require "wrong/adapters/rspec"
|
19
|
+
|
20
|
+
describe "arithmetic" do
|
21
|
+
it "should not work like this" do
|
22
|
+
assert { 2 + 2 == 5 }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# now, thanks to the require 'rspec/autorun', this spec will run and fail
|
@@ -0,0 +1,104 @@
|
|
1
|
+
here = File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "open3"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
require "./test/test_helper"
|
7
|
+
require "wrong/adapters/minitest"
|
8
|
+
|
9
|
+
include Wrong
|
10
|
+
|
11
|
+
# Okay, this looks like RSpec but it's actually minitest
|
12
|
+
describe "testing rspec" do
|
13
|
+
|
14
|
+
def sys(cmd, expected_status = 0)
|
15
|
+
start_time = Time.now
|
16
|
+
$stderr.print cmd
|
17
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thread|
|
18
|
+
# in Ruby 1.8, wait_thread is nil :-( so just pretend the process was successful (status 0)
|
19
|
+
exit_status = (wait_thread.value.exitstatus if wait_thread) || 0
|
20
|
+
output = stdout.read + stderr.read
|
21
|
+
unless expected_status.nil?
|
22
|
+
assert { output and exit_status == expected_status }
|
23
|
+
end
|
24
|
+
yield output if block_given?
|
25
|
+
output
|
26
|
+
end
|
27
|
+
ensure
|
28
|
+
$stderr.puts " (#{"%.2f" % (Time.now - start_time)} sec)"
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear_bundler_env
|
32
|
+
# Bundler inherits its environment by default, so clear it here
|
33
|
+
%w{BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE}.each { |var| ENV.delete(var) }
|
34
|
+
end
|
35
|
+
|
36
|
+
[1, 2].each do |rspec_version|
|
37
|
+
it "version #{rspec_version}" do
|
38
|
+
dir = "#{here}/rspec#{rspec_version}"
|
39
|
+
spec_output = nil
|
40
|
+
Dir.chdir(dir) do
|
41
|
+
clear_bundler_env
|
42
|
+
FileUtils.rm "#{dir}/Gemfile.lock", :force => true
|
43
|
+
|
44
|
+
sys "bundle check" do |output|
|
45
|
+
unless output == "The Gemfile's dependencies are satisfied\n"
|
46
|
+
sys "bundle install --gemfile=#{dir}/Gemfile --local"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
sys "bundle list" do |output|
|
51
|
+
lines = output.split("\n")
|
52
|
+
lines.grep(/rspec/) do |line|
|
53
|
+
assert { line =~ /rspec[-\w]* \(#{rspec_version}\.[\w.]*\)/ }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
spec_output = sys "ruby #{dir}/failing_spec.rb",
|
58
|
+
(rspec_version == 1 || RUBY_VERSION =~ /^1\.8\./ || RUBY_VERSION == '1.9.1' ? nil : 1) # RSpec v1 exits with 0 on failure :-(
|
59
|
+
end
|
60
|
+
|
61
|
+
assert { spec_output.include? "1 example, 1 failure" }
|
62
|
+
assert { spec_output.include? "Expected ((2 + 2) == 5), but" }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
=begin
|
68
|
+
# I would use
|
69
|
+
# out, err = capturing(:stdout, :stderr) do
|
70
|
+
# but minitest does its own arcane stream munging and it's not working
|
71
|
+
|
72
|
+
out = StringIO.new
|
73
|
+
err = StringIO.new
|
74
|
+
Spec::Runner.use(Spec::Runner::Options.new(out, err))
|
75
|
+
|
76
|
+
module RSpecWrapper
|
77
|
+
include Spec::DSL::Main
|
78
|
+
describe "inside rspec land" do
|
79
|
+
it "works" do
|
80
|
+
sky = "blue"
|
81
|
+
assert { sky == "green" }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
Spec::Runner.options.parse_format("nested")
|
87
|
+
Spec::Runner.options.run_examples
|
88
|
+
|
89
|
+
assert(err.string.index(<<-RSPEC) == 0, "make sure the rspec formatter was used")
|
90
|
+
inside rspec land
|
91
|
+
works (FAILED - 1)
|
92
|
+
|
93
|
+
1)
|
94
|
+
'inside rspec land works' FAILED
|
95
|
+
RSPEC
|
96
|
+
|
97
|
+
failures = Spec::Runner.options.reporter.instance_variable_get(:@failures) # todo: use my own reporter?
|
98
|
+
assert !failures.empty?
|
99
|
+
exception = failures.first.exception
|
100
|
+
assert(exception.is_a?(Spec::Expectations::ExpectationNotMetError))
|
101
|
+
assert(exception.message =~ /^Expected \(sky == \"green\"\), but/, "message is #{exception.message.inspect}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
=end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
|
5
|
+
#require "wrong/assert"
|
6
|
+
require "wrong/adapters/test_unit"
|
7
|
+
|
8
|
+
# get rid of atrocious Test::Unit color scheme (gray on green = puke)
|
9
|
+
Test::Unit::AutoRunner.setup_option do |auto_runner, opts|
|
10
|
+
auto_runner.runner_options[:use_color] = false
|
11
|
+
end
|
12
|
+
|
13
|
+
class MyFailingAssertTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_wrong_assert_and_deny_are_available_to_test_unit_tests
|
16
|
+
my_failing_assert_test = Class.new(Test::Unit::TestCase)
|
17
|
+
my_failing_assert_test.class_eval do
|
18
|
+
def test_fail
|
19
|
+
assert{1==2}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
my_failing_deny_test = Class.new(Test::Unit::TestCase)
|
24
|
+
my_failing_deny_test.class_eval do
|
25
|
+
def test_fail
|
26
|
+
deny{1==1}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
result = Test::Unit::TestResult.new
|
31
|
+
my_failing_assert_test.new("test_fail").run(result) {|started, name| }
|
32
|
+
#I can do without all the TU Listener business, thank you
|
33
|
+
failures = result.instance_variable_get("@failures".to_sym)
|
34
|
+
assert{ failures.length==1 }
|
35
|
+
assert{ failures.first.long_display.include?("1 is not equal to 2") }
|
36
|
+
|
37
|
+
result = Test::Unit::TestResult.new
|
38
|
+
failures = result.instance_variable_get("@failures".to_sym)
|
39
|
+
my_failing_deny_test.new("test_fail").run(result) {|started, name| }
|
40
|
+
assert{ failures.length==1 }
|
41
|
+
assert{ failures.first.long_display.include?("1 is equal to 1") }
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_passes_asserts_with_no_block_up_to_the_frameworks_assert_method
|
45
|
+
e = rescuing { assert(1 == 2) }
|
46
|
+
assert { e.message == "<false> is not true." }
|
47
|
+
|
48
|
+
e = rescuing { assert(1 == 2, "black is white") }
|
49
|
+
assert { e.message == "black is white.\n<false> is not true." }
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_passes_denys_with_no_block_up_to_the_frameworks_assert_method
|
53
|
+
e = rescuing { deny(2 + 2 == 4) }
|
54
|
+
assert { e.message == "<false> is not true." }
|
55
|
+
|
56
|
+
e = rescuing { deny(2 + 2 == 4, "up is down") }
|
57
|
+
assert { e.message == "up is down.\n<false> is not true." }
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
require "wrong/assert"
|
3
|
+
require "wrong/adapters/minitest"
|
4
|
+
|
5
|
+
describe "advanced assert features" do
|
6
|
+
|
7
|
+
def assert_later(&p)
|
8
|
+
assert(&p)
|
9
|
+
end
|
10
|
+
|
11
|
+
# dunno why, but this fails under JRuby (both 1.8 and 1.9)
|
12
|
+
unless Object.const_defined? :JRuby
|
13
|
+
it "is possible (but hardly advisable) to define procs in different places from the assert call" do
|
14
|
+
x = 10
|
15
|
+
e = get_error do
|
16
|
+
assert_later { x > 10 }
|
17
|
+
end
|
18
|
+
|
19
|
+
assert(e.message =~ /Expected \(x > 10\), but.*x is 10/m, e.message)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
xit "can parse a here doc defined inside the block" do
|
24
|
+
# todo: test in Chunk too
|
25
|
+
assert { "123\n456" == <<-TEXT
|
26
|
+
123
|
27
|
+
456
|
28
|
+
TEXT
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
xit "can parse a here doc defined outside the block" do
|
33
|
+
# todo: test in Chunk too
|
34
|
+
assert { "123\n456" == <<-TEXT }
|
35
|
+
123
|
36
|
+
456
|
37
|
+
TEXT
|
38
|
+
end
|
39
|
+
|
40
|
+
it "finds the file to parse even when inside a chdir to a child directory" do
|
41
|
+
e = get_error do
|
42
|
+
Dir.chdir("test") do
|
43
|
+
assert { (1 + 2) == 5 }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
assert { e.message.include? "Expected ((1 + 2) == 5), but" }
|
47
|
+
end
|
48
|
+
|
49
|
+
# todo: test for finding it if you'd changed dirs into a parent or sibling or cousin dir
|
50
|
+
|
51
|
+
end
|
data/test/assert_test.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
require "wrong/assert"
|
3
|
+
|
4
|
+
describe "basic assert features" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@m = Module.new do
|
8
|
+
extend Wrong::Assert
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "pass/fail basics" do
|
13
|
+
it "passes when the result is true. deny does the reverse" do
|
14
|
+
@m.assert { true }
|
15
|
+
@m.assert { 1==1 }
|
16
|
+
|
17
|
+
@m.deny { false }
|
18
|
+
@m.deny { 1==2 }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "fails when result is false. deny does the reverse" do
|
22
|
+
get_error {
|
23
|
+
@m.assert { false }
|
24
|
+
} || fail
|
25
|
+
get_error {
|
26
|
+
@m.assert { 1==2 }
|
27
|
+
} || fail
|
28
|
+
|
29
|
+
get_error {
|
30
|
+
@m.deny { true }
|
31
|
+
} || fail
|
32
|
+
get_error {
|
33
|
+
@m.deny { 1==1 }
|
34
|
+
} || fail
|
35
|
+
end
|
36
|
+
|
37
|
+
class MyError < StandardError;
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "assert" do
|
41
|
+
it "fails when an error is thrown and bubbles up the error" do
|
42
|
+
assert_raises(MyError) { @m.assert { raise MyError.new } }
|
43
|
+
end
|
44
|
+
|
45
|
+
it "takes an optional explanation" do
|
46
|
+
e = get_error {
|
47
|
+
sky = "green"
|
48
|
+
@m.assert("the sky should be blue") { sky == "blue" }
|
49
|
+
}
|
50
|
+
assert e.message =~ /^the sky should be blue: /, e.message
|
51
|
+
end
|
52
|
+
|
53
|
+
it "gives a meaningful error when passed no block" do
|
54
|
+
e = get_error {
|
55
|
+
@m.assert(2+2 == 5)
|
56
|
+
}
|
57
|
+
assert e.message =~ /a block/, e.message
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "deny" do
|
62
|
+
it "fails when an error is thrown and bubbles up the error" do
|
63
|
+
assert_raises(MyError) { @m.deny { raise MyError.new } }
|
64
|
+
end
|
65
|
+
|
66
|
+
it "takes an optional explanation" do
|
67
|
+
e = get_error {
|
68
|
+
sky = "blue"
|
69
|
+
@m.deny("the sky should not be blue") { sky == "blue" }
|
70
|
+
}
|
71
|
+
assert e.message =~ /^the sky should not be blue: /,
|
72
|
+
e.message + "\n\t" + e.backtrace.join("\n\t")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
|
3
|
+
require "wrong/assert"
|
4
|
+
require "wrong/helpers"
|
5
|
+
|
6
|
+
describe "a tool for capturing output" do
|
7
|
+
|
8
|
+
include Wrong::Assert
|
9
|
+
include Wrong::Helpers
|
10
|
+
|
11
|
+
it "captures stdout" do
|
12
|
+
assert {
|
13
|
+
capturing { puts "hi" } == "hi\n"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
it "captures stderr" do
|
18
|
+
assert {
|
19
|
+
capturing(:stderr) { $stderr.puts "hi" } == "hi\n"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "captures both" do
|
24
|
+
out, err = capturing(:stdout, :stderr) do
|
25
|
+
$stdout.puts "hi"
|
26
|
+
$stderr.puts "bye"
|
27
|
+
end
|
28
|
+
|
29
|
+
assert { out == "hi\n"}
|
30
|
+
assert { err == "bye\n"}
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
it "supports nesting" do
|
35
|
+
inside = nil
|
36
|
+
outside = capturing do
|
37
|
+
puts "bread"
|
38
|
+
inside = capturing do
|
39
|
+
puts "ham"
|
40
|
+
end
|
41
|
+
puts "more bread"
|
42
|
+
end
|
43
|
+
|
44
|
+
assert { inside == "ham\n"}
|
45
|
+
assert { outside == "bread\nham\nmore bread\n"}
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
it "bails if stream was reassigned" do
|
50
|
+
e = rescuing do
|
51
|
+
capturing do
|
52
|
+
$stdout = StringIO.new # uh-oh!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
assert { e.message =~ /^stdout was reassigned/ }
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
end
|
data/test/chunk_test.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
require "wrong/chunk"
|
3
|
+
|
4
|
+
unless Object.const_defined?(:Chunk)
|
5
|
+
Chunk = Wrong::Chunk
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Chunk do
|
9
|
+
describe "#from_block" do
|
10
|
+
it "reads the source location" do
|
11
|
+
file, line = __FILE__, __LINE__
|
12
|
+
chunk = Chunk.from_block(proc { "hi" })
|
13
|
+
assert(chunk.file == file)
|
14
|
+
assert(chunk.line_number == line+1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "line numbers" do
|
19
|
+
before do
|
20
|
+
@chunk = Wrong::Chunk.new("foo.rb", 10)
|
21
|
+
end
|
22
|
+
it "#line_index is zero-based" do
|
23
|
+
assert(@chunk.line_index == 9)
|
24
|
+
end
|
25
|
+
it "#location is one-based" do
|
26
|
+
assert(@chunk.location == "foo.rb:10")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "parsing" do
|
31
|
+
it "reads a statement on a line by itself" do
|
32
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
33
|
+
"hi"
|
34
|
+
CODE
|
35
|
+
code = chunk.sexp.to_ruby
|
36
|
+
assert(code == '"hi"')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "reads a statement on multiple lines" do
|
40
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
41
|
+
proc do
|
42
|
+
"hi"
|
43
|
+
end
|
44
|
+
CODE
|
45
|
+
code = chunk.sexp.to_ruby
|
46
|
+
assert(code == "proc { \"hi\" }")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "fails if there's a stray close-paren symbol on the last line (sorry)" do
|
50
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
51
|
+
"hi" )
|
52
|
+
CODE
|
53
|
+
assert(chunk.sexp.nil?)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "fails if there's a stray close-block symbol on the last line (sorry)" do
|
57
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
58
|
+
"hi" }
|
59
|
+
CODE
|
60
|
+
assert(chunk.sexp.nil?)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "fails if it can't parse the code" do
|
64
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
65
|
+
}
|
66
|
+
CODE
|
67
|
+
assert(chunk.sexp.nil?)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "fails if it can't find the file" do
|
71
|
+
chunk = Chunk.new("nonexistent_file.rb", 0)
|
72
|
+
error = get_error { chunk.sexp }
|
73
|
+
assert error.is_a? Errno::ENOENT
|
74
|
+
end
|
75
|
+
|
76
|
+
it "finds the file to parse even when inside a chdir to a child directory" do
|
77
|
+
Dir.chdir("test") do
|
78
|
+
chunk = Chunk.new __FILE__, __LINE__ + 1; <<-CODE
|
79
|
+
"hi"
|
80
|
+
CODE
|
81
|
+
code = chunk.sexp.to_ruby
|
82
|
+
assert(code == '"hi"')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#claim" do
|
88
|
+
it "returns the part of the assertion statement inside the curly braces" do
|
89
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
90
|
+
assert { x == 5 }
|
91
|
+
CODE
|
92
|
+
full_code = chunk.sexp.to_ruby
|
93
|
+
assert(full_code == "assert { (x == 5) }")
|
94
|
+
claim_code = chunk.claim.to_ruby
|
95
|
+
assert claim_code == "(x == 5)"
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
it "reads an assert statement on a line by itself" do
|
100
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
101
|
+
assert { x == 5 }
|
102
|
+
CODE
|
103
|
+
claim_code = chunk.claim.to_ruby
|
104
|
+
assert claim_code == "(x == 5)"
|
105
|
+
end
|
106
|
+
|
107
|
+
it "reads an assert statement on multiple lines" do
|
108
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
109
|
+
assert do
|
110
|
+
x == 5
|
111
|
+
end
|
112
|
+
CODE
|
113
|
+
claim_code = chunk.claim.to_ruby
|
114
|
+
assert claim_code == "(x == 5)"
|
115
|
+
end
|
116
|
+
|
117
|
+
def yielding
|
118
|
+
yield
|
119
|
+
end
|
120
|
+
|
121
|
+
if RUBY_VERSION > "1.9"
|
122
|
+
it "reads an assert statement that's nested inside another yield block on the same line (Ruby 1.9 only)" do
|
123
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
124
|
+
yielding { assert { x == 5 }}
|
125
|
+
CODE
|
126
|
+
code = chunk.claim.to_ruby
|
127
|
+
assert code == "(x == 5)"
|
128
|
+
end
|
129
|
+
|
130
|
+
# test "goes crazy if you try to nest two asserts on the same line"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "if it can't find an assertion, it uses the whole chunk" do
|
134
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
135
|
+
yielding { x == 5 }
|
136
|
+
CODE
|
137
|
+
code = chunk.claim.to_ruby
|
138
|
+
assert code == "yielding { (x == 5) }"
|
139
|
+
end
|
140
|
+
|
141
|
+
it "fails if it can't parse the code" do
|
142
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
143
|
+
}
|
144
|
+
CODE
|
145
|
+
error = get_error {
|
146
|
+
chunk.claim
|
147
|
+
}
|
148
|
+
assert error.message.include?("Could not parse")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#parts" do
|
153
|
+
it "returns all unique sub-expressions of the main sexpression" do
|
154
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
155
|
+
assert { (x == 5) && (y == (z + 10)) }
|
156
|
+
CODE
|
157
|
+
code_parts = chunk.parts
|
158
|
+
assert code_parts == <<-PARTS.split("\n")
|
159
|
+
((x == 5) and (y == (z + 10)))
|
160
|
+
(x == 5)
|
161
|
+
x
|
162
|
+
5
|
163
|
+
(y == (z + 10))
|
164
|
+
y
|
165
|
+
(z + 10)
|
166
|
+
z
|
167
|
+
10
|
168
|
+
PARTS
|
169
|
+
end
|
170
|
+
|
171
|
+
it "omits the method-call-sans-block part of a method call with a block" do
|
172
|
+
chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
|
173
|
+
assert { rescuing { 1 + 2 } }
|
174
|
+
CODE
|
175
|
+
code_parts = chunk.parts
|
176
|
+
assert !code_parts.include?("rescuing")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "#details" do
|
181
|
+
def details(&block)
|
182
|
+
chunk = Chunk.from_block(block, 1)
|
183
|
+
d = chunk.details
|
184
|
+
# puts d
|
185
|
+
d
|
186
|
+
end
|
187
|
+
|
188
|
+
it "returns an empty string if there are no parts" do
|
189
|
+
d = details { assert { true } }
|
190
|
+
assert d == ""
|
191
|
+
end
|
192
|
+
|
193
|
+
it "returns an string beginning with a newline if there are parts" do
|
194
|
+
x = 10
|
195
|
+
d = details { assert { x == 10 } }
|
196
|
+
assert d == "\n x is 10\n"
|
197
|
+
end
|
198
|
+
|
199
|
+
it "skips literals" do
|
200
|
+
d = details { assert { 10 == 11 } }
|
201
|
+
assert d == ""
|
202
|
+
end
|
203
|
+
|
204
|
+
it "shows lots of details" do
|
205
|
+
x = 10
|
206
|
+
d = details { assert { (x * (x - 10)) == (x / (x + 10)) } }
|
207
|
+
assert d == <<-DETAILS
|
208
|
+
|
209
|
+
(x * (x - 10)) is 0
|
210
|
+
x is 10
|
211
|
+
(x - 10) is 0
|
212
|
+
(x / (x + 10)) is 0
|
213
|
+
(x + 10) is 20
|
214
|
+
DETAILS
|
215
|
+
end
|
216
|
+
|
217
|
+
it "skips duplicates" do
|
218
|
+
x = 10
|
219
|
+
d = details { assert { (x + 5) == 1 + (x + 5) } }
|
220
|
+
assert d == <<-DETAILS
|
221
|
+
|
222
|
+
(x + 5) is 15
|
223
|
+
x is 10
|
224
|
+
(1 + (x + 5)) is 16
|
225
|
+
DETAILS
|
226
|
+
end
|
227
|
+
|
228
|
+
it "shows exceptions" do
|
229
|
+
d = details { assert { (raise "hi") == 1 } }
|
230
|
+
assert d == "\n raise(\"hi\") raises RuntimeError: hi\n"
|
231
|
+
end
|
232
|
+
|
233
|
+
it "indents newlines inside the exception message" do
|
234
|
+
d = details { assert { (raise "hello\nsailor") == 1 } }
|
235
|
+
assert d == "\n raise(\"hello\\nsailor\") raises RuntimeError: hello\n sailor\n"
|
236
|
+
end
|
237
|
+
|
238
|
+
it "abridges exceptions with no message" do
|
239
|
+
d = details { assert { (raise Exception.new) == 1 } }
|
240
|
+
assert d == "\n raise(Exception.new) raises Exception\n" +
|
241
|
+
" Exception.new is #<Exception: Exception>\n"
|
242
|
+
end
|
243
|
+
|
244
|
+
it "inspects values" do
|
245
|
+
x = "flavor:\tvanilla"
|
246
|
+
d = details { assert { x == "flavor:\tchocolate" } }
|
247
|
+
# this means it's a literal slash plus t inside double quotes -- i.e. it shows the escaped (inspected) string
|
248
|
+
assert d == "\n" + ' x is "flavor:\tvanilla"' + "\n"
|
249
|
+
end
|
250
|
+
|
251
|
+
it "indents unescaped newlines inside the inspected value" do
|
252
|
+
weirdo = Object.new
|
253
|
+
|
254
|
+
def weirdo.inspect
|
255
|
+
"first\nsecond\nthird"
|
256
|
+
end
|
257
|
+
|
258
|
+
x = weirdo
|
259
|
+
d = details { assert { x == "foo" } }
|
260
|
+
assert d == "\n x is first\n second\n third\n"
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
end
|