mirror of
				https://gitea.invidious.io/iv-org/shard-spectator.git
				synced 2024-08-15 00:53:35 +00:00 
			
		
		
		
	More structure around exceptions and matching
This commit is contained in:
		
							parent
							
								
									4c2f6157af
								
							
						
					
					
						commit
						79886e9efb
					
				
					 9 changed files with 95 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -1,11 +1,50 @@
 | 
			
		|||
module Spectator::Expectations
 | 
			
		||||
  abstract class Expectation
 | 
			
		||||
    getter? negated : Bool
 | 
			
		||||
  # Min-in for all expectation types.
 | 
			
		||||
  # Classes that include this must implement
 | 
			
		||||
  # the `#satisfied?`, `#message`, and `#negated_message` methods.
 | 
			
		||||
  module Expectation
 | 
			
		||||
    # Checks whether the expectation is met.
 | 
			
		||||
    abstract def satisfied? : Bool
 | 
			
		||||
 | 
			
		||||
    private def initialize(@negated)
 | 
			
		||||
    # Describes the condition that must be met for the expectation to be satisifed.
 | 
			
		||||
    abstract def message : String
 | 
			
		||||
 | 
			
		||||
    # Describes the condition under which the expectation won't be satisifed.
 | 
			
		||||
    abstract def negated_message : String
 | 
			
		||||
 | 
			
		||||
    # Evaulates the expectation and produces a result.
 | 
			
		||||
    # The `negated` flag should be set to true to invert the result.
 | 
			
		||||
    def eval(negated = false) : Result
 | 
			
		||||
      success = satisfied? ^ negated
 | 
			
		||||
      Result.new(success, negated, self)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    abstract def eval : Bool
 | 
			
		||||
    abstract def message : String
 | 
			
		||||
    # Information regarding the outcome of an expectation.
 | 
			
		||||
    class Result
 | 
			
		||||
      # Indicates whether the expectation was satisifed or not.
 | 
			
		||||
      getter? successful : Bool
 | 
			
		||||
 | 
			
		||||
      # Creates the result.
 | 
			
		||||
      # The expectation is stored so that information from it may be lazy-loaded.
 | 
			
		||||
      protected def initialize(@successful, @negated : Bool, @expectation : Expectation)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Description of the condition that satisfies, or meets, the expectation.
 | 
			
		||||
      def satisfy_message
 | 
			
		||||
        message(@negated)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Description of what actually happened when the expectation was evaluated.
 | 
			
		||||
      def result_message
 | 
			
		||||
        message(@successful)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Retrieves the message or negated message from an expectation.
 | 
			
		||||
      # Set `negated` to true to get the negated message,
 | 
			
		||||
      # or to false to get the regular message.
 | 
			
		||||
      private def message(negated)
 | 
			
		||||
        negated ? @expectation.negated_message : @expectation.message
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ module Spectator::Expectations
 | 
			
		|||
    private def initialize(@raise_on_failure = true)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def report(expectation : Expectation) : Nil
 | 
			
		||||
    def report(result : Expectation::Result) : Nil
 | 
			
		||||
      raise NotImplementedError.new("ExpectationRegistry#report")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,11 +15,11 @@ module Spectator::Expectations
 | 
			
		|||
      raise NotImplementedError.new("ExpectationRegistry.current")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.start(example : Example) : ExpectationRegistry
 | 
			
		||||
    def self.start(example : Example) : Nil
 | 
			
		||||
      raise NotImplementedError.new("ExpectationRegistry.start")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.finish : Nil # TODO: Define return type.
 | 
			
		||||
    def self.finish : ExpectationResults
 | 
			
		||||
      raise NotImplementedError.new("ExpectationRegistry.finish")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								src/spectator/expectations/expectation_results.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/spectator/expectations/expectation_results.cr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
module Spectator::Expectations
 | 
			
		||||
  class ExpectationResults
 | 
			
		||||
    def initialize(@results : Enumerable(ExpectationResult))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +1,26 @@
 | 
			
		|||
require "./expectation"
 | 
			
		||||
 | 
			
		||||
module Spectator::Expectations
 | 
			
		||||
  class ValueExpectation(ActualType, ExpectedType) < Expectation
 | 
			
		||||
    def initialize(negated,
 | 
			
		||||
                   @partial : ValueExpectationPartial(ActualType),
 | 
			
		||||
                   @matcher : ValueMatcher(ExpectedType))
 | 
			
		||||
      super(negated)
 | 
			
		||||
  class ValueExpectation(ActualType, ExpectedType)
 | 
			
		||||
    include Expectation
 | 
			
		||||
 | 
			
		||||
    def initialize(@partial : ValueExpectationPartial(ActualType),
 | 
			
		||||
                   @matcher : Matchers::ValueMatcher(ExpectedType))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def eval : Bool
 | 
			
		||||
      @matcher.match?(@partial) ^ negated?
 | 
			
		||||
    # Checks whether the expectation is met.
 | 
			
		||||
    def satisfied? : Bool
 | 
			
		||||
      @matcher.match?(@partial)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Describes the condition that must be met for the expectation to be satisifed.
 | 
			
		||||
    def message : String
 | 
			
		||||
      negated? ? @matcher.negated_message(@partial) : @matcher.message(@partial)
 | 
			
		||||
      @matcher.message(@partial)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Describes the condition under which the expectation won't be satisifed.
 | 
			
		||||
    def negated_message : String
 | 
			
		||||
      @matcher.negated_message(@partial)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,11 +9,15 @@ module Spectator::Expectations
 | 
			
		|||
    end
 | 
			
		||||
 | 
			
		||||
    def to(matcher : Matchers::ValueMatcher(ExpectedType)) : Nil forall ExpectedType
 | 
			
		||||
      raise NotImplementedError.new("ValueExpectationPartial#to")
 | 
			
		||||
      expectation = ValueExpectation.new(self, matcher)
 | 
			
		||||
      result = expectation.eval
 | 
			
		||||
      ExpectationRegistry.current.report(result)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_not(matcher : Matchers::ValueMatcher(ExpectedType)) : Nil forall ExpectedType
 | 
			
		||||
      raise NotImplementedError.new("ValueExpectationPartial#to_not")
 | 
			
		||||
      expectation = ValueExpectation.new(self, matcher)
 | 
			
		||||
      result = expectation.eval(true)
 | 
			
		||||
      ExpectationRegistry.current.report(result)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # ditto
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,11 @@ require "./result"
 | 
			
		|||
module Spectator
 | 
			
		||||
  class FailedResult < Result
 | 
			
		||||
    getter error : Exception
 | 
			
		||||
    getter expectations : Expectations::ExpectationResults
 | 
			
		||||
 | 
			
		||||
    def initialize(example, elapsed, @expectations, @error)
 | 
			
		||||
      super(example, elapsed)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def passed?
 | 
			
		||||
      false
 | 
			
		||||
| 
						 | 
				
			
			@ -19,9 +24,5 @@ module Spectator
 | 
			
		|||
    def pending?
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize(example, elapsed, @error)
 | 
			
		||||
      super(example, elapsed)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,15 +2,15 @@ require "./value_matcher"
 | 
			
		|||
 | 
			
		||||
module Spectator::Matchers
 | 
			
		||||
  class EqualityMatcher(ExpectedType) < ValueMatcher(ExpectedType)
 | 
			
		||||
    def match?(partial : ValueExpectationPartial(ActualType)) : Bool forall ActualType
 | 
			
		||||
    def match?(partial : Expectations::ValueExpectationPartial(ActualType)) : Bool forall ActualType
 | 
			
		||||
      partial.actual == expected
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def message(partial : ValueExpectationPartial(ActualType)) : String forall ActualType
 | 
			
		||||
    def message(partial : Expectations::ValueExpectationPartial(ActualType)) : String forall ActualType
 | 
			
		||||
      "Expected #{partial.label} to equal #{label} (using ==)"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def negated_message(partial : ValueExpectationPartial(ActualType)) : String forall ActualType
 | 
			
		||||
    def negated_message(partial : Expectations::ValueExpectationPartial(ActualType)) : String forall ActualType
 | 
			
		||||
      "Expected #{partial.label} to not equal #{label} (using ==)"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ require "./example"
 | 
			
		|||
module Spectator
 | 
			
		||||
  abstract class RunnableExample < Example
 | 
			
		||||
    def run
 | 
			
		||||
      Expectations::ExpectationRegistry.start(self)
 | 
			
		||||
      result = ResultCapture.new
 | 
			
		||||
      group.run_before_all_hooks
 | 
			
		||||
      group.run_before_each_hooks
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +14,8 @@ module Spectator
 | 
			
		|||
        group.run_after_each_hooks
 | 
			
		||||
        group.run_after_all_hooks
 | 
			
		||||
      end
 | 
			
		||||
      translate_result(result)
 | 
			
		||||
      expectations = Expectations::ExpectationRegistry.finish
 | 
			
		||||
      translate_result(result, expectations)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private def wrapped_capture_result(result)
 | 
			
		||||
| 
						 | 
				
			
			@ -32,14 +34,14 @@ module Spectator
 | 
			
		|||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private def translate_result(result)
 | 
			
		||||
    private def translate_result(result, expectations)
 | 
			
		||||
      case (error = result.error)
 | 
			
		||||
      when Nil
 | 
			
		||||
        SuccessfulResult.new(self, result.elapsed)
 | 
			
		||||
        SuccessfulResult.new(self, result.elapsed, expectations)
 | 
			
		||||
      when ExpectationFailed
 | 
			
		||||
        FailedResult.new(self, result.elapsed, error)
 | 
			
		||||
        FailedResult.new(self, result.elapsed, expectations, error)
 | 
			
		||||
      else
 | 
			
		||||
        ErroredResult.new(self, result.elapsed, error)
 | 
			
		||||
        ErroredResult.new(self, result.elapsed, expectations, error)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,12 @@ require "./result"
 | 
			
		|||
 | 
			
		||||
module Spectator
 | 
			
		||||
  class SuccessfulResult < Result
 | 
			
		||||
    getter expectations : Expectations::ExpectationResults
 | 
			
		||||
 | 
			
		||||
    def initialize(example, elapsed, @expectations)
 | 
			
		||||
      super(example, elapsed)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def passed?
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue