riot 0.9.12 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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