Skip to content
bparity

Behavioral verification for Ruby

Change the code.
Keep the behavior.

Your legacy code has a lot to teach its replacement. Capture what it does, then check the new implementation against the same behavior.

Different APIs. One behavioral contract. Slugifier example

Legacy APIRecord once

# An instance method
slugifier = Legacy::Slugifier.new
slugifier.call("Hello World")

# => "hello-world"

Replacement APIVerify independently

# A module. A keyword argument.
Replacement::Slugs.generate(
  text: "Hello World"
)
# => "hello-world"
Same observed results, through an adapter
"Hello World"
"hello-world"
" Hi! "
"hi"
""
ArgumentError: "blank"

The replacement can change shape. The recorded behavior stays the reference.

Ruby 3.1+ MIT licensed

Behavior is more than a return value.

Keep the details that callers depend on, including the ones a happy-path test can miss.

  • Arguments
  • Return values
  • Errors
  • Yields
  • Mutations
  • State
  • External calls

Keep the evidence.
Leave the legacy.

Record while the old environment still runs. A portable Specification Bundle becomes the reference for everything that comes next.

  1. 1

    Capture the original

    Define the public boundary and run your RSpec or Minitest suite. Combine recorded traces and source evidence into a checked bundle.

    record + synthesize

  2. 2

    Map the replacement

    Use a small Ruby adapter to connect recorded operations to your new API. Classes, method names, and argument shapes can all change.

    .bparity/adapter.rb

  3. 3

    Check what changed

    Verify with just the bundle, adapter, and replacement. Inspect differences and declared waivers in Markdown, JSON, JUnit XML, or HTML.

    bparity verify

Know what passed.
And what was checked.

Start with recorded examples. Add property checks, finite-domain exploration, model comparison, or Z3 proofs when the required inputs are available.

Every formal result reports its scope, assumptions, and exclusions. Inconclusive results stay inconclusive.

Read the assurance limits
F0

Trace replay

The recorded examples match.

F1

Contract & property checks

Executed inputs satisfy declared predicates.

F2

Bounded exhaustive comparison

No difference within the reported finite domain.

F3

Finite-state model comparison

The projected learned models conform.

F4

Translation-validated Z3 proof

No difference in the supported pure fragment, under reported assumptions.

Give your rewrite
a reference point.

Start in the legacy environment, while its dependencies still work.

Follow the quick start
Add to your Gemfile
gem "bparity", github: "ydah/bparity", branch: "main"
Install and preserve the environment
bundle install
bundle package --all
bundle exec bparity init --timecapsule

Next, define your boundary, record the suite, and map your replacement. The quick start walks through each step.