riot 0.10.9 → 0.10.10

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 (39) hide show
  1. data/CHANGELOG +46 -0
  2. data/README.markdown +53 -16
  3. data/Rakefile +8 -0
  4. data/VERSION +1 -1
  5. data/lib/riot.rb +1 -1
  6. data/lib/riot/assertion.rb +18 -31
  7. data/lib/riot/assertion_macro.rb +35 -0
  8. data/lib/riot/assertion_macros/any.rb +12 -0
  9. data/lib/riot/assertion_macros/assigns.rb +27 -0
  10. data/lib/riot/assertion_macros/empty.rb +13 -0
  11. data/lib/riot/assertion_macros/equals.rb +18 -0
  12. data/lib/riot/assertion_macros/exists.rb +15 -0
  13. data/lib/riot/assertion_macros/includes.rb +17 -0
  14. data/lib/riot/assertion_macros/kind_of.rb +16 -0
  15. data/lib/riot/assertion_macros/matches.rb +17 -0
  16. data/lib/riot/assertion_macros/nil.rb +12 -0
  17. data/lib/riot/assertion_macros/raises.rb +31 -0
  18. data/lib/riot/assertion_macros/respond_to.rb +16 -0
  19. data/lib/riot/assertion_macros/same_elements.rb +14 -0
  20. data/lib/riot/assertion_macros/size.rb +15 -0
  21. data/lib/riot/context.rb +9 -17
  22. data/lib/riot/reporter.rb +25 -21
  23. data/riot.gemspec +17 -3
  24. data/test/assertion_macros/any_test.rb +2 -2
  25. data/test/assertion_macros/equals_test.rb +4 -4
  26. data/test/assertion_macros/exists_test.rb +2 -2
  27. data/test/assertion_macros/includes_test.rb +1 -1
  28. data/test/assertion_macros/kind_of_test.rb +1 -1
  29. data/test/assertion_macros/matching_test.rb +1 -1
  30. data/test/assertion_macros/nil_test.rb +1 -1
  31. data/test/assertion_macros/raises_test.rb +3 -3
  32. data/test/assertion_macros/respond_to_test.rb +1 -1
  33. data/test/assertion_macros/size_test.rb +17 -6
  34. data/test/assertion_test.rb +11 -6
  35. data/test/context_test.rb +2 -54
  36. data/test/report_test.rb +7 -2
  37. data/test/teststrap.rb +12 -3
  38. metadata +17 -3
  39. data/lib/riot/assertion_macros.rb +0 -136
@@ -0,0 +1,31 @@
1
+ module Riot
2
+ # Asserts that the test raises the expected Exception
3
+ # asserts("test") { raise My::Exception }.raises(My::Exception)
4
+ # should("test") { raise My::Exception }.raises(My::Exception)
5
+ #
6
+ # You can also check to see if the provided message equals or matches your expectations. The message
7
+ # from the actual raised exception will be converted to a string before any comparison is executed.
8
+ # asserts("test") { raise My::Exception, "Foo" }.raises(My::Exception, "Foo")
9
+ # asserts("test") { raise My::Exception, "Foo Bar" }.raises(My::Exception, /Bar/)
10
+ class RaisesMacro < AssertionMacro
11
+ register :raises
12
+ expects_exception!
13
+
14
+ def evaluate(actual_exception, expected_class, expected_message=nil)
15
+ actual_message = actual_exception && actual_exception.message
16
+ if actual_exception.nil?
17
+ fail("should have raised #{expected_class}, but raised nothing")
18
+ elsif expected_class != actual_exception.class
19
+ fail("should have raised #{expected_class}, not #{actual_exception.class}")
20
+ elsif expected_message && !(actual_message.to_s =~ %r[#{expected_message}])
21
+ fail("expected #{expected_message.inspect} for message, not #{actual_message.inspect}")
22
+ else
23
+ if expected_message
24
+ pass("raises #{expected_class.inspect} with message #{expected_message.inspect}")
25
+ else
26
+ pass("raises #{expected_class.inspect}")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ module Riot
2
+ # Asserts that the result of the test is an object that responds to the given method
3
+ # asserts("test") { "foo" }.respond_to(:to_s)
4
+ # should("test") { "foo" }.respond_to(:to_s)
5
+ class RespondToMacro < AssertionMacro
6
+ register :respond_to
7
+
8
+ def evaluate(actual, expected)
9
+ if actual.respond_to?(expected)
10
+ pass("responds to #{expected.inspect}")
11
+ else
12
+ fail("expected method #{expected.inspect} is not defined")
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module Riot
2
+ # Asserts that two arrays contain the same elements, the same number of times.
3
+ # asserts("test") { ["foo", "bar"] }.same_elements(["bar", "foo"])
4
+ # should("test") { ["foo", "bar"] }.same_elements(["bar", "foo"])
5
+ class SameElementsMacro < AssertionMacro
6
+ register :same_elements
7
+
8
+ def evaluate(actual, expected)
9
+ require 'set'
10
+ same = (Set.new(expected) == Set.new(actual))
11
+ same ? pass : fail("expected elements #{expected.inspect} to match #{actual.inspect}")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module Riot
2
+ # Asserts that result's size is as expected. Expected size can be specified as
3
+ # a number or a range.
4
+ # asserts("a string") { 'washington' }.size(9..12)
5
+ # asserts("an array") { [1, 2, 3] }.size(3)
6
+ # asserts("a hash") { {:name => 'washington'} }.size(1)
7
+ class SizeMacro < AssertionMacro
8
+ register :size
9
+
10
+ def evaluate(actual, expected)
11
+ failure_message = "size of #{actual.inspect} expected to be #{expected} but is #{actual.size}"
12
+ expected === actual.size ? pass("is of size #{expected}") : fail(failure_message)
13
+ end
14
+ end
15
+ end
@@ -1,9 +1,5 @@
1
1
  module Riot
2
- RootContext = Struct.new(:setups, :teardowns) do
3
- def assertion_class
4
- Assertion
5
- end
6
- end
2
+ RootContext = Struct.new(:setups, :teardowns)
7
3
 
8
4
  class Context
9
5
  attr_reader :description
@@ -28,23 +24,12 @@ module Riot
28
24
  @contexts << self.class.new("#{@description} #{description}", self, &definition)
29
25
  end
30
26
 
31
- def extend_assertions(*extension_modules)
32
- @assertion_class = Class.new(Assertion) do
33
- include *extension_modules
34
- end
35
- end
36
-
37
27
  def run(reporter)
38
28
  reporter.describe_context(self) unless @assertions.empty?
39
29
  local_run(reporter, Situation.new)
40
30
  run_sub_contexts(reporter)
41
31
  reporter
42
32
  end
43
-
44
- def assertion_class
45
- @assertion_class ||= @parent.assertion_class
46
- end
47
-
48
33
  private
49
34
 
50
35
  def local_run(reporter, situation)
@@ -56,7 +41,14 @@ module Riot
56
41
  def run_sub_contexts(reporter) @contexts.each { |ctx| ctx.run(reporter) }; end
57
42
 
58
43
  def new_assertion(scope, what, &definition)
59
- (@assertions << assertion_class.new("#{scope} #{what}", &definition)).last
44
+ if what.kind_of?(Symbol)
45
+ definition ||= lambda { topic.send(what) }
46
+ description = "#{scope} ##{what}"
47
+ else
48
+ description = "#{scope} #{what}"
49
+ end
50
+
51
+ (@assertions << Assertion.new(description, &definition)).last
60
52
  end
61
53
  end # Context
62
54
  end # Riot
@@ -20,7 +20,7 @@ module Riot
20
20
  case code
21
21
  when :pass then
22
22
  @passes += 1
23
- pass(description)
23
+ pass(description, result)
24
24
  when :fail then
25
25
  @failures += 1
26
26
  fail(description, result)
@@ -36,24 +36,25 @@ module Riot
36
36
  end # Reporter
37
37
 
38
38
  class IOReporter < Reporter
39
- attr_reader :writer
40
39
  def initialize(writer=STDOUT)
41
40
  super()
42
41
  @writer = writer
43
42
  end
44
- def say(message) writer.puts(message); end
43
+ def puts(message) @writer.puts(message); end
44
+ def print(message) @writer.print(message); end
45
45
 
46
46
  def results(time_taken)
47
47
  values = [passes, failures, errors, ("%0.6f" % time_taken)]
48
- say "\n%d passes, %d failures, %d errors in %s seconds" % values
48
+ puts "\n%d passes, %d failures, %d errors in %s seconds" % values
49
49
  end
50
50
 
51
51
  def format_error(e)
52
- format = " #{e.class.name} occured"
53
- format += "\n#{e.to_s}\n"
54
- e.backtrace.each { |line| format += "\n at #{line}" }
52
+ format = []
53
+ format << " #{e.class.name} occurred"
54
+ format << "#{e.to_s}"
55
+ e.backtrace.each { |line| format << " at #{line}" }
55
56
 
56
- format
57
+ format.join("\n")
57
58
  end
58
59
 
59
60
  begin
@@ -71,46 +72,49 @@ module Riot
71
72
  class StoryReporter < IOReporter
72
73
  def describe_context(context)
73
74
  super
74
- say context.description
75
+ puts context.description
75
76
  end
76
- def pass(description) say " + " + green(description); end
77
- def fail(description, message) say " - " + yellow("#{description}: #{message}"); end
78
- def error(description, e) say " ! " + red("#{description}: #{e.message}"); end
77
+ def pass(description, message) puts " + " + green("#{description} #{message}".strip); end
78
+ def fail(description, message) puts " - " + yellow("#{description}: #{message}"); end
79
+ def error(description, e) puts " ! " + red("#{description}: #{e.message}"); end
79
80
  end
80
81
 
81
82
  class VerboseStoryReporter < StoryReporter
82
83
  def error(description, e)
83
- super(description, e)
84
- say red(format_error(e))
84
+ super
85
+ puts red(format_error(e))
85
86
  end
86
87
  end
87
88
 
88
89
  class DotMatrixReporter < IOReporter
89
- def pass(description); writer.write green("."); end
90
-
91
90
  def initialize(writer=STDOUT)
92
91
  super
93
92
  @details = []
94
93
  end
94
+
95
+ def pass(description, message)
96
+ print green(".")
97
+ end
98
+
95
99
  def fail(description, message)
96
- writer.write yellow("F")
100
+ print yellow("F")
97
101
  @details << "FAILURE - #{current_context.description} #{description} => #{message}"
98
102
  end
99
103
 
100
104
  def error(description, e)
101
- writer.write red("E")
105
+ print red("E")
102
106
  @details << "ERROR - #{current_context.description} #{description} => #{format_error(e)}"
103
107
  end
104
108
 
105
109
  def results(time_taken)
106
- say "\n"
107
- @details.each { |detail| say detail }
110
+ puts "\n" unless @details.empty?
111
+ @details.each { |detail| puts detail }
108
112
  super
109
113
  end
110
114
  end
111
115
 
112
116
  class SilentReporter < Reporter
113
- def pass(description); end
117
+ def pass(description, message); end
114
118
  def fail(description, message); end
115
119
  def error(description, e); end
116
120
  def results(time_taken); end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{riot}
8
- s.version = "0.10.9"
8
+ s.version = "0.10.10"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Justin 'Gus' Knowlden"]
12
- s.date = %q{2009-12-15}
12
+ s.date = %q{2009-12-29}
13
13
  s.description = %q{An extremely fast, expressive, and context-driven unit-testing framework. A replacement for all other testing frameworks. Protest the slow test.}
14
14
  s.email = %q{gus@gusg.us}
15
15
  s.extra_rdoc_files = [
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
  ]
18
18
  s.files = [
19
19
  ".gitignore",
20
+ "CHANGELOG",
20
21
  "MIT-LICENSE",
21
22
  "README.markdown",
22
23
  "Rakefile",
@@ -24,7 +25,20 @@ Gem::Specification.new do |s|
24
25
  "VERSION",
25
26
  "lib/riot.rb",
26
27
  "lib/riot/assertion.rb",
27
- "lib/riot/assertion_macros.rb",
28
+ "lib/riot/assertion_macro.rb",
29
+ "lib/riot/assertion_macros/any.rb",
30
+ "lib/riot/assertion_macros/assigns.rb",
31
+ "lib/riot/assertion_macros/empty.rb",
32
+ "lib/riot/assertion_macros/equals.rb",
33
+ "lib/riot/assertion_macros/exists.rb",
34
+ "lib/riot/assertion_macros/includes.rb",
35
+ "lib/riot/assertion_macros/kind_of.rb",
36
+ "lib/riot/assertion_macros/matches.rb",
37
+ "lib/riot/assertion_macros/nil.rb",
38
+ "lib/riot/assertion_macros/raises.rb",
39
+ "lib/riot/assertion_macros/respond_to.rb",
40
+ "lib/riot/assertion_macros/same_elements.rb",
41
+ "lib/riot/assertion_macros/size.rb",
28
42
  "lib/riot/context.rb",
29
43
  "lib/riot/reporter.rb",
30
44
  "lib/riot/runnable.rb",
@@ -7,12 +7,12 @@ context "An any assertion macro" do
7
7
  end
8
8
  end
9
9
 
10
- assertion_test_passes("when an array has items") { assert_any([1]) }
10
+ assertion_test_passes("when an array has items", "is not empty") { assert_any([1]) }
11
11
  assertion_test_fails("when an array is empty", "expected [] to have items") do
12
12
  assert_any([])
13
13
  end
14
14
 
15
- assertion_test_passes("when a hash has items") { assert_any({:name => 'washington'}) }
15
+ assertion_test_passes("when a hash has items", "is not empty") { assert_any({:name => 'washington'}) }
16
16
  assertion_test_fails("when a hash is empty", "expected {} to have items") do
17
17
  assert_any({})
18
18
  end
@@ -1,6 +1,6 @@
1
1
  require 'teststrap'
2
2
 
3
- # Using == to verify the tes because this is the test for :equals itself. Look at assertion_test_passes
3
+ # Using == to verify the test because this is the test for :equals itself. Look at assertion_test_passes
4
4
  # and assertion_test_fails for testing other macros.
5
5
 
6
6
  context "An equals assertion macro" do
@@ -9,7 +9,7 @@ context "An equals assertion macro" do
9
9
  end
10
10
 
11
11
  asserts(":pass when expectation met") do
12
- topic.equals("foo").run(Riot::Situation.new) == [:pass]
12
+ topic.equals("foo").run(Riot::Situation.new) == [:pass, %Q{is equal to "foo"}]
13
13
  end
14
14
 
15
15
  context "that is failing" do
@@ -25,7 +25,7 @@ context "An equals assertion macro" do
25
25
  end
26
26
 
27
27
  asserts(":pass when in expected range") do
28
- topic.equals(30000..32000).run(Riot::Situation.new) == [:pass]
28
+ topic.equals(30000..32000).run(Riot::Situation.new) == [:pass, "is equal to 30000..32000"]
29
29
  end
30
30
 
31
31
  context "when not in expected range" do
@@ -39,7 +39,7 @@ context "An equals assertion macro" do
39
39
  context "with block as the expectation" do
40
40
  asserts(":pass when block expectation met") do
41
41
  topic.equals { "foo" }.run(Riot::Situation.new)
42
- end.equals([:pass])
42
+ end.equals([:pass, %Q{is equal to "foo"}])
43
43
 
44
44
  asserts(":fail with message when block expectation not met") do
45
45
  topic.equals { "bar" }.run(Riot::Situation.new)
@@ -5,11 +5,11 @@ context "An exists assertion macro" do
5
5
 
6
6
  asserts(":pass when result has a value") do
7
7
  Riot::Assertion.new("foo") { "foo" }.exists.run(topic)
8
- end.equals([:pass])
8
+ end.equals([:pass, "is not nil"])
9
9
 
10
10
  asserts(":pass because empty string is considered a value") do
11
11
  Riot::Assertion.new("foo") { "" }.exists.run(topic)
12
- end.equals([:pass])
12
+ end.equals([:pass, "is not nil"])
13
13
 
14
14
  asserts(":fail with message when value is nil") do
15
15
  Riot::Assertion.new("foo") { nil }.exists.run(topic)
@@ -5,7 +5,7 @@ context "An includes assertion macro" do
5
5
  Riot::Assertion.new("an array") { [1, 6, 42, 7] }
6
6
  end
7
7
 
8
- assertion_test_passes("when array includes 42") { topic.includes(42) }
8
+ assertion_test_passes("when array includes 42", "includes 42") { topic.includes(42) }
9
9
 
10
10
  assertion_test_fails("when 99 not included in array", "expected [1, 6, 42, 7] to include 99") do
11
11
  topic.includes(99)
@@ -5,7 +5,7 @@ context "A kind_of assertion macro" do
5
5
 
6
6
  asserts ":pass when specific result is a kind of String" do
7
7
  Riot::Assertion.new("foo") { "a" }.kind_of(String).run(topic)
8
- end.equals([:pass])
8
+ end.equals([:pass, %Q{is a kind of String}])
9
9
 
10
10
  asserts ":fail when not a kind of String" do
11
11
  Riot::Assertion.new("foo") { 0 }.kind_of(String).run(topic)
@@ -3,7 +3,7 @@ require 'teststrap'
3
3
  context "A matching assertion macro" do
4
4
  setup { Riot::Assertion.new("foo") { "abc" } }
5
5
 
6
- assertion_test_passes("when expression matches actual") { topic.matches(/abc/) }
6
+ assertion_test_passes("when expression matches actual", %Q{matches /abc/}) { topic.matches(/abc/) }
7
7
 
8
8
  assertion_test_fails("when expression fails to match", "expected /abcd/ to match \"abc\"") do
9
9
  topic.matches(/abcd/)
@@ -5,7 +5,7 @@ context "A nil assertion macro" do
5
5
 
6
6
  asserts(":pass when result is nil") do
7
7
  Riot::Assertion.new("foo") { nil }.nil.run(topic)
8
- end.equals([:pass])
8
+ end.equals([:pass, "is nil"])
9
9
 
10
10
  asserts(":fail with message") do
11
11
  Riot::Assertion.new("foo") { "a" }.nil.run(topic)
@@ -3,7 +3,7 @@ require 'teststrap'
3
3
  class Whoops < Exception; end
4
4
 
5
5
  context "A raises assertion macro" do
6
- assertion_test_passes("when expected exception is raised") do
6
+ assertion_test_passes("when expected exception is raised", "raises Whoops") do
7
7
  Riot::Assertion.new("foo") { raise Whoops }.raises(Whoops)
8
8
  end
9
9
 
@@ -15,7 +15,7 @@ context "A raises assertion macro" do
15
15
  assertion = Riot::Assertion.new("foo") { "barf" }.raises(Whoops)
16
16
  end
17
17
 
18
- assertion_test_passes("when provided message equals expected message") do
18
+ assertion_test_passes("when provided message equals expected message", %Q{raises Whoops with message "Mom"}) do
19
19
  Riot::Assertion.new("foo") { raise Whoops, "Mom" }.raises(Whoops, "Mom")
20
20
  end
21
21
 
@@ -23,7 +23,7 @@ context "A raises assertion macro" do
23
23
  Riot::Assertion.new("foo") { raise Whoops, "Dad" }.raises(Whoops, "Mom")
24
24
  end
25
25
 
26
- assertion_test_passes("when provided message matches expected message") do
26
+ assertion_test_passes("when provided message matches expected message", %Q{raises Whoops with message /Mom/}) do
27
27
  Riot::Assertion.new("foo") { raise Whoops, "Mom" }.raises(Whoops, /Mom/)
28
28
  end
29
29
 
@@ -3,7 +3,7 @@ require 'teststrap'
3
3
  context "A respond_to assertion macro" do
4
4
  setup { Riot::Assertion.new("foo") { "bar" } }
5
5
 
6
- assertion_test_passes("when method is defined") { topic.respond_to(:each_byte) }
6
+ assertion_test_passes("when method is defined", "responds to :each_byte") { topic.respond_to(:each_byte) }
7
7
 
8
8
  assertion_test_fails("when method not defined", "expected method :goofballs is not defined") do
9
9
  topic.respond_to(:goofballs)
@@ -7,8 +7,13 @@ context "A size assertion macro" do
7
7
  end
8
8
  end
9
9
 
10
- assertion_test_passes("when string's size is as expected") { assert_size("washington", 10) }
11
- assertion_test_passes("when string's size is in given range") { assert_size("washington", 9..12) }
10
+ assertion_test_passes("when string's size is as expected", "is of size 10") do
11
+ assert_size("washington", 10)
12
+ end
13
+ assertion_test_passes("when string's size is in given range", "is of size 9..12") do
14
+ assert_size("washington", 9..12)
15
+ end
16
+
12
17
  assertion_test_fails("when string's size is not as expected", "size of \"washington\" expected to be 11 but is 10") do
13
18
  assert_size("washington", 11)
14
19
  end
@@ -16,8 +21,10 @@ context "A size assertion macro" do
16
21
  assert_size("washington", 11..13)
17
22
  end
18
23
 
19
- assertion_test_passes("when an array's size is as expected") { assert_size([1, 2, 3], 3) }
20
- assertion_test_passes("when an array's size is in given range") { assert_size([1, 2, 3], 3..4) }
24
+ assertion_test_passes("when an array's size is as expected", "is of size 3") { assert_size([1, 2, 3], 3) }
25
+ assertion_test_passes("when an array's size is in given range", "is of size 3..4") do
26
+ assert_size([1, 2, 3], 3..4)
27
+ end
21
28
  assertion_test_fails("when an array's size is not as expected", "size of [1, 2, 3] expected to be 2 but is 3") do
22
29
  assert_size([1, 2, 3], 2)
23
30
  end
@@ -25,8 +32,12 @@ context "A size assertion macro" do
25
32
  assert_size([1, 2, 3], 4..6)
26
33
  end
27
34
 
28
- assertion_test_passes("when a hash size is as expected") { assert_size({:name => 'washington'}, 1) }
29
- assertion_test_passes("when a hash size is in range") { assert_size({:name => 'washington'}, 1...3) }
35
+ assertion_test_passes("when a hash size is as expected", "is of size 1") do
36
+ assert_size({:name => 'washington'}, 1)
37
+ end
38
+ assertion_test_passes("when a hash size is in range", "is of size 1...3") do
39
+ assert_size({:name => 'washington'}, 1...3)
40
+ end
30
41
  assertion_test_fails("when a hash size is not as expected", "size of {} expected to be 2 but is 0") do
31
42
  assert_size({}, 2)
32
43
  end