Repository: rails/rails
File: activesupport/lib/active_support/testing/assertions.rb (Ruby)

Code before:
      #
      # You can pass the block as a string to be evaluated in the context of
      # the block. A lambda can be passed for the block as well.
      #
      #   assert_changes -> { Status.all_good? } do
      #     post :create, params: { status: { ok: false } }
      #   end
      #
      # The assertion is useful to test side effects. The passed block can be
      # anything that can be converted to string with #to_s.
      #
      #   assert_changes :@object do
      #     @object = 42
      #   end
      #
      # The keyword arguments +:from+ and +:to+ can be given to specify the
      # expected initial value and the expected value after the block was
      # executed. The comparison is done using case equality (===), which means
      # you can specify patterns or classes:
      #
      #   # Exact value match
      #   assert_changes :@object, from: nil, to: :foo do
      #     @object = :foo
      #   end
      #
      #   # Pattern match
      #   assert_changes -> { user.token }, to: /\w{32}/ do
      #     user.generate_token
      #   end
      #
      #   # Type check
      #   assert_changes -> { current_error }, from: nil, to: RuntimeError do
      #     raise "Oops"
      #   end
      #
      # An error message can be specified.
      #
      #   assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
      #     post :create, params: { status: { incident: true } }
      #   end
      def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
        exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }

        before = exp.call
        retval = _assert_nothing_raised_or_warn("assert_changes", &block)

        unless from == UNTRACKED
          rich_message = -> do
            error = "Expected change from #{from.inspect}, got #{before.inspect}"
            error = "#{message}.\n#{error}" if message
            error

Review comment (suggestion):
I think it's better to change the wording here to avoid confusion with [Ruby pattern matching](https://docs.ruby-lang.org/en/3.4/syntax/pattern_matching_rdoc.html)
```suggestion
      #   # Case equality
```

Code after:
      #
      # You can pass the block as a string to be evaluated in the context of
      # the block. A lambda can be passed for the block as well.
      #
      #   assert_changes -> { Status.all_good? } do
      #     post :create, params: { status: { ok: false } }
      #   end
      #
      # The assertion is useful to test side effects. The passed block can be
      # anything that can be converted to string with #to_s.
      #
      #   assert_changes :@object do
      #     @object = 42
      #   end
      #
      # The keyword arguments +:from+ and +:to+ can be given to specify the
      # expected initial value and the expected value after the block was
      # executed. The comparison is done using case equality (===), which means
      # you can specify patterns or classes:
      #
      #   # Exact value match
      #   assert_changes :@object, from: nil, to: :foo do
      #     @object = :foo
      #   end
      #
      #   # Case equality
      #   assert_changes -> { user.token }, to: /\w{32}/ do
      #     user.generate_token
      #   end
      #
      #   # Type check
      #   assert_changes -> { current_error }, from: nil, to: RuntimeError do
      #     raise "Oops"
      #   end
      #
      # An error message can be specified.
      #
      #   assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
      #     post :create, params: { status: { incident: true } }
      #   end
      def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
        exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }

        before = exp.call
        retval = _assert_nothing_raised_or_warn("assert_changes", &block)

        unless from == UNTRACKED
          rich_message = -> do
            error = "Expected change from #{from.inspect}, got #{before.inspect}"
            error = "#{message}.\n#{error}" if message
            error