calificador 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
 - data/README.md +35 -16
 - data/TODO.md +16 -0
 - data/calificador.gemspec +54 -0
 - data/lib/calificador.rb +8 -4
 - data/lib/calificador/assert.rb +15 -0
 - data/lib/calificador/assertor.rb +79 -35
 - data/lib/calificador/build/attribute_evaluator.rb +34 -30
 - data/lib/calificador/build/basic_factory.rb +195 -0
 - data/lib/calificador/build/mock_factory.rb +151 -0
 - data/lib/calificador/build/object_factory.rb +85 -0
 - data/lib/calificador/build/trait.rb +0 -20
 - data/lib/calificador/context/basic_context.rb +406 -0
 - data/lib/calificador/context/class_method_context.rb +0 -0
 - data/lib/calificador/{spec → context}/condition_context.rb +1 -3
 - data/lib/calificador/{spec/type_context.rb → context/instance_context.rb} +5 -10
 - data/lib/calificador/context/operation_context.rb +27 -0
 - data/lib/calificador/context/override/argument_override.rb +73 -0
 - data/lib/calificador/context/override/basic_override.rb +14 -0
 - data/lib/calificador/context/override/factory_override.rb +31 -0
 - data/lib/calificador/context/override/property_override.rb +61 -0
 - data/lib/calificador/context/test_environment.rb +283 -0
 - data/lib/calificador/{spec → context}/test_method.rb +2 -31
 - data/lib/calificador/{spec → context}/test_root.rb +3 -15
 - data/lib/calificador/{spec/examine_context.rb → context/type_context.rb} +7 -10
 - data/lib/calificador/key.rb +27 -15
 - data/lib/calificador/minitest/minitest_patches.rb +0 -2
 - data/lib/calificador/test.rb +1 -3
 - data/lib/calificador/test_mixin.rb +143 -139
 - data/lib/calificador/util/call_formatter.rb +5 -5
 - data/lib/calificador/util/core_extensions.rb +104 -79
 - data/lib/calificador/util/proxy_object.rb +63 -0
 - data/lib/calificador/version.rb +1 -1
 - metadata +22 -42
 - data/lib/calificador/build/attribute_container.rb +0 -103
 - data/lib/calificador/build/factory.rb +0 -132
 - data/lib/calificador/spec/basic_context.rb +0 -353
 - data/lib/calificador/spec/class_method_context.rb +0 -42
 - data/lib/calificador/spec/instance_method_context.rb +0 -38
 - data/lib/calificador/spec/test_environment.rb +0 -141
 - data/lib/calificador/spec/value_override.rb +0 -37
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 391cd5fa12b8710d063b8523dbb6d3350c13162ff241279c5d979ce9b7a3b555
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0d0527fda2ab45e903f057d6cd22a23588cde7b1a7c4ad352c718dc577785d59
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 588366fbb53142a962e3a18b4b6fdfc9232729f22967d2ceb2105bd032293fea21d7c41ba3650d48a85827a12e926de27be63fe9523a6b9913aebb2f23fa4b39
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 24c4a70eebd0528f2fb6a041a7283f65b23636048f480632e5975b6e78c862b479f0202142d45f2b9e77c3ee089b4852e4f0172989071e3f0390e10f833449c1
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            # What is it?
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            A small Gem that lets you write concise and readable unit tests. It is heavily inspired by [Minitest], [Factory Bot], and [Assertive Expressive] but tries to boil everything down to be as concise as possible:
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
         @@ -6,12 +6,18 @@ A small Gem that lets you write concise and readable unit tests. It is heavily i 
     | 
|
| 
       6 
6 
     | 
    
         
             
                module ReadMe
         
     | 
| 
       7 
7 
     | 
    
         
             
                  require "calificador"
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                  # Define  
     | 
| 
      
 9 
     | 
    
         
            +
                  # Define class to test
         
     | 
| 
       10 
10 
     | 
    
         
             
                  class HighTea
         
     | 
| 
       11 
11 
     | 
    
         
             
                    attr_accessor :scones, :posh
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
      
 13 
     | 
    
         
            +
                    def initialize(scones:)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      raise ArgumentError, "Cannot have a negative amount of scones" if scones.negative?
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      @scones = scones
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       13 
19 
     | 
    
         
             
                    def eat_scone
         
     | 
| 
       14 
     | 
    
         
            -
                      raise "Out of scones" if scones 
     | 
| 
      
 20 
     | 
    
         
            +
                      raise "Out of scones" if scones.zero?
         
     | 
| 
       15 
21 
     | 
    
         | 
| 
       16 
22 
     | 
    
         
             
                      @scones -= 1
         
     | 
| 
       17 
23 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -27,37 +33,50 @@ A small Gem that lets you write concise and readable unit tests. It is heavily i 
     | 
|
| 
       27 
33 
     | 
    
         | 
| 
       28 
34 
     | 
    
         
             
                    # Define a factory for the test subject
         
     | 
| 
       29 
35 
     | 
    
         
             
                    factory HighTea do
         
     | 
| 
       30 
     | 
    
         
            -
                       
     | 
| 
      
 36 
     | 
    
         
            +
                      # Set properties on the created object
         
     | 
| 
       31 
37 
     | 
    
         
             
                      posh { false }
         
     | 
| 
       32 
38 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                      #  
     | 
| 
      
 39 
     | 
    
         
            +
                      # Define transient properties that will not be set automatically
         
     | 
| 
      
 40 
     | 
    
         
            +
                      transient do
         
     | 
| 
      
 41 
     | 
    
         
            +
                        # Constructor arguments are automatically set from properties
         
     | 
| 
      
 42 
     | 
    
         
            +
                        scones { 2 }
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                      # Use traits to define variants of your test subject
         
     | 
| 
       34 
46 
     | 
    
         
             
                      trait :style do
         
     | 
| 
       35 
47 
     | 
    
         
             
                        posh { true }
         
     | 
| 
       36 
48 
     | 
    
         
             
                      end
         
     | 
| 
       37 
49 
     | 
    
         
             
                    end
         
     | 
| 
       38 
50 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                    #  
     | 
| 
       40 
     | 
    
         
            -
                     
     | 
| 
       41 
     | 
    
         
            -
                       
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
      
 51 
     | 
    
         
            +
                    # Test class methods
         
     | 
| 
      
 52 
     | 
    
         
            +
                    type do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      operation :new do
         
     | 
| 
      
 54 
     | 
    
         
            +
                        must "set a default amount of scones" do
         
     | 
| 
      
 55 
     | 
    
         
            +
                          # Write assertions using plain Ruby methods instead of spec DSL methods
         
     | 
| 
      
 56 
     | 
    
         
            +
                          assert { subject.scones } > 0
         
     | 
| 
      
 57 
     | 
    
         
            +
                        end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                        must "provide an instance that has tea" do
         
     | 
| 
      
 60 
     | 
    
         
            +
                          refute { subject.tea }.nil?
         
     | 
| 
      
 61 
     | 
    
         
            +
                        end
         
     | 
| 
      
 62 
     | 
    
         
            +
                      end
         
     | 
| 
       44 
63 
     | 
    
         
             
                    end
         
     | 
| 
       45 
64 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                    # Get nice test names. This one will be called "HighTea must  
     | 
| 
      
 65 
     | 
    
         
            +
                    # Get nice test names. This one will be called "HighTea must let me have a scone"
         
     | 
| 
       47 
66 
     | 
    
         
             
                    must "let me have a scone" do
         
     | 
| 
       48 
67 
     | 
    
         
             
                      count = subject.scones
         
     | 
| 
       49 
68 
     | 
    
         
             
                      subject.eat_scone
         
     | 
| 
       50 
69 
     | 
    
         
             
                      assert { subject.scones } == count - 1
         
     | 
| 
       51 
70 
     | 
    
         
             
                    end
         
     | 
| 
       52 
71 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                    #  
     | 
| 
       54 
     | 
    
         
            -
                    must "complain if out of scones", scones 
     | 
| 
      
 72 
     | 
    
         
            +
                    # Modify test subject using traits or properties for minor variations
         
     | 
| 
      
 73 
     | 
    
         
            +
                    must "complain if out of scones", props { scones { 0 } } do
         
     | 
| 
       55 
74 
     | 
    
         
             
                      assert { subject.eat_scone }.raises?(StandardError)
         
     | 
| 
       56 
75 
     | 
    
         
             
                    end
         
     | 
| 
       57 
76 
     | 
    
         | 
| 
       58 
77 
     | 
    
         
             
                    # Create subcontexts for variations of the test subject using traits and properties
         
     | 
| 
       59 
78 
     | 
    
         
             
                    with :style do
         
     | 
| 
       60 
     | 
    
         
            -
                      # Still nice test names. This one is "HighTea with style  
     | 
| 
      
 79 
     | 
    
         
            +
                      # Still nice test names. This one is "HighTea with style must have expensive tea"
         
     | 
| 
       61 
80 
     | 
    
         
             
                      must "have expensive tea" do
         
     | 
| 
       62 
81 
     | 
    
         
             
                        assert { subject.tea }.include?("First Flush")
         
     | 
| 
       63 
82 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -79,8 +98,8 @@ Calificador is an experiment in getting rid of as much mental load, boilerplate 
     | 
|
| 
       79 
98 
     | 
    
         | 
| 
       80 
99 
     | 
    
         
             
            Only a handful of DSL methods are required:
         
     | 
| 
       81 
100 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
            * Test structure: examine,  
     | 
| 
       83 
     | 
    
         
            -
            * Factory methods: factory, traits
         
     | 
| 
      
 101 
     | 
    
         
            +
            * Test structure: examine, type, operation, where/with/without, must
         
     | 
| 
      
 102 
     | 
    
         
            +
            * Factory methods: factory, mock, traits
         
     | 
| 
       84 
103 
     | 
    
         
             
            * Assertions: assert, refute and raises?
         
     | 
| 
       85 
104 
     | 
    
         | 
| 
       86 
105 
     | 
    
         
             
            It also tries to keep things simple by avoiding all the special assertion and expectation methods you need to learn for other test frameworks. Instead of having to learn that `include` is the RSpec matcher for `include?`, or Minitest's `assert_match` is used to assert regular expression matches, you can write `refute { something }.include? "value"` or `assert { something }.match %r{pattern}` using Ruby's normal `String#match` method.
         
     | 
    
        data/TODO.md
    ADDED
    
    
    
        data/calificador.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            LIB_DIR = File.join(__dir__, "lib")
         
     | 
| 
      
 4 
     | 
    
         
            +
            $LOAD_PATH.unshift(LIB_DIR) unless $LOAD_PATH.include?(LIB_DIR)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require "calificador/version"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "pathname"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 11 
     | 
    
         
            +
              raise "RubyGems 2.0 or newer is required." unless spec.respond_to?(:metadata)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              spec.name = "calificador"
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.version = Calificador::VERSION
         
     | 
| 
      
 15 
     | 
    
         
            +
              spec.summary = "Concise and readable unit tests"
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              spec.required_ruby_version = ">= 2.7"
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              spec.authors = ["Jochen Seeber"]
         
     | 
| 
      
 20 
     | 
    
         
            +
              spec.email = ["jochen@seeber.me"]
         
     | 
| 
      
 21 
     | 
    
         
            +
              spec.homepage = "https://github.com/jochenseeber/calificador"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              spec.metadata["issue_tracker"] = "https://github.com/jochenseeber/calificador/issues"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.metadata["documentation"] = "http://jochenseeber.github.com/calificador"
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.metadata["source_code"] = "https://github.com/jochenseeber/calificador"
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.metadata["wiki"] = "https://github.com/jochenseeber/calificador/wiki"
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              spec.files = Dir[
         
     | 
| 
      
 29 
     | 
    
         
            +
                "*.gemspec",
         
     | 
| 
      
 30 
     | 
    
         
            +
                "*.md",
         
     | 
| 
      
 31 
     | 
    
         
            +
                "*.txt",
         
     | 
| 
      
 32 
     | 
    
         
            +
                "lib/**/*.rb",
         
     | 
| 
      
 33 
     | 
    
         
            +
              ]
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              spec.require_paths = [
         
     | 
| 
      
 36 
     | 
    
         
            +
                "lib",
         
     | 
| 
      
 37 
     | 
    
         
            +
              ]
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              spec.bindir = "cmd"
         
     | 
| 
      
 40 
     | 
    
         
            +
              spec.executables = spec.files.filter { |f| File.dirname(f) == "cmd" && File.file?(f) }.map { |f| File.basename(f) }
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              spec.add_dependency "minitest", "~> 5.14"
         
     | 
| 
      
 43 
     | 
    
         
            +
              spec.add_dependency "zeitwerk", "~> 2.3"
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 2.1"
         
     | 
| 
      
 46 
     | 
    
         
            +
              spec.add_development_dependency "debase", "~> 0.2"
         
     | 
| 
      
 47 
     | 
    
         
            +
              spec.add_development_dependency "qed", "~> 2.9"
         
     | 
| 
      
 48 
     | 
    
         
            +
              spec.add_development_dependency "rake", "~> 13.0"
         
     | 
| 
      
 49 
     | 
    
         
            +
              spec.add_development_dependency "rubocop", ">= 0.85"
         
     | 
| 
      
 50 
     | 
    
         
            +
              spec.add_development_dependency "rubocop-rake", ">= 0.5.1"
         
     | 
| 
      
 51 
     | 
    
         
            +
              spec.add_development_dependency "ruby-debug-ide", "~> 0.7"
         
     | 
| 
      
 52 
     | 
    
         
            +
              spec.add_development_dependency "simplecov", "~> 0.18"
         
     | 
| 
      
 53 
     | 
    
         
            +
              spec.add_development_dependency "yard", "~> 0.9"
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/calificador.rb
    CHANGED
    
    | 
         @@ -1,17 +1,21 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require " 
     | 
| 
      
 3 
     | 
    
         
            +
            require "calificador/util/core_extensions"
         
     | 
| 
       4 
4 
     | 
    
         
             
            require "minitest"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "pathname"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "zeitwerk"
         
     | 
| 
       5 
7 
     | 
    
         | 
| 
       6 
8 
     | 
    
         
             
            loader = Zeitwerk::Loader.for_gem
         
     | 
| 
       7 
9 
     | 
    
         
             
            loader.setup
         
     | 
| 
       8 
10 
     | 
    
         | 
| 
       9 
11 
     | 
    
         
             
            # Main module
         
     | 
| 
       10 
12 
     | 
    
         
             
            module Calificador
         
     | 
| 
       11 
     | 
    
         
            -
              using Calificador::Util::CoreExtensions
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
13 
     | 
    
         
             
              MISSING = Util::Missing.instance
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
      
 15 
     | 
    
         
            +
              BASE_DIR = Pathname(__FILE__).expand_path.dirname
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              METHOD_PATTERN = %r{[[:alpha:]](?:[[:alnum:]]|_)*}.freeze
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       15 
19 
     | 
    
         
             
              class << self
         
     | 
| 
       16 
20 
     | 
    
         
             
                attr_writer :call_formatter
         
     | 
| 
       17 
21 
     | 
    
         | 
| 
         @@ -40,5 +44,5 @@ module Calificador 
     | 
|
| 
       40 
44 
     | 
    
         
             
              end
         
     | 
| 
       41 
45 
     | 
    
         
             
            end
         
     | 
| 
       42 
46 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
            Minitest::Assertion.prepend(Calificador::Minitest::MinitestPatches::AssertionMethods)
         
     | 
| 
       44 
47 
     | 
    
         
             
            Class.include(Calificador::Util::ClassMixin)
         
     | 
| 
      
 48 
     | 
    
         
            +
            Minitest::Assertion.prepend(Calificador::Minitest::MinitestPatches::AssertionMethods)
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "calificador"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Calificador
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Assert
         
     | 
| 
      
 7 
     | 
    
         
            +
                def assert(&block)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  Calificador::Assertor.new(block: block)
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def refute(&block)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  Calificador::Assertor.new(negated: true, block: block)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/calificador/assertor.rb
    CHANGED
    
    | 
         @@ -1,64 +1,67 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require "minitest"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "singleton"
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            module Calificador
         
     | 
| 
       6 
     | 
    
         
            -
              class Assertor <  
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
       8 
     | 
    
         
            -
                   
     | 
| 
      
 7 
     | 
    
         
            +
              class Assertor < Util::ProxyObject
         
     | 
| 
      
 8 
     | 
    
         
            +
                class DefaultHandler
         
     | 
| 
      
 9 
     | 
    
         
            +
                  include Singleton
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def assert(condition, message)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    raise ::Minitest::Assertion, message unless condition
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def refute(condition, message) 
         
     | 
| 
      
 16 
     | 
    
         
            +
                    raise ::Minitest::Assertion, message if condition
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def initialize(handler: DefaultHandler.instance, negated: false, block: nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  super()
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  @handler = handler
         
     | 
| 
       9 
24 
     | 
    
         
             
                  @negated = negated ? true : false
         
     | 
| 
       10 
25 
     | 
    
         
             
                  @block = block
         
     | 
| 
       11 
26 
     | 
    
         
             
                  @value = MISSING
         
     | 
| 
       12 
27 
     | 
    
         
             
                  @triggered = false
         
     | 
| 
       13 
28 
     | 
    
         
             
                end
         
     | 
| 
       14 
29 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                def respond_to?(method, include_all = false)
         
     | 
| 
       16 
     | 
    
         
            -
                  __value.respond_to?(method, include_all) || super
         
     | 
| 
       17 
     | 
    
         
            -
                end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                def method_missing(method, *arguments, **options, &block) # rubocop:disable Style/MissingRespondToMissing
         
     | 
| 
       20 
     | 
    
         
            -
                  if __value.respond_to?(method)
         
     | 
| 
       21 
     | 
    
         
            -
                    __check(method: method, arguments: arguments, options: options, &block)
         
     | 
| 
       22 
     | 
    
         
            -
                  else
         
     | 
| 
       23 
     | 
    
         
            -
                    super
         
     | 
| 
       24 
     | 
    
         
            -
                  end
         
     | 
| 
       25 
     | 
    
         
            -
                end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
30 
     | 
    
         
             
                def ==(other)
         
     | 
| 
       28 
31 
     | 
    
         
             
                  message = ::Kernel.proc do
         
     | 
| 
       29 
     | 
    
         
            -
                    actual = ::Calificador.call_formatter. 
     | 
| 
       30 
     | 
    
         
            -
                    expected = ::Calificador.call_formatter. 
     | 
| 
      
 32 
     | 
    
         
            +
                    actual = ::Calificador.call_formatter.format_value(value: __value)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expected = ::Calificador.call_formatter.format_value(value: other)
         
     | 
| 
       31 
34 
     | 
    
         | 
| 
       32 
35 
     | 
    
         
             
                    "Expected #{actual} (#{__value.class}) to#{@negated ? " not" : ""} be equal to #{expected} (#{other.class})"
         
     | 
| 
       33 
36 
     | 
    
         
             
                  end
         
     | 
| 
       34 
37 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                  __check( 
     | 
| 
      
 38 
     | 
    
         
            +
                  __check(name: :"==", message: message, arguments: [other])
         
     | 
| 
       36 
39 
     | 
    
         
             
                end
         
     | 
| 
       37 
40 
     | 
    
         | 
| 
       38 
41 
     | 
    
         
             
                def !=(other)
         
     | 
| 
       39 
42 
     | 
    
         
             
                  message = ::Kernel.proc do
         
     | 
| 
       40 
     | 
    
         
            -
                    actual = ::Calificador.call_formatter. 
     | 
| 
       41 
     | 
    
         
            -
                    expected = ::Calificador.call_formatter. 
     | 
| 
      
 43 
     | 
    
         
            +
                    actual = ::Calificador.call_formatter.format_value(value: __value)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    expected = ::Calificador.call_formatter.format_value(value: other)
         
     | 
| 
       42 
45 
     | 
    
         | 
| 
       43 
46 
     | 
    
         
             
                    "Expected #{actual} (#{__value.class})  to#{@negated ? "" : " not"} be equal to #{expected} (#{other.class})"
         
     | 
| 
       44 
47 
     | 
    
         
             
                  end
         
     | 
| 
       45 
48 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                  __check( 
     | 
| 
      
 49 
     | 
    
         
            +
                  __check(name: :"!=", message: message, arguments: [other])
         
     | 
| 
       47 
50 
     | 
    
         
             
                end
         
     | 
| 
       48 
51 
     | 
    
         | 
| 
       49 
52 
     | 
    
         
             
                def identical?(other)
         
     | 
| 
       50 
53 
     | 
    
         
             
                  message = ::Kernel.proc do
         
     | 
| 
       51 
     | 
    
         
            -
                    actual = ::Calificador.call_formatter. 
     | 
| 
       52 
     | 
    
         
            -
                    expected = ::Calificador.call_formatter. 
     | 
| 
      
 54 
     | 
    
         
            +
                    actual = ::Calificador.call_formatter.format_value(value: __value)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    expected = ::Calificador.call_formatter.format_value(value: other)
         
     | 
| 
       53 
56 
     | 
    
         | 
| 
       54 
57 
     | 
    
         
             
                    "Expected #{actual} (#{__value.class}) to#{@negated ? " not" : ""} be identical to #{expected} (#{other.class})"
         
     | 
| 
       55 
58 
     | 
    
         
             
                  end
         
     | 
| 
       56 
59 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                  __check( 
     | 
| 
      
 60 
     | 
    
         
            +
                  __check(name: :"equal?", message: message, arguments: [other])
         
     | 
| 
       58 
61 
     | 
    
         
             
                end
         
     | 
| 
       59 
62 
     | 
    
         | 
| 
       60 
63 
     | 
    
         
             
                def not
         
     | 
| 
       61 
     | 
    
         
            -
                  Assertor.new( 
     | 
| 
      
 64 
     | 
    
         
            +
                  Assertor.new(handler: @handler, negated: !@negated, block: @block)
         
     | 
| 
       62 
65 
     | 
    
         
             
                end
         
     | 
| 
       63 
66 
     | 
    
         | 
| 
       64 
67 
     | 
    
         
             
                def raises?(*exception_classes, &block)
         
     | 
| 
         @@ -70,23 +73,23 @@ module Calificador 
     | 
|
| 
       70 
73 
     | 
    
         
             
                  ::Kernel.raise ::ArgumentError, "Exception assert must have a block" if block.nil?
         
     | 
| 
       71 
74 
     | 
    
         | 
| 
       72 
75 
     | 
    
         
             
                  message = ::Kernel.proc do
         
     | 
| 
       73 
     | 
    
         
            -
                    actual = ::Calificador.call_formatter. 
     | 
| 
      
 76 
     | 
    
         
            +
                    actual = ::Calificador.call_formatter.format_value(value: @block)
         
     | 
| 
       74 
77 
     | 
    
         
             
                    "Expected #{actual} (#{@block}) to#{@negated ? " not" : ""} raise #{exception_classes.join(", ")}"
         
     | 
| 
       75 
78 
     | 
    
         
             
                  end
         
     | 
| 
       76 
79 
     | 
    
         | 
| 
       77 
80 
     | 
    
         
             
                  begin
         
     | 
| 
       78 
81 
     | 
    
         
             
                    result = block.call
         
     | 
| 
       79 
82 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
                     
     | 
| 
      
 83 
     | 
    
         
            +
                    __assert(@negated, message: message)
         
     | 
| 
       81 
84 
     | 
    
         | 
| 
       82 
85 
     | 
    
         
             
                    result
         
     | 
| 
       83 
86 
     | 
    
         
             
                  rescue *exception_classes => e
         
     | 
| 
       84 
     | 
    
         
            -
                     
     | 
| 
      
 87 
     | 
    
         
            +
                    __refute(@negated, message: __exception_details(e, message: message))
         
     | 
| 
       85 
88 
     | 
    
         
             
                    e
         
     | 
| 
       86 
89 
     | 
    
         
             
                  rescue ::Minitest::Assertion, ::SignalException, ::SystemExit
         
     | 
| 
       87 
90 
     | 
    
         
             
                    ::Kernel.raise
         
     | 
| 
       88 
91 
     | 
    
         
             
                  rescue ::Exception => e # rubocop:disable Lint/RescueException
         
     | 
| 
       89 
     | 
    
         
            -
                     
     | 
| 
      
 92 
     | 
    
         
            +
                    __assert(@negated, message: __exception_details(e, message: message))
         
     | 
| 
       90 
93 
     | 
    
         
             
                  end
         
     | 
| 
       91 
94 
     | 
    
         
             
                end
         
     | 
| 
       92 
95 
     | 
    
         | 
| 
         @@ -101,6 +104,18 @@ module Calificador 
     | 
|
| 
       101 
104 
     | 
    
         | 
| 
       102 
105 
     | 
    
         
             
                protected
         
     | 
| 
       103 
106 
     | 
    
         | 
| 
      
 107 
     | 
    
         
            +
                def __respond_to_missing?(name:, include_all:)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  __value.respond_to?(name, false)
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                def __method_missing(name:, arguments:, keywords:, block:)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  if __value.respond_to?(name)
         
     | 
| 
      
 113 
     | 
    
         
            +
                    __check(name: name, arguments: arguments, keywords: keywords, &block)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  else
         
     | 
| 
      
 115 
     | 
    
         
            +
                    super
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
       104 
119 
     | 
    
         
             
                def __value
         
     | 
| 
       105 
120 
     | 
    
         
             
                  if @value.equal?(MISSING)
         
     | 
| 
       106 
121 
     | 
    
         
             
                    ::Kernel.raise ::StandardError, "No block set for assertion" if @block.nil?
         
     | 
| 
         @@ -111,24 +126,53 @@ module Calificador 
     | 
|
| 
       111 
126 
     | 
    
         
             
                  @value
         
     | 
| 
       112 
127 
     | 
    
         
             
                end
         
     | 
| 
       113 
128 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
                def __check( 
     | 
| 
      
 129 
     | 
    
         
            +
                def __check(name:, message: nil, arguments: [], keywords: {}, &block)
         
     | 
| 
       115 
130 
     | 
    
         
             
                  @triggered = true
         
     | 
| 
       116 
131 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
                  result =  
     | 
| 
      
 132 
     | 
    
         
            +
                  result = begin
         
     | 
| 
      
 133 
     | 
    
         
            +
                    __value.send(name, *arguments, **keywords, &block)
         
     | 
| 
      
 134 
     | 
    
         
            +
                  rescue ::StandardError => e
         
     | 
| 
      
 135 
     | 
    
         
            +
                    raise ::Minitest::UnexpectedError, e
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
       118 
137 
     | 
    
         | 
| 
       119 
138 
     | 
    
         
             
                  message ||= ::Kernel.proc do
         
     | 
| 
       120 
     | 
    
         
            -
                    actual = ::Calificador.call_formatter. 
     | 
| 
       121 
     | 
    
         
            -
                    call = ::Calificador.call_formatter. 
     | 
| 
      
 139 
     | 
    
         
            +
                    actual = ::Calificador.call_formatter.format_value(value: __value)
         
     | 
| 
      
 140 
     | 
    
         
            +
                    call = ::Calificador.call_formatter.format_method(name: name, arguments: arguments, keywords: keywords)
         
     | 
| 
       122 
141 
     | 
    
         
             
                    "Expected #{actual} (#{__value.class}) to#{@negated ? " not" : ""} #{call}"
         
     | 
| 
       123 
142 
     | 
    
         
             
                  end
         
     | 
| 
       124 
143 
     | 
    
         | 
| 
       125 
144 
     | 
    
         
             
                  if @negated
         
     | 
| 
       126 
     | 
    
         
            -
                     
     | 
| 
      
 145 
     | 
    
         
            +
                    __refute(result, message: message)
         
     | 
| 
       127 
146 
     | 
    
         
             
                  else
         
     | 
| 
       128 
     | 
    
         
            -
                     
     | 
| 
      
 147 
     | 
    
         
            +
                    __assert(result, message: message)
         
     | 
| 
       129 
148 
     | 
    
         
             
                  end
         
     | 
| 
       130 
149 
     | 
    
         | 
| 
       131 
150 
     | 
    
         
             
                  result
         
     | 
| 
       132 
151 
     | 
    
         
             
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                def __assert(condition, message:)
         
     | 
| 
      
 154 
     | 
    
         
            +
                  message = message.call if !condition && message.is_a?(::Proc)
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                  @handler.assert(condition, message)
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                def __refute(condition, message:)
         
     | 
| 
      
 160 
     | 
    
         
            +
                  message = message.call if condition && message.is_a?(::Proc)
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                  @handler.refute(condition, message)
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                def __exception_details(exception, message:)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  message = message.call if message.is_a?(::Proc)
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                  [
         
     | 
| 
      
 169 
     | 
    
         
            +
                    message,
         
     | 
| 
      
 170 
     | 
    
         
            +
                    "Class: <#{exception.class}>",
         
     | 
| 
      
 171 
     | 
    
         
            +
                    "Message: #{exception.message}",
         
     | 
| 
      
 172 
     | 
    
         
            +
                    "---Backtrace---",
         
     | 
| 
      
 173 
     | 
    
         
            +
                    exception.backtrace.map(&:to_s),
         
     | 
| 
      
 174 
     | 
    
         
            +
                    "---------------",
         
     | 
| 
      
 175 
     | 
    
         
            +
                  ].flatten.join("\n")
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
       133 
177 
     | 
    
         
             
              end
         
     | 
| 
       134 
178 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,67 +1,69 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            using Calificador::Util::CoreExtensions
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
3 
     | 
    
         
             
            module Calificador
         
     | 
| 
       6 
4 
     | 
    
         
             
              module Build
         
     | 
| 
       7 
5 
     | 
    
         
             
                class AttributeEvaluator
         
     | 
| 
       8 
6 
     | 
    
         
             
                  EVALUATING = Object.new.freeze
         
     | 
| 
       9 
7 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                  class Proxy
         
     | 
| 
       11 
     | 
    
         
            -
                    def initialize( 
     | 
| 
       12 
     | 
    
         
            -
                       
     | 
| 
       13 
     | 
    
         
            -
                    end
         
     | 
| 
      
 8 
     | 
    
         
            +
                  class Proxy < Util::ProxyObject
         
     | 
| 
      
 9 
     | 
    
         
            +
                    def initialize(evaluator:)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      super()
         
     | 
| 
       14 
11 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                       
     | 
| 
       17 
     | 
    
         
            -
                      @delegate.create_object(key: key)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      @evaluator = evaluator
         
     | 
| 
      
 13 
     | 
    
         
            +
                      @environment_proxy = evaluator.environment.proxy
         
     | 
| 
       18 
14 
     | 
    
         
             
                    end
         
     | 
| 
       19 
15 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                     
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                    protected
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    def __respond_to_missing?(name:, include_all:)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @evaluator.attribute?(name: name) || @environment_proxy.respond_to?(name)
         
     | 
| 
       22 
20 
     | 
    
         
             
                    end
         
     | 
| 
       23 
21 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                    def  
     | 
| 
       25 
     | 
    
         
            -
                      if @ 
     | 
| 
      
 22 
     | 
    
         
            +
                    def __method_missing(name:, arguments:, keywords:, block:)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      if @evaluator.attribute?(name: name)
         
     | 
| 
       26 
24 
     | 
    
         
             
                        raise ArgumentError, "Getter must not be called with arguments" unless arguments.empty?
         
     | 
| 
       27 
25 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                        @ 
     | 
| 
      
 26 
     | 
    
         
            +
                        @evaluator.value(name: name)
         
     | 
| 
       29 
27 
     | 
    
         
             
                      else
         
     | 
| 
       30 
     | 
    
         
            -
                         
     | 
| 
      
 28 
     | 
    
         
            +
                        @environment_proxy.__send__(name, *arguments, **keywords, &block)
         
     | 
| 
       31 
29 
     | 
    
         
             
                      end
         
     | 
| 
       32 
30 
     | 
    
         
             
                    end
         
     | 
| 
       33 
31 
     | 
    
         
             
                  end
         
     | 
| 
       34 
32 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                  attr_reader :attributes, :values
         
     | 
| 
      
 33 
     | 
    
         
            +
                  attr_reader :attributes, :values, :environment
         
     | 
| 
       36 
34 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
                  def initialize( 
     | 
| 
       38 
     | 
    
         
            -
                    @ 
     | 
| 
      
 35 
     | 
    
         
            +
                  def initialize(key:, environment:)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @key = key
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @environment = environment
         
     | 
| 
       39 
38 
     | 
    
         
             
                    @attributes = {}
         
     | 
| 
       40 
39 
     | 
    
         
             
                    @values = {}
         
     | 
| 
       41 
     | 
    
         
            -
                    @proxy = Proxy.new( 
     | 
| 
      
 40 
     | 
    
         
            +
                    @proxy = Proxy.new(evaluator: self)
         
     | 
| 
       42 
41 
     | 
    
         
             
                  end
         
     | 
| 
       43 
42 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                  def  
     | 
| 
       45 
     | 
    
         
            -
                    @ 
     | 
| 
       46 
     | 
    
         
            -
                  end
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                  def add_values(values)
         
     | 
| 
       49 
     | 
    
         
            -
                    @values.merge!(values)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def add_attribute(attribute)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @attributes[attribute.name] = attribute
         
     | 
| 
       50 
45 
     | 
    
         
             
                  end
         
     | 
| 
       51 
46 
     | 
    
         | 
| 
       52 
47 
     | 
    
         
             
                  def add_attributes(attributes)
         
     | 
| 
       53 
48 
     | 
    
         
             
                    attributes.each do |attribute|
         
     | 
| 
       54 
     | 
    
         
            -
                       
     | 
| 
      
 49 
     | 
    
         
            +
                      add_attribute(attribute)
         
     | 
| 
       55 
50 
     | 
    
         
             
                    end
         
     | 
| 
       56 
51 
     | 
    
         
             
                  end
         
     | 
| 
       57 
52 
     | 
    
         | 
| 
      
 53 
     | 
    
         
            +
                  def add_values(values)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @values.merge!(values)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
       58 
57 
     | 
    
         
             
                  def value(name:)
         
     | 
| 
       59 
58 
     | 
    
         
             
                    result = @values.fetch(name) do
         
     | 
| 
       60 
59 
     | 
    
         
             
                      @values[name] = EVALUATING
         
     | 
| 
       61 
60 
     | 
    
         | 
| 
       62 
61 
     | 
    
         
             
                      begin
         
     | 
| 
       63 
     | 
    
         
            -
                         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 62 
     | 
    
         
            +
                        attribute = @attributes.fetch(name) do
         
     | 
| 
      
 63 
     | 
    
         
            +
                          raise KeyError, "Could not find attribute '#{name}' for factory #{@key}"
         
     | 
| 
      
 64 
     | 
    
         
            +
                        end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                        @values[name] = evaluate(&attribute.config)
         
     | 
| 
       65 
67 
     | 
    
         
             
                      rescue StandardError
         
     | 
| 
       66 
68 
     | 
    
         
             
                        @values.delete(name)
         
     | 
| 
       67 
69 
     | 
    
         
             
                        raise
         
     | 
| 
         @@ -73,10 +75,12 @@ module Calificador 
     | 
|
| 
       73 
75 
     | 
    
         
             
                    result
         
     | 
| 
       74 
76 
     | 
    
         
             
                  end
         
     | 
| 
       75 
77 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                  def evaluate(*arguments,  
     | 
| 
       77 
     | 
    
         
            -
                     
     | 
| 
      
 78 
     | 
    
         
            +
                  def evaluate(*arguments, &block)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    @proxy.instance_exec(*arguments, &block)
         
     | 
| 
       78 
80 
     | 
    
         
             
                  end
         
     | 
| 
       79 
81 
     | 
    
         | 
| 
      
 82 
     | 
    
         
            +
                  ruby2_keywords :evaluate
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
       80 
84 
     | 
    
         
             
                  def attribute?(name:)
         
     | 
| 
       81 
85 
     | 
    
         
             
                    @attributes.key?(name)
         
     | 
| 
       82 
86 
     | 
    
         
             
                  end
         
     |