riot 0.9.12 → 0.10.0

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 (40) hide show
  1. data/.gitignore +1 -0
  2. data/README.markdown +37 -45
  3. data/VERSION +1 -1
  4. data/lib/riot.rb +27 -18
  5. data/lib/riot/assertion_macros.rb +63 -53
  6. data/lib/riot/context.rb +26 -36
  7. data/lib/riot/reporter.rb +77 -0
  8. data/lib/riot/runnable.rb +50 -0
  9. data/lib/riot/situation.rb +6 -3
  10. data/riot.gemspec +30 -21
  11. data/test/assertion_macros/assigns_test.rb +24 -0
  12. data/test/assertion_macros/equals_test.rb +18 -0
  13. data/test/assertion_macros/exists_test.rb +17 -0
  14. data/test/assertion_macros/kind_of_test.rb +17 -0
  15. data/test/assertion_macros/matching_test.rb +12 -0
  16. data/test/assertion_macros/nil_test.rb +13 -0
  17. data/test/assertion_macros/raises_test.rb +33 -0
  18. data/test/assertion_macros/respond_to_test.rb +12 -0
  19. data/test/assertion_macros/same_elements_test.rb +17 -0
  20. data/test/assertion_test.rb +25 -22
  21. data/test/benchmark/riot_vs_minitest.rb +8 -8
  22. data/test/benchmark/same_elements_vs_set.rb +41 -0
  23. data/test/benchmark/simple_context_and_assertions.rb +8 -8
  24. data/test/context_test.rb +68 -83
  25. data/test/report_test.rb +44 -0
  26. data/test/setup_test.rb +17 -0
  27. data/test/situation_test.rb +16 -0
  28. data/test/teststrap.rb +31 -0
  29. metadata +30 -21
  30. data/lib/riot/assertion.rb +0 -37
  31. data/lib/riot/errors.rb +0 -15
  32. data/lib/riot/report.rb +0 -82
  33. data/test/assertion_macros/assertion_macro_assigns_test.rb +0 -40
  34. data/test/assertion_macros/assertion_macro_equals_test.rb +0 -13
  35. data/test/assertion_macros/assertion_macro_exists_test.rb +0 -17
  36. data/test/assertion_macros/assertion_macro_kind_of_test.rb +0 -13
  37. data/test/assertion_macros/assertion_macro_matching_test.rb +0 -17
  38. data/test/assertion_macros/assertion_macro_nil_test.rb +0 -13
  39. data/test/assertion_macros/assertion_macro_raises_test.rb +0 -43
  40. data/test/assertion_macros/assertion_macro_respond_to_test.rb +0 -16
@@ -0,0 +1,77 @@
1
+ module Riot
2
+ class Reporter
3
+ attr_accessor :passes, :failures, :errors
4
+ def initialize
5
+ @passes = @failures = @errors = 0
6
+ end
7
+
8
+ def summarize(&block)
9
+ started = Time.now
10
+ yield
11
+ ensure
12
+ results(Time.now - started)
13
+ end
14
+
15
+ def describe_context(msg); end
16
+
17
+ def report(description, response)
18
+ code, result = *response
19
+ case code
20
+ when :pass then
21
+ @passes += 1
22
+ pass(description)
23
+ when :fail then
24
+ @failures += 1
25
+ fail(description, result)
26
+ when :error then
27
+ @errors += 1
28
+ error(description, result)
29
+ end
30
+ end
31
+ end # Reporter
32
+
33
+ class IOReporter < Reporter
34
+ def initialize(writer=nil)
35
+ super()
36
+ @writer = writer || STDOUT
37
+ end
38
+ def say(message) @writer.puts(message); end
39
+
40
+ def results(time_taken)
41
+ values = [@passes, @failures, @errors, ("%0.6f" % time_taken)]
42
+ say "\n%d passes, %d failures, %d errors in %s seconds" % values
43
+ end
44
+ end
45
+
46
+ class StoryReporter < IOReporter
47
+ def describe_context(description) say description; end
48
+ def pass(description) say " + " + description.green; end
49
+ def fail(description, message) say " - " + "#{description}: #{message}".yellow; end
50
+ def error(description, e) say " ! " + "#{description}: #{e.message}".red; end
51
+ end
52
+
53
+ class DotMatrixReporter < IOReporter
54
+ def pass(description); @writer.write ".".green; end
55
+ def fail(description, message); @writer.write "F".yellow; end
56
+ def error(description, e); @writer.write "E".red; end
57
+ end
58
+
59
+ class SilentReporter < Reporter
60
+ def pass(description); end
61
+ def fail(description, message); end
62
+ def error(description, e); end
63
+ def results(time_taken); end
64
+ end
65
+ end # Riot
66
+
67
+ begin
68
+ raise LoadError if ENV["TM_MODE"]
69
+ require 'rubygems'
70
+ require 'colorize'
71
+ rescue LoadError
72
+ class ::String
73
+ def green; self; end
74
+ alias :red :green
75
+ alias :yellow :green
76
+ end
77
+ end
@@ -0,0 +1,50 @@
1
+ module Riot
2
+ class RunnableBlock
3
+ def initialize(description, &definition)
4
+ @description, @definition = description, definition
5
+ end
6
+
7
+ def to_s
8
+ @description
9
+ end
10
+ end # RunnableBlock
11
+
12
+ class Setup < RunnableBlock
13
+ def initialize(&definition)
14
+ super("setup", &definition)
15
+ end
16
+
17
+ def run(situation)
18
+ situation.setup(&@definition)
19
+ [:setup]
20
+ end
21
+ end # Setup
22
+
23
+ class Assertion < RunnableBlock
24
+ def self.pass() [:pass]; end
25
+ def self.fail(message) [:fail, message]; end
26
+ def self.error(e) [:error, e]; end
27
+
28
+ def run(situation)
29
+ process_macro(situation, false) do |actual|
30
+ actual ? Assertion.pass : Assertion.fail("Expected non-false but got #{actual.inspect} instead")
31
+ end
32
+ end
33
+
34
+ def self.assertion(name, expect_exception=false, &assertion_block)
35
+ define_method(name) do |*expectings|
36
+ (class << self; self; end).send(:define_method, :run) do |situation|
37
+ process_macro(situation, expect_exception) { |actual| assertion_block.call(actual, *expectings) }
38
+ end # redefine run method when the assertion is called
39
+ self
40
+ end # define_method for assertion
41
+ end
42
+ private
43
+ def process_macro(situation, expect_exception)
44
+ actual = situation.evaluate(&@definition)
45
+ yield(expect_exception ? nil : actual)
46
+ rescue Exception => e
47
+ expect_exception ? yield(e) : Assertion.error(e)
48
+ end
49
+ end # Assertion
50
+ end # Riot
@@ -1,9 +1,12 @@
1
1
  module Riot
2
2
  class Situation
3
3
  attr_accessor :topic
4
+ def setup(&block)
5
+ @topic = self.instance_eval(&block)
6
+ end
4
7
 
5
- def fail(message)
6
- raise Failure.new(message)
8
+ def evaluate(&block)
9
+ self.instance_eval(&block)
7
10
  end
8
11
  end # Situation
9
- end # Riot
12
+ end # Riot
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{riot}
8
- s.version = "0.9.12"
8
+ s.version = "0.10.0"
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-10-22}
12
+ s.date = %q{2009-11-21}
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 = [
@@ -22,25 +22,29 @@ Gem::Specification.new do |s|
22
22
  "Rakefile",
23
23
  "VERSION",
24
24
  "lib/riot.rb",
25
- "lib/riot/assertion.rb",
26
25
  "lib/riot/assertion_macros.rb",
27
26
  "lib/riot/context.rb",
28
- "lib/riot/errors.rb",
29
- "lib/riot/report.rb",
27
+ "lib/riot/reporter.rb",
28
+ "lib/riot/runnable.rb",
30
29
  "lib/riot/situation.rb",
31
30
  "riot.gemspec",
32
- "test/assertion_macros/assertion_macro_assigns_test.rb",
33
- "test/assertion_macros/assertion_macro_equals_test.rb",
34
- "test/assertion_macros/assertion_macro_exists_test.rb",
35
- "test/assertion_macros/assertion_macro_kind_of_test.rb",
36
- "test/assertion_macros/assertion_macro_matching_test.rb",
37
- "test/assertion_macros/assertion_macro_nil_test.rb",
38
- "test/assertion_macros/assertion_macro_raises_test.rb",
39
- "test/assertion_macros/assertion_macro_respond_to_test.rb",
31
+ "test/assertion_macros/assigns_test.rb",
32
+ "test/assertion_macros/equals_test.rb",
33
+ "test/assertion_macros/exists_test.rb",
34
+ "test/assertion_macros/kind_of_test.rb",
35
+ "test/assertion_macros/matching_test.rb",
36
+ "test/assertion_macros/nil_test.rb",
37
+ "test/assertion_macros/raises_test.rb",
38
+ "test/assertion_macros/respond_to_test.rb",
39
+ "test/assertion_macros/same_elements_test.rb",
40
40
  "test/assertion_test.rb",
41
41
  "test/benchmark/riot_vs_minitest.rb",
42
+ "test/benchmark/same_elements_vs_set.rb",
42
43
  "test/benchmark/simple_context_and_assertions.rb",
43
44
  "test/context_test.rb",
45
+ "test/report_test.rb",
46
+ "test/setup_test.rb",
47
+ "test/situation_test.rb",
44
48
  "test/teststrap.rb"
45
49
  ]
46
50
  s.homepage = %q{http://github.com/thumblemonks/riot}
@@ -49,18 +53,23 @@ Gem::Specification.new do |s|
49
53
  s.rubygems_version = %q{1.3.5}
50
54
  s.summary = %q{An extremely fast, expressive, and context-driven unit-testing framework. Protest the slow test.}
51
55
  s.test_files = [
52
- "test/assertion_macros/assertion_macro_assigns_test.rb",
53
- "test/assertion_macros/assertion_macro_equals_test.rb",
54
- "test/assertion_macros/assertion_macro_exists_test.rb",
55
- "test/assertion_macros/assertion_macro_kind_of_test.rb",
56
- "test/assertion_macros/assertion_macro_matching_test.rb",
57
- "test/assertion_macros/assertion_macro_nil_test.rb",
58
- "test/assertion_macros/assertion_macro_raises_test.rb",
59
- "test/assertion_macros/assertion_macro_respond_to_test.rb",
56
+ "test/assertion_macros/assigns_test.rb",
57
+ "test/assertion_macros/equals_test.rb",
58
+ "test/assertion_macros/exists_test.rb",
59
+ "test/assertion_macros/kind_of_test.rb",
60
+ "test/assertion_macros/matching_test.rb",
61
+ "test/assertion_macros/nil_test.rb",
62
+ "test/assertion_macros/raises_test.rb",
63
+ "test/assertion_macros/respond_to_test.rb",
64
+ "test/assertion_macros/same_elements_test.rb",
60
65
  "test/assertion_test.rb",
61
66
  "test/benchmark/riot_vs_minitest.rb",
67
+ "test/benchmark/same_elements_vs_set.rb",
62
68
  "test/benchmark/simple_context_and_assertions.rb",
63
69
  "test/context_test.rb",
70
+ "test/report_test.rb",
71
+ "test/setup_test.rb",
72
+ "test/situation_test.rb",
64
73
  "test/teststrap.rb"
65
74
  ]
66
75
 
@@ -0,0 +1,24 @@
1
+ require 'teststrap'
2
+
3
+ context "An assigns assertion macro" do
4
+ setup do
5
+ item = Object.new
6
+ item.instance_eval { @foo = 1; @bar; @nil_val = nil }
7
+ Riot::Assertion.new("test") { item }
8
+ end
9
+
10
+ assertion_test_passes("when foo is defined") { topic.assigns(:foo) }
11
+ assertion_test_passes("when foo is defined with expected value") { topic.assigns(:foo, 1) }
12
+
13
+ assertion_test_fails("when foo does not match expectation", "expected @foo to be equal to 2, not 1") do
14
+ topic.assigns(:foo, 2)
15
+ end
16
+
17
+ assertion_test_fails("when bar is not define", "expected @bar to be assigned a value") do
18
+ topic.assigns(:bar)
19
+ end
20
+
21
+ assertion_test_fails("when var assigned nil value", "expected @nil_val to be assigned a value") do
22
+ topic.assigns(:nil_val)
23
+ end
24
+ end # An assigns assertion macro
@@ -0,0 +1,18 @@
1
+ require 'teststrap'
2
+
3
+ context "An equals assertion macro" do
4
+ setup do
5
+ Riot::Assertion.new("blue") { "foo" }
6
+ end
7
+
8
+ asserts(":pass when expectation met") do
9
+ topic.equals("foo").run(Riot::Situation.new) == [:pass]
10
+ end
11
+
12
+ context "that is failing" do
13
+ setup { topic.equals("bar").run(Riot::Situation.new) }
14
+
15
+ asserts(":fail") { topic.first == :fail }
16
+ asserts("message") { topic.last == %Q{expected "foo" to equal "bar"} }
17
+ end # that is failing
18
+ end # An equals assertion macro
@@ -0,0 +1,17 @@
1
+ require 'teststrap'
2
+
3
+ context "An exists assertion macro" do
4
+ setup { Riot::Situation.new }
5
+
6
+ asserts(":pass when result has a value") do
7
+ Riot::Assertion.new("foo") { "foo" }.exists.run(topic)
8
+ end.equals([:pass])
9
+
10
+ asserts(":pass because empty string is considered a value") do
11
+ Riot::Assertion.new("foo") { "" }.exists.run(topic)
12
+ end.equals([:pass])
13
+
14
+ asserts(":fail with message when value is nil") do
15
+ Riot::Assertion.new("foo") { nil }.exists.run(topic)
16
+ end.equals([:fail, "expected a non-nil value"])
17
+ end # An exists assertion macro
@@ -0,0 +1,17 @@
1
+ require 'teststrap'
2
+
3
+ context "A kind_of assertion macro" do
4
+ setup { Riot::Situation.new }
5
+
6
+ asserts ":pass when specific result is a kind of String" do
7
+ Riot::Assertion.new("foo") { "a" }.kind_of(String).run(topic)
8
+ end.equals([:pass])
9
+
10
+ asserts ":fail when not a kind of String" do
11
+ Riot::Assertion.new("foo") { 0 }.kind_of(String).run(topic)
12
+ end.equals([:fail, %Q{expected kind of String, not 0}])
13
+
14
+ asserts ":fail when nil" do
15
+ Riot::Assertion.new("foo") { }.kind_of(String).run(topic)
16
+ end.equals([:fail, %Q{expected kind of String, not nil}])
17
+ end # A kind_of assertion macro
@@ -0,0 +1,12 @@
1
+ require 'teststrap'
2
+
3
+ context "A matching assertion macro" do
4
+ setup { Riot::Assertion.new("foo") { "abc" } }
5
+
6
+ assertion_test_passes("when expression matches actual") { topic.matches(/abc/) }
7
+
8
+ assertion_test_fails("when expression fails to match", "expected /abcd/ to match \"abc\"") do
9
+ topic.matches(/abcd/)
10
+ end
11
+
12
+ end # A matching assertion macro
@@ -0,0 +1,13 @@
1
+ require 'teststrap'
2
+
3
+ context "A nil assertion macro" do
4
+ setup { Riot::Situation.new }
5
+
6
+ asserts(":pass when result is nil") do
7
+ Riot::Assertion.new("foo") { nil }.nil.run(topic)
8
+ end.equals([:pass])
9
+
10
+ asserts(":fail with message") do
11
+ Riot::Assertion.new("foo") { "a" }.nil.run(topic)
12
+ end.equals([:fail, %Q{expected nil, not "a"}])
13
+ end # A nil assertion macro
@@ -0,0 +1,33 @@
1
+ require 'teststrap'
2
+
3
+ class Whoops < Exception; end
4
+
5
+ context "A raises assertion macro" do
6
+ assertion_test_passes("when expected exception is raised") do
7
+ Riot::Assertion.new("foo") { raise Whoops }.raises(Whoops)
8
+ end
9
+
10
+ assertion_test_fails("when unexpected exception is raised", "should have raised Exception, not Whoops") do
11
+ Riot::Assertion.new("foo") { raise Whoops }.raises(Exception)
12
+ end
13
+
14
+ assertion_test_fails("when nothing was raised", "should have raised Whoops, but raised nothing") do
15
+ assertion = Riot::Assertion.new("foo") { "barf" }.raises(Whoops)
16
+ end
17
+
18
+ assertion_test_passes("when provided message equals expected message") do
19
+ Riot::Assertion.new("foo") { raise Whoops, "Mom" }.raises(Whoops, "Mom")
20
+ end
21
+
22
+ assertion_test_fails("when messages aren't equal", %Q{expected "Mom" for message, not "Dad"}) do
23
+ Riot::Assertion.new("foo") { raise Whoops, "Dad" }.raises(Whoops, "Mom")
24
+ end
25
+
26
+ assertion_test_passes("when provided message matches expected message") do
27
+ Riot::Assertion.new("foo") { raise Whoops, "Mom" }.raises(Whoops, /Mom/)
28
+ end
29
+
30
+ assertion_test_fails("when messages don't match", %Q{expected /Mom/ for message, not "Dad"}) do
31
+ Riot::Assertion.new("foo") { raise Whoops, "Dad" }.raises(Whoops, /Mom/)
32
+ end
33
+ end # A raises assertion macro
@@ -0,0 +1,12 @@
1
+ require 'teststrap'
2
+
3
+ context "A respond_to assertion macro" do
4
+ setup { Riot::Assertion.new("foo") { "bar" } }
5
+
6
+ assertion_test_passes("when method is defined") { topic.respond_to(:each_byte) }
7
+
8
+ assertion_test_fails("when method not defined", "expected method :goofballs is not defined") do
9
+ topic.respond_to(:goofballs)
10
+ end
11
+
12
+ end # A respond_to assertion macro
@@ -0,0 +1,17 @@
1
+ require 'teststrap'
2
+
3
+ context "A same_elements assertion macro" do
4
+ setup { Riot::Assertion.new("test") { ["foo", "bar", 69] } }
5
+
6
+ assertion_test_passes(%Q{when [69, "foo", "bar"] are returned}) do
7
+ topic.same_elements([69, "foo", "bar"])
8
+ end
9
+
10
+ assertion_test_passes(%Q{when [69, "foo", "bar"] are returned in any order}) do
11
+ topic.same_elements(["foo", "bar", 69])
12
+ end
13
+
14
+ assertion_test_fails("when elements do not match", %Q{expected elements ["foo", "bar", 96] to match ["foo", "bar", 69]}) do
15
+ topic.same_elements(["foo", "bar", 96])
16
+ end
17
+ end # A same_elements assertion macro
@@ -1,31 +1,34 @@
1
1
  require 'teststrap'
2
2
 
3
- context "basic assertion" do
4
- setup { Riot::Situation.new }
3
+ context "An assertion block" do
4
+ context "that is passing" do
5
+ setup { Riot::Assertion.new("foo") { true } }
6
+ asserts("to_s") { topic.to_s == "foo" }
5
7
 
6
- should "have a description" do
7
- Riot::Assertion.new("i will pass", topic).to_s
8
- end.equals("i will pass")
9
-
10
- asserts "pass? is true when assertion passed" do
11
- Riot::Assertion.new("i will pass", topic) { true }.passed?
12
- end
8
+ asserts(":pass is returned when evaluated") do
9
+ topic.run(Riot::Situation.new) == [:pass]
10
+ end
11
+ end # that is passing
13
12
 
14
- asserts "failure? is true when assertion does not pass" do
15
- Riot::Assertion.new("i will pass", topic) { false }.failed?
16
- end
13
+ context "that is failing" do
14
+ setup { Riot::Assertion.new("foo") { nil } }
15
+ asserts("to_s") { topic.to_s == "foo" }
17
16
 
18
- asserts "error? is true when an unexpected Exception is raised" do
19
- Riot::Assertion.new("error", topic) { raise Exception, "blah" }.errored?
20
- end
17
+ asserts(":fail and message are evaluated") do
18
+ topic.run(Riot::Situation.new) == [:fail, "Expected non-false but got nil instead"]
19
+ end
20
+ end # that is failing
21
21
 
22
- context "that fails while executing a test" do
22
+ context "that is erroring" do
23
23
  setup do
24
- fake_situation = Riot::Situation.new
25
- Riot::Assertion.new("error", fake_situation) { fail("I'm a bum") }
24
+ @exception = exception = Exception.new("blah")
25
+ Riot::Assertion.new("baz") { raise exception }
26
26
  end
27
27
 
28
- should("be considered a failing assertion") { topic.failed? }
29
- should("use failed message in description") { topic.result.message }.matches(/I'm a bum/)
30
- end # that fails while executing test
31
- end # basic assertion
28
+ asserts("to_s") { topic.to_s == "baz" }
29
+
30
+ asserts(":error and exception are evaluated") do
31
+ topic.run(Riot::Situation.new) == [:error, @exception]
32
+ end
33
+ end # that is erroring
34
+ end # An assertion block