Module: Fix

Defined in:
lib/fix.rb,
lib/fix/doc.rb,
lib/fix/dsl.rb,
lib/fix/run.rb,
lib/fix/set.rb,
lib/fix/matcher.rb,
lib/fix/requirement.rb,
lib/fix/error/missing_subject_block.rb,
lib/fix/error/specification_not_found.rb,
lib/fix/error/invalid_specification_name.rb,
lib/fix/error/missing_specification_block.rb

Overview

The Fix framework namespace provides core functionality for managing and running test specifications. Fix offers a unique approach to testing by clearly separating specifications from their implementations.

Fix supports two primary modes of operation:

  1. Named specifications that can be stored and referenced later

  2. Anonymous specifications for immediate one-time testing

Available matchers through the Matchi library include:

  • Basic Comparison: eq, eql, be, equal

  • Type Checking: be_an_instance_of, be_a_kind_of

  • State & Changes: change(object, method).by(n), by_at_least(n), by_at_most(n), from(old).to(new), to(new)

  • Value Testing: be_within(delta).of(value), match(regex), satisfy { |value| … }

  • Exceptions: raise_exception(class)

  • State Testing: be_true, be_false, be_nil

  • Predicate Matchers: be_*, have_* (e.g., be_empty, have_key)

Examples:

Creating and running a named specification with various matchers

Fix :Calculator do
  on(:add, 0.1, 0.2) do
    it SHOULD be 0.3                     # Technically true but fails due to floating point precision
    it MUST be_an_instance_of(Float)     # Type checking
    it MUST be_within(0.0001).of(0.3)    # Proper floating point comparison
  end

  on(:divide, 1, 0) do
    it MUST raise_exception ZeroDivisionError  # Exception testing
  end
end

Fix[:Calculator].test { Calculator.new }

Using state change matchers

Fix :UserAccount do
  on(:deposit, 100) do
    it MUST change(, :balance).by(100)
    it SHOULD change(, :updated_at)
  end

  on(:update_status, :premium) do
    it MUST change(, :status).from(:basic).to(:premium)
  end
end

Using predicate matchers

Fix :Collection do
  with items: [] do
    it MUST be_empty          # Tests empty?
    it MUST_NOT have_errors   # Tests has_errors?
  end
end

Complete specification with multiple matchers

Fix :Product do
  let(:price) { 42.99 }

  it MUST be_an_instance_of Product     # Type checking
  it MUST_NOT be_nil                    # Nil checking

  on(:price) do
    it MUST be_within(0.01).of(42.99)   # Floating point comparison
  end

  with category: "electronics" do
    it MUST satisfy { |p| p.valid? }    # Custom validation

    on(:save) do
      it MUST change(product, :updated_at)  # State change
      it SHOULD_NOT raise_exception         # Exception checking
    end
  end
end

See Also:

Defined Under Namespace

Modules: Doc, Error, Matcher, Requirement Classes: Dsl, Run, Set

Class Method Summary collapse

Class Method Details

.[](name) ⇒ Fix::Set

Retrieves a previously registered specification by name.

Examples:

# Define a specification with multiple matchers
Fix :EmailValidator do
  on(:validate, "[email protected]") do
    it MUST be_valid
    it MUST_NOT raise_exception
    it SHOULD satisfy { |result| result.score > 0.8 }
  end
end

# Later, retrieve and use it
Fix[:EmailValidator].test { MyEmailValidator }

Parameters:

  • name (Symbol)

    The constant name of the specification to retrieve

Returns:

  • (Fix::Set)

    The loaded specification set ready for testing

Raises:

See Also:



141
142
143
144
145
# File 'lib/fix.rb', line 141

def self.[](name)
  raise Error::SpecificationNotFound, name unless key?(name)

  Set.load(name)
end

.key?(name) ⇒ Boolean

Checks if a specification is registered under the given name.

Examples:

Fix :Example do
  it MUST be_an_instance_of(Example)
end

Fix.key?(:Example)  #=> true
Fix.key?(:Missing)  #=> false

Parameters:

  • name (Symbol)

    The name to check for

Returns:

  • (Boolean)

    true if a specification exists with this name, false otherwise



176
177
178
# File 'lib/fix.rb', line 176

def self.key?(name)
  keys.include?(name)
end

.keysArray<Symbol>

Lists all defined specification names.

Examples:

Fix :First do; end
Fix :Second do; end

Fix.keys #=> [:First, :Second]

Returns:

  • (Array<Symbol>)

    Sorted array of registered specification names



158
159
160
# File 'lib/fix.rb', line 158

def self.keys
  Doc.constants.sort
end

.spec(name = nil, &block) ⇒ Fix::Set

Creates a new specification set, optionally registering it under a name.

Examples:

Create a named specification

Fix :StringValidator do
  on(:validate, "[email protected]") do
    it MUST be_valid_email
    it MUST satisfy { |result| result.errors.empty? }
  end
end

Create an anonymous specification

Fix do
  it MUST be_positive
  it MUST be_within(0.1).of(42.0)
end.test { 42 }

Parameters:

  • name (Symbol, nil) (defaults to: nil)

    Optional name to register the specification under. If nil, creates an anonymous specification for immediate use.

Yield Returns:

  • (void)

    Block containing the specification definition using Fix DSL

Returns:

  • (Fix::Set)

    A new specification set ready for testing

Raises:



111
112
113
114
115
# File 'lib/fix.rb', line 111

def self.spec(name = nil, &block)
  raise Error::MissingSpecificationBlock if block.nil?

  Set.build(name, &block)
end