riot 0.11.4 → 0.12.0.pre

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 (61) hide show
  1. data/CHANGELOG +6 -0
  2. data/VERSION +1 -1
  3. data/lib/riot/assertion.rb +10 -5
  4. data/lib/riot/assertion_macro.rb +10 -0
  5. data/lib/riot/assertion_macros/any.rb +16 -2
  6. data/lib/riot/assertion_macros/assigns.rb +42 -16
  7. data/lib/riot/assertion_macros/empty.rb +13 -2
  8. data/lib/riot/assertion_macros/equals.rb +17 -2
  9. data/lib/riot/assertion_macros/equivalent_to.rb +15 -1
  10. data/lib/riot/assertion_macros/exists.rb +13 -1
  11. data/lib/riot/assertion_macros/includes.rb +16 -0
  12. data/lib/riot/assertion_macros/kind_of.rb +13 -0
  13. data/lib/riot/assertion_macros/matches.rb +14 -0
  14. data/lib/riot/assertion_macros/nil.rb +10 -0
  15. data/lib/riot/assertion_macros/not_borat.rb +10 -0
  16. data/lib/riot/assertion_macros/raises.rb +28 -0
  17. data/lib/riot/assertion_macros/respond_to.rb +14 -0
  18. data/lib/riot/assertion_macros/same_elements.rb +13 -2
  19. data/lib/riot/assertion_macros/size.rb +12 -0
  20. data/lib/riot/context.rb +4 -126
  21. data/lib/riot/context_helpers.rb +132 -0
  22. data/lib/riot/context_options.rb +24 -0
  23. data/riot.gemspec +46 -27
  24. data/test.watchr +70 -0
  25. data/test/core/assertion_macros/any_test.rb +36 -4
  26. data/test/core/assertion_macros/assigns_test.rb +28 -0
  27. data/test/core/assertion_macros/empty_test.rb +35 -7
  28. data/test/core/assertion_macros/equals_test.rb +29 -0
  29. data/test/core/assertion_macros/equivalent_to_test.rb +36 -17
  30. data/test/core/assertion_macros/exists_test.rb +25 -4
  31. data/test/core/assertion_macros/includes_test.rb +12 -0
  32. data/test/core/assertion_macros/kind_of_test.rb +15 -0
  33. data/test/core/assertion_macros/matches_test.rb +49 -0
  34. data/test/core/assertion_macros/nil_test.rb +10 -8
  35. data/test/core/assertion_macros/not_borat_test.rb +14 -8
  36. data/test/core/assertion_macros/raises_test.rb +39 -6
  37. data/test/core/assertion_macros/respond_to_test.rb +18 -1
  38. data/test/core/assertion_macros/same_elements_test.rb +17 -0
  39. data/test/core/assertion_macros/size_test.rb +45 -5
  40. data/test/core/context/asserts_topic_test.rb +21 -0
  41. data/test/core/context/context_test.rb +35 -0
  42. data/test/core/{context_with_options_test.rb → context/context_with_options_test.rb} +0 -0
  43. data/test/core/context/deny_test.rb +25 -0
  44. data/test/core/context/helper_test.rb +11 -0
  45. data/test/core/context/hookup_test.rb +13 -0
  46. data/test/core/context/nested_contexts_test.rb +40 -0
  47. data/test/core/context/premium_setup_test.rb +19 -0
  48. data/test/core/context/should_test.rb +17 -0
  49. data/test/core/{using_describe_in_a_test.rb → context/using_describe_in_a_test.rb} +9 -0
  50. data/test/core/{chained_context_middleware_test.rb → middleware/chained_context_middleware_test.rb} +0 -0
  51. data/test/core/{context_middleware_test.rb → middleware/context_middleware_test.rb} +0 -0
  52. data/test/core/{assertion_macro_test.rb → runnable/assertion_macro_test.rb} +0 -0
  53. data/test/core/{assertion_test.rb → runnable/assertion_test.rb} +0 -0
  54. data/test/core/{message_test.rb → runnable/message_test.rb} +0 -0
  55. data/test/core/runnable/negative_assertion_test.rb +36 -0
  56. data/test/core/{setup_test.rb → runnable/setup_test.rb} +0 -0
  57. data/test/core/{situation_test.rb → runnable/situation_test.rb} +0 -0
  58. data/test/core/{teardown_test.rb → runnable/teardown_test.rb} +0 -0
  59. metadata +54 -32
  60. data/test/core/assertion_macros/matching_test.rb +0 -24
  61. data/test/core/context_test.rb +0 -157
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ *0.12.0.pre*
2
+
3
+ * Negative tests are finally here! Added support for `denies` and adjusted macros to care about it with `devaluate`. [jaknowlden, achiu]
4
+
5
+ denies("my name") { "Rumplestiltzkin" }.equals("Henry")
6
+
1
7
  *0.11.4*
2
8
 
3
9
  * Passing Proc's instead of lambdas to `instance_eval` to comply with ruby 1.9.2. [skade]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.4
1
+ 0.12.0.pre
@@ -8,18 +8,19 @@ module Riot
8
8
  end
9
9
  end
10
10
 
11
- def initialize(description, &definition)
12
- super
13
- @expectings, @expectation_block = [], false, nil
11
+ def initialize(description, negative=false, &definition)
12
+ super(description, &definition)
13
+ @negative = negative
14
+ @expectings, @expectation_block = [], nil
14
15
  @macro = AssertionMacro.default
15
16
  end
16
17
 
17
18
  def run(situation)
18
19
  @expectings << situation.evaluate(&@expectation_block) if @expectation_block
19
20
  actual = situation.evaluate(&definition)
20
- @macro.evaluate((@macro.expects_exception? ? nil : actual), *@expectings)
21
+ assert((@macro.expects_exception? ? nil : actual), *@expectings)
21
22
  rescue Exception => e
22
- @macro.expects_exception? ? @macro.evaluate(e, *@expectings) : @macro.error(e)
23
+ @macro.expects_exception? ? assert(e, *@expectings) : @macro.error(e)
23
24
  end
24
25
  private
25
26
  def enhance_with_macro(name, *expectings, &expectation_block)
@@ -30,5 +31,9 @@ module Riot
30
31
  self
31
32
  end
32
33
  alias :method_missing :enhance_with_macro
34
+
35
+ def assert(*arguments)
36
+ @negative ? @macro.devaluate(*arguments) : @macro.evaluate(*arguments)
37
+ end
33
38
  end # Assertion
34
39
  end # Riot
@@ -22,6 +22,10 @@ module Riot
22
22
  # def evaluate(actual)
23
23
  # actual.length == 0 ? pass : fail(expected_message(actual).to_be_empty)
24
24
  # end
25
+ #
26
+ # def devaluate(actual)
27
+ # actual.empty? ? fail(expected_message(actual).to_not_be_empty) : pass(new_message.is_empty)
28
+ # end
25
29
  # end
26
30
  #
27
31
  class AssertionMacro
@@ -55,10 +59,16 @@ module Riot
55
59
 
56
60
  def expects_exception?; self.class.expects_exception; end
57
61
 
62
+ # Supports positive assertion testing
58
63
  def evaluate(actual)
59
64
  actual ? pass : fail("Expected non-false but got #{actual.inspect} instead")
60
65
  end
61
66
 
67
+ # Supports negative/converse assertion testing
68
+ def devaluate(actual)
69
+ !actual ? pass : fail("Expected non-true but got #{actual.inspect} instead")
70
+ end
71
+
62
72
  # Messaging
63
73
 
64
74
  def new_message(*phrases) Message.new(*phrases); end
@@ -1,12 +1,26 @@
1
1
  module Riot
2
- # Asserts the result has items
2
+ # In the positive case, asserts the result has items using the +any?+ operator.
3
+ #
3
4
  # asserts("an array") { [1] }.any
4
5
  # asserts("a hash") { {:name => 'washington'} }.any
6
+ #
7
+ # In the negative case, asserts the result has no items using the +any?+ operator.
8
+ #
9
+ # denies("an empty array") { [] }.any
10
+ # denies("an empty hash") { {} }.any
5
11
  class AnyMacro < AssertionMacro
6
12
  register :any
7
13
 
8
14
  def evaluate(actual)
9
- actual.any? ? pass("is not empty") : fail(expected_message(actual).to_have_items)
15
+ any?(actual) ? pass("is not empty") : fail(expected_message(actual).to_have_items)
16
+ end
17
+
18
+ def devaluate(actual)
19
+ any?(actual) ? fail(expected_message(actual).not_to_have_elements) : pass("has elements")
20
+ end
21
+ private
22
+ def any?(object)
23
+ object.kind_of?(String) ? object.length > 0 : object.any?
10
24
  end
11
25
  end
12
26
  end
@@ -1,27 +1,53 @@
1
1
  module Riot
2
- # Asserts that an instance variable is defined for the result of the assertion. Value of instance
3
- # variable is expected to not be nil
2
+ # In the positive case, asserts that an instance variable is defined for the result of the assertion.
3
+ # Value of instance variable is expected to not be nil.
4
+ #
4
5
  # setup { User.new(:email => "foo@bar.baz") }
5
- # topic.assigns(:email)
6
+ # asserts_topic.assigns(:email)
6
7
  #
7
8
  # If a value is provided in addition to the variable name, the actual value of the instance variable
8
- # must equal the expected value
9
+ # must equal the expected value.
10
+ #
9
11
  # setup { User.new(:email => "foo@bar.baz") }
10
- # topic.assigns(:email, "foo@bar.baz")
12
+ # asserts_topic.assigns(:email, "foo@bar.baz")
13
+ #
14
+ # In the negative case, asserts that an instance variables *is not* defined or has a nil value. If a value
15
+ # is provided in addition to the name, then ensure that the actual value does not equal the expected value.
16
+ #
17
+ # setup { User.new(:email => "foo@bar.baz") }
18
+ # denies("topic") { topic }.assigns(:first_name)
19
+ # denies("topic") { topic }.assigns(:email, "bar@baz.boo")
11
20
  class AssignsMacro < AssertionMacro
12
21
  register :assigns
13
22
 
14
23
  def evaluate(actual, *expectings)
15
- variable, expected_value = expectings
16
- variable_name = "@#{variable}"
17
- actual_value = actual.instance_variable_defined?(variable_name) ? actual.instance_variable_get(variable_name) : nil
18
- if actual_value.nil?
19
- fail expected_message(variable).to_be_assigned_a_value
20
- elsif !expected_value.nil? && expected_value != actual_value
21
- fail expected_message(variable).to_be_equal_to(expected_value).not(actual_value)
22
- else
23
- pass
24
+ prepare(actual, *expectings) do |variable, expected_value, actual_value|
25
+ if actual_value.nil?
26
+ fail expected_message(variable).to_be_assigned_a_value
27
+ elsif !expected_value.nil? && expected_value != actual_value
28
+ fail expected_message(variable).to_be_equal_to(expected_value).not(actual_value)
29
+ else
30
+ pass
31
+ end
24
32
  end
25
33
  end
26
- end
27
- end
34
+
35
+ def devaluate(actual, *expectings)
36
+ prepare(actual, *expectings) do |variable, expected_value, actual_value|
37
+ if actual_value.nil? || (expected_value && expected_value != actual_value)
38
+ pass
39
+ else
40
+ message = expected_message(variable).to_not_be
41
+ fail(expected_value.nil? ? message.assigned_a_value : message.equal_to(expected_value))
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def prepare(actual, *expectings, &block)
49
+ variable, expected_value = expectings
50
+ yield(variable, expected_value, actual.instance_variable_get("@#{variable}"))
51
+ end
52
+ end # AssignsMacro
53
+ end # Riot
@@ -1,13 +1,24 @@
1
1
  module Riot
2
- # Asserts the result is empty
2
+ # In the postive case, asserts the result of the test is empty.
3
+ #
3
4
  # asserts("a string") { "" }.empty
4
5
  # asserts("an array") { [] }.empty
5
6
  # asserts("a hash") { Hash.new }.empty
7
+ #
8
+ # In the negative case, asserts the result of the test is not empty.
9
+ #
10
+ # denies("a string") { "foo" }.empty
11
+ # denies("an array") { [1] }.empty
12
+ # denies("a hash") { {:foo => "bar" } }.empty
6
13
  class EmptyMacro < AssertionMacro
7
14
  register :empty
8
15
 
9
16
  def evaluate(actual)
10
- actual.length == 0 ? pass : fail(expected_message(actual).to_be_empty)
17
+ actual.empty? ? pass(new_message.is_empty) : fail(expected_message(actual).to_be_empty)
18
+ end
19
+
20
+ def devaluate(actual)
21
+ actual.empty? ? fail(expected_message(actual).to_not_be_empty) : pass(new_message.is_empty)
11
22
  end
12
23
  end
13
24
  end
@@ -1,9 +1,16 @@
1
1
  module Riot
2
- # Asserts that the result of the test equals the expected value. Using the +==+ operator to assert
3
- # equality.
2
+ # In the positive case, asserts that the result of the test equals the expected value. Using the +==+
3
+ # operator to assert equality.
4
+ #
4
5
  # asserts("test") { "foo" }.equals("foo")
5
6
  # should("test") { "foo" }.equals("foo")
6
7
  # asserts("test") { "foo" }.equals { "foo" }
8
+ #
9
+ # In the negative case, asserts that the result of the test *does not* equal the expected value. Using the
10
+ # +==+ operator.
11
+ #
12
+ # denies("test") { "foo" }.equals("bar")
13
+ # denies("test") { "foo" }.equals { "bar" }
7
14
  class EqualsMacro < AssertionMacro
8
15
  register :equals
9
16
 
@@ -14,5 +21,13 @@ module Riot
14
21
  fail expected_message(expected).not(actual)
15
22
  end
16
23
  end
24
+
25
+ def devaluate(actual, expected)
26
+ if expected != actual
27
+ pass new_message.is_equal_to(expected).when_it_is(actual)
28
+ else
29
+ fail new_message.did_not_expect(actual)
30
+ end
31
+ end
17
32
  end
18
33
  end
@@ -5,7 +5,12 @@ module Riot
5
5
  # should("test") { "foo" }.equivalent_to("foo")
6
6
  # asserts("test") { "foo" }.equivalent_to { "foo" }
7
7
  #
8
- # Underneath the hood, this assertion macro says:
8
+ # You can also assert that the expected value is not equivalent to something else:
9
+ #
10
+ # denies("test") { "foo" }.equivalent_to(Boolean)
11
+ # denies("test") { "foo" }.equivalent_to("bar")
12
+ #
13
+ # Underneath the hood, this assertion macro uses:
9
14
  #
10
15
  # expected === actual
11
16
  class EquivalentToMacro < AssertionMacro
@@ -18,5 +23,14 @@ module Riot
18
23
  fail expected_message(actual).to_be_equivalent_to(expected)
19
24
  end
20
25
  end
26
+
27
+ def devaluate(actual, expected)
28
+ if expected === actual
29
+ fail expected_message(actual).not_to_be_equivalent_to(expected)
30
+ else
31
+ pass new_message.is_not_equivalent_to(expected)
32
+ end
33
+ end
34
+
21
35
  end
22
36
  end
@@ -1,15 +1,27 @@
1
1
  module Riot
2
2
  # Asserts that the result of the test is a non-nil value. This is useful in the case where you don't want
3
3
  # to translate the result of the test into a boolean value
4
+ #
4
5
  # asserts("test") { "foo" }.exists
5
6
  # should("test") { 123 }.exists
6
7
  # asserts("test") { "" }.exists
7
8
  # asserts("test") { nil }.exists # This would fail
9
+ #
10
+ # You can also test for non-existince (being nil), but if you would better if you used the +nil+ macro:
11
+ #
12
+ # denies("test") { nil }.exists # would pass
13
+ # asserts("test") { nil }.nil # same thing
14
+ #
15
+ # denies("test") { "foo" }.exists # would fail
8
16
  class ExistsMacro < AssertionMacro
9
17
  register :exists
10
18
 
11
19
  def evaluate(actual)
12
- !actual.nil? ? pass("is not nil") : fail("expected a non-nil value")
20
+ actual.nil? ? fail("expected a non-nil value") : pass("is not nil")
21
+ end
22
+
23
+ def devaluate(actual)
24
+ actual.nil? ? pass("is nil") : fail("expected a nil value")
13
25
  end
14
26
  end
15
27
  end
@@ -1,8 +1,15 @@
1
1
  module Riot
2
2
  # Asserts the result contains the expected element
3
+ #
3
4
  # asserts("a string") { "world" }.includes('o')
4
5
  # asserts("an array") { [1,2,3] }.includes(2)
5
6
  # asserts("a range") { (1..15) }.includes(10)
7
+ #
8
+ # You can also assert that the result does not contain an element:
9
+ #
10
+ # denies("a string") { "world" }.includes('f')
11
+ # denies("an array") { [1,2,3,4,5] }.includes(0)
12
+ # denies("a range") { (1..15) }.includes(16)
6
13
  class IncludesMacro < AssertionMacro
7
14
  register :includes
8
15
 
@@ -13,5 +20,14 @@ module Riot
13
20
  fail expected_message(actual).to_include(expected)
14
21
  end
15
22
  end
23
+
24
+ def devaluate(actual, expected)
25
+ if actual.include?(expected)
26
+ fail expected_message(actual).to_not_include(expected)
27
+ else
28
+ pass new_message.does_not_include(expected)
29
+ end
30
+ end
31
+
16
32
  end
17
33
  end
@@ -1,7 +1,12 @@
1
1
  module Riot
2
2
  # Asserts that the result of the test is an object that is a kind of the expected type
3
+ #
3
4
  # asserts("test") { "foo" }.kind_of(String)
4
5
  # should("test") { "foo" }.kind_of(String)
6
+ #
7
+ # You can also test the result is not a kind of a thing:
8
+ #
9
+ # denies("test") { "foo" }.kind_of(Boolean)
5
10
  class KindOfMacro < AssertionMacro
6
11
  register :kind_of
7
12
 
@@ -12,5 +17,13 @@ module Riot
12
17
  fail expected_message.kind_of(expected).not(actual.class)
13
18
  end
14
19
  end
20
+
21
+ def devaluate(actual, expected)
22
+ if actual.kind_of?(expected)
23
+ fail expected_message.not_kind_of(expected).not(actual.class)
24
+ else
25
+ pass new_message.is_not_a_kind_of(expected)
26
+ end
27
+ end
15
28
  end
16
29
  end
@@ -1,7 +1,12 @@
1
1
  module Riot
2
2
  # Asserts that the result of the test equals matches against the proved expression
3
+ #
3
4
  # asserts("test") { "12345" }.matches(/\d+/)
4
5
  # should("test") { "12345" }.matches(/\d+/)
6
+ #
7
+ # You can also test that the result does not match your regex:
8
+ #
9
+ # denies("test") { "hello, world"}.matches(/\d+/)
5
10
  class MatchesMacro < AssertionMacro
6
11
  register :matches
7
12
 
@@ -13,5 +18,14 @@ module Riot
13
18
  fail(expected_message(expected).to_match(actual))
14
19
  end
15
20
  end
21
+
22
+ def devaluate(actual, expected)
23
+ expected = %r[#{Regexp.escape(expected)}] if expected.kind_of?(String)
24
+ if actual.to_s =~ expected
25
+ fail(expected_message(expected).not_to_match(actual))
26
+ else
27
+ pass(new_message.does_not_match(expected))
28
+ end
29
+ end
16
30
  end
17
31
  end
@@ -1,12 +1,22 @@
1
1
  module Riot
2
2
  # Asserts that the result of the test is nil
3
+ #
3
4
  # asserts("test") { nil }.nil
4
5
  # should("test") { nil }.nil
6
+ #
7
+ # You could test that the result is not nil, but it would make more sense to use the +exists+ macro:
8
+ #
9
+ # denies("test") { "foo" }.nil
10
+ # asserts("test") { "foo" }.exists
5
11
  class NilMacro < AssertionMacro
6
12
  register :nil
7
13
 
8
14
  def evaluate(actual)
9
15
  actual.nil? ? pass("is nil") : fail(expected_message.nil.not(actual))
10
16
  end
17
+
18
+ def devaluate(actual)
19
+ actual.nil? ? fail(expected_message.is_nil.not('non-nil')) : pass("is not nil")
20
+ end
11
21
  end
12
22
  end
@@ -1,16 +1,26 @@
1
1
  module Riot
2
2
  # Asserts the result of the test is a non-truthy value. Read the following assertions in the way Borat
3
3
  # learned about humor:
4
+ #
4
5
  # asserts("you are funny") { false }.not!
5
6
  # should("be funny") { nil }.not!
6
7
  #
7
8
  # Thusly, Borat would say "You are funny ... not!" The above two assertions would pass because the values
8
9
  # are non-truthy.
10
+ #
11
+ # You can also apply not to the negative assertion (denies), but I'm not sure how much sense it would make.
12
+ # It would be kind of like a double negative:
13
+ #
14
+ # denies("you are funny") { true }.not!
9
15
  class NotMacro < AssertionMacro
10
16
  register :not!
11
17
 
12
18
  def evaluate(actual)
13
19
  actual ? fail("expected to exist ... not!") : pass("does exist ... not!")
14
20
  end
21
+
22
+ def devaluate(actual)
23
+ actual ? pass("does not exist ... not!") : fail("expected to not exist ... not!")
24
+ end
15
25
  end
16
26
  end
@@ -7,6 +7,13 @@ module Riot
7
7
  # from the actual raised exception will be converted to a string before any comparison is executed.
8
8
  # asserts("test") { raise My::Exception, "Foo" }.raises(My::Exception, "Foo")
9
9
  # asserts("test") { raise My::Exception, "Foo Bar" }.raises(My::Exception, /Bar/)
10
+ #
11
+ # In the negative case, you can test that an exception was not raised or that if an exception was raised
12
+ # that the type of exception was different (sounds confusing).
13
+ #
14
+ # denies("test") { "foo" }.raises(Exception) # would pass
15
+ # denies("test") { raise Exception }.raises(My::Exception) # would pass
16
+ # denies("test") { raise Exception }.raises(Exception) # would fail
10
17
  class RaisesMacro < AssertionMacro
11
18
  register :raises
12
19
  expects_exception!
@@ -24,5 +31,26 @@ module Riot
24
31
  pass(expected_message ? message.with_message(expected_message) : message)
25
32
  end
26
33
  end # evaluate
34
+
35
+ def devaluate(actual_exception, expected_class, expected_message=nil)
36
+ actual_message = actual_exception && actual_exception.message
37
+ if actual_exception.nil?
38
+ pass new_message.raised_nothing
39
+ elsif expected_class != actual_exception.class
40
+ if expected_message && !(actual_message.to_s =~ %r[#{expected_message}])
41
+ pass new_message.not_raised(expected_class).with_message(expected_message)
42
+ else
43
+ pass new_message.not_raised(expected_class)
44
+ end
45
+ else
46
+ message = should_have_message.not_raised(expected_class)
47
+ if expected_message
48
+ fail message.with_message(expected_message).but.raised(actual_exception.class).
49
+ with_message(actual_exception.message)
50
+ else
51
+ fail message.but.raised(actual_exception.class)
52
+ end
53
+ end
54
+ end # devaluate
27
55
  end # RaisesMacro
28
56
  end