File: assertion_macro.rb

package info (click to toggle)
ruby-riot 0.12.7-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster, forky, sid, trixie
  • size: 512 kB
  • sloc: ruby: 2,557; makefile: 2
file content (141 lines) | stat: -rw-r--r-- 4,958 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require 'riot/message'

module Riot
  # The base class for all assertion macros.
  #
  # == Using macros
  #
  # Macros are applied to the return value of assertions. For example, the
  # +empty+ macro asserts that the value is empty or denies that it is empty e.g.
  #
  #     asserts(:comments).empty?
  #     denies(:comments).empty?
  #
  # == Writing your own macros
  #
  # Macros are added by subclassing {AssertionMacro}. For example, here's
  # the implementation of +empty+:
  #
  #     class EmptyMacro < AssertionMacro
  #       register :empty
  #
  #       def evaluate(actual)
  #         actual.length == 0 ? pass : fail(expected_message(actual).to_be_empty)
  #       end
  #
  #       def devaluate(actual)
  #         actual.empty? ? fail(expected_message(actual).to_not_be_empty) : pass(new_message.is_empty)
  #       end
  #     end
  #
  class AssertionMacro
    class << self
      # Whether the macro expects an exception to be thrown.
      #
      # @return [Boolean]
      attr_reader :expects_exception

      # @private
      # The default macro.
      #
      # @return [Riot::AssertionMacro]
      def default
        @default_macro ||= new
      end

      # Specify that the macro expects an exception to be thrown by the assertion.
      def expects_exception!
        @expects_exception = true
      end

      # Register the macro under the given name.
      #
      # @param [String, Symbol] name the name of the macro
      def register(name)
        Assertion.register_macro name, self
      end
    end

    # During failure reporting, what line number did the failure occur at
    # @return [Number]
    attr_accessor :line

    # During failure reporting, what file did the failure occur in
    # @return [String]
    attr_accessor :file

    # Returns a status tuple indicating the assertion passed.
    #
    # @param [String] message the message to report with
    # @return [Array[Symbol, String]]
    def pass(message=nil) [:pass, message.to_s]; end

    # Returns a status tuple indicating the assertion failed and where it failed it if that can be
    # determined.
    #
    # @param [String] message the message to report with
    # @return [Array[Symbol, String, Number, String]]
    def fail(message) [:fail, message.to_s, line, file]; end

    # Returns a status tuple indicating the assertion had an unexpected error.
    #
    # @param [Exception] ex the Exception that was captured
    # @return [Array[Symbol, Exception]]
    def error(ex) [:error, ex]; end

    # Returns +true+ if this macro expects to handle Exceptions during evaluation.
    #
    # @return [boolean]
    def expects_exception?; self.class.expects_exception; end

    # Supports positive assertion testing. This is where magic happens.
    #
    # @param [Object] actual the value returned from evaling the {Riot::Assertion Assertion} block
    # @return [Array] response from either {#pass}, {#fail} or {#error}
    def evaluate(actual)
      actual ? pass : fail("Expected non-false but got #{actual.inspect} instead")
    end

    # Supports negative/converse assertion testing. This is also where magic happens.
    #
    # @param [Object] actual the value returned from evaling the {Riot::Assertion Assertion} block
    # @return [Array] response from either {#pass}, {#fail} or {#error}
    def devaluate(actual)
      !actual ? pass : fail("Expected non-true but got #{actual.inspect} instead")
    end

    # Creates a new message for use in any macro response that is initially empty.
    #
    # @param [Array<Object>] *phrases array of object whose values will be inspected and added to message
    # @return [Riot::Message]
    def new_message(*phrases) Message.new(*phrases); end

    # Creates a new message for use in any macro response that will start as "should have ".
    #
    # @param [Array<Object>] *phrases array of object whose values will be inspected and added to message
    # @return [Riot::Message]
    def should_have_message(*phrases) new_message.should_have(*phrases); end

    # Creates a new message for use in any macro response that will start as "expected ".
    #
    # @param [Array<Object>] *phrases array of object whose values will be inspected and added to message
    # @return [Riot::Message]
    def expected_message(*phrases) new_message.expected(*phrases); end
  end
end

require 'riot/assertion_macros/any'
require 'riot/assertion_macros/assigns'
require 'riot/assertion_macros/empty'
require 'riot/assertion_macros/equals'
require 'riot/assertion_macros/equivalent_to'
require 'riot/assertion_macros/exists'
require 'riot/assertion_macros/includes'
require 'riot/assertion_macros/kind_of'
require 'riot/assertion_macros/matches'
require 'riot/assertion_macros/nil'
require 'riot/assertion_macros/raises'
require 'riot/assertion_macros/raises_kind_of'
require 'riot/assertion_macros/respond_to'
require 'riot/assertion_macros/same_elements'
require 'riot/assertion_macros/size'