Module: Rubyzen::Assertions

Includes:
ExpectationHelpers
Defined in:
lib/rubyzen/assertions/zen_assertions.rb,
lib/rubyzen/assertions/assert_zen_true.rb,
lib/rubyzen/assertions/assert_zen_empty.rb,
lib/rubyzen/assertions/assert_zen_false.rb

Overview

Minitest equivalents of the zen_empty / zen_true / zen_false RSpec matchers. Mixed into Minitest::Assertions by require ‘rubyzen/minitest’, so the methods are available in every Minitest::Test (and spec-style block).

All three delegate to the shared ExpectationHelpers for violation/allowlist/baseline classification and failure-message formatting. The behavior is identical to the RSpec matchers (Matchers).

Examples:

class ArchitectureTest < Minitest::Test
  def test_controllers_have_no_if_statements
    assert_zen_empty(controllers.all_methods.if_statements)
  end

  def test_repos_live_in_module
    assert_zen_true(repos) { |repo| repo.top_level_module == 'Repos' }
  end
end

Instance Method Summary collapse

Methods included from ExpectationHelpers

#classify_items, #element_name, #exception_entry_matches_item?, #formatted_matcher_groups, #item_details, #item_identifiers, #message_for_failure, #normalize_exception_entries

Instance Method Details

#assert_zen_empty(collection, message: nil, allowlist: nil, baseline: nil) ⇒ true

Asserts that a Rubyzen collection is empty (the Minitest counterpart of the zen_empty matcher).

Used in architectural lint rules to verify that no items match a forbidden pattern (e.g., no controllers call .where directly).

Examples:

Ensure no controllers use .where

assert_zen_empty(controllers.all_methods.call_sites.with_name('where'))

With a baseline for gradual adoption

assert_zen_empty(violations, baseline: ['LegacyController'])

Parameters:

  • collection (Enumerable)

    a Rubyzen collection of declarations

  • message (String, nil) (defaults to: nil)

    optional custom failure message

  • allowlist (Array<String>, nil) (defaults to: nil)

    items to permanently ignore

  • baseline (Array<String>, nil) (defaults to: nil)

    known violations for gradual adoption

Returns:

  • (true)

    when the assertion passes

Raises:

  • (Minitest::Assertion)

    when there are live violations or stale entries



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
# File 'lib/rubyzen/assertions/assert_zen_empty.rb', line 21

def assert_zen_empty(collection, message: nil, allowlist: nil, baseline: nil)
  @failure_message = nil
  @custom_message = message
  @classified_items = classify_items(collection, allowlist: allowlist, baseline: baseline)

  violations = @classified_items[:violations]
  stale_baseline = @classified_items[:stale_baseline]
  stale_allowlist = @classified_items[:stale_allowlist]

  stale_groups = []
  stale_groups << 'baseline entries' if stale_baseline.any?
  stale_groups << 'allowlist entries' if stale_allowlist.any?

  reason =
    if violations.any? && stale_groups.any?
      "Expected to be empty, but found live violations and stale #{stale_groups.join(' and ')}."
    elsif violations.any?
      if allowlist || baseline
        'Expected to be empty, but found live violations.'
      else
        'Expected to be empty, but had elements.'
      end
    elsif stale_groups.any?
      "Expected to be empty, but found stale #{stale_groups.join(' and ')}."
    end

  passed = violations.empty? && stale_baseline.empty? && stale_allowlist.empty?
  assert(passed, message_for_failure(reason || 'Expected to be empty, but had elements.'))
end

#assert_zen_false(collection, message: nil, allowlist: nil, baseline: nil) {|item| ... } ⇒ true

Asserts that a block returns false for every item in a collection (the Minitest counterpart of the zen_false matcher).

Examples:

Ensure no methods have more than 5 parameters

assert_zen_false(methods) { |m| m.parameters.size > 5 }

With a baseline for gradual adoption

assert_zen_false(classes, baseline: ['LegacyModel']) { |k| k.lines_of_code > 200 }

Parameters:

  • collection (Enumerable)

    a Rubyzen collection of declarations

  • message (String, nil) (defaults to: nil)

    optional custom failure message

  • allowlist (Array<String>, nil) (defaults to: nil)

    items to permanently ignore

  • baseline (Array<String>, nil) (defaults to: nil)

    known violations for gradual adoption

Yields:

  • (item)

    block that should return false for each item

Returns:

  • (true)

    when the assertion passes

Raises:

  • (ArgumentError)

    when no block is given

  • (Minitest::Assertion)

    when the block returns truthy for a live item



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
# File 'lib/rubyzen/assertions/assert_zen_false.rb', line 20

def assert_zen_false(collection, message: nil, allowlist: nil, baseline: nil, &block)
  raise ArgumentError, 'assert_zen_false requires a block' unless block

  @failure_message = nil
  @custom_message = message
  failing_items = Array(collection).filter { |item| block.call(item) }
  @classified_items = classify_items(failing_items, allowlist: allowlist, baseline: baseline)

  violations = @classified_items[:violations]
  stale_baseline = @classified_items[:stale_baseline]
  stale_allowlist = @classified_items[:stale_allowlist]

  stale_groups = []
  stale_groups << 'baseline entries' if stale_baseline.any?
  stale_groups << 'allowlist entries' if stale_allowlist.any?

  reason =
    if violations.any? && stale_groups.any?
      "Expected to return false for all elements, but found live violations and stale #{stale_groups.join(' and ')}."
    elsif violations.any?
      'Expected to return false for all elements.'
    elsif stale_groups.any?
      "Expected to return false for all elements, but found stale #{stale_groups.join(' and ')}."
    end

  passed = violations.empty? && stale_baseline.empty? && stale_allowlist.empty?
  assert(passed, message_for_failure(reason || 'Expected to return false for all elements.'))
end

#assert_zen_true(collection, message: nil, allowlist: nil, baseline: nil) {|item| ... } ⇒ true

Asserts that a block returns true for every item in a collection (the Minitest counterpart of the zen_true matcher).

Examples:

Ensure all methods have parameters

assert_zen_true(methods) { |m| m.parameters? }

With a custom failure message

assert_zen_true(services, message: 'All services must inherit from BaseService') { |s| s.superclass_name == 'BaseService' }

Parameters:

  • collection (Enumerable)

    a Rubyzen collection of declarations

  • message (String, nil) (defaults to: nil)

    optional custom failure message

  • allowlist (Array<String>, nil) (defaults to: nil)

    items to permanently ignore

  • baseline (Array<String>, nil) (defaults to: nil)

    known violations for gradual adoption

Yields:

  • (item)

    block that should return true for each item

Returns:

  • (true)

    when the assertion passes

Raises:

  • (ArgumentError)

    when no block is given

  • (Minitest::Assertion)

    when the block returns falsey for a live item



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
# File 'lib/rubyzen/assertions/assert_zen_true.rb', line 20

def assert_zen_true(collection, message: nil, allowlist: nil, baseline: nil, &block)
  raise ArgumentError, 'assert_zen_true requires a block' unless block

  @failure_message = nil
  @custom_message = message
  failing_items = Array(collection).filter { |item| !block.call(item) }
  @classified_items = classify_items(failing_items, allowlist: allowlist, baseline: baseline)

  violations = @classified_items[:violations]
  stale_baseline = @classified_items[:stale_baseline]
  stale_allowlist = @classified_items[:stale_allowlist]

  stale_groups = []
  stale_groups << 'baseline entries' if stale_baseline.any?
  stale_groups << 'allowlist entries' if stale_allowlist.any?

  reason =
    if violations.any? && stale_groups.any?
      "Expected to return true for all elements, but found live violations and stale #{stale_groups.join(' and ')}."
    elsif violations.any?
      'Expected to return true for all elements.'
    elsif stale_groups.any?
      "Expected to return true for all elements, but found stale #{stale_groups.join(' and ')}."
    end

  passed = violations.empty? && stale_baseline.empty? && stale_allowlist.empty?
  assert(passed, message_for_failure(reason || 'Expected to return true for all elements.'))
end