Back to Repositories

Testing Pry REPL Integration in BetterErrors

This test suite validates the Pry REPL integration within BetterErrors, focusing on line continuation and standard REPL functionality. It ensures proper handling of interactive debugging sessions and exception contexts.

Test Coverage Overview

The test suite comprehensively covers the Pry REPL implementation in BetterErrors, focusing on:

  • Line continuation behavior for multi-line code input
  • REPL provider compliance through shared examples
  • Exception context handling
  • Binding state preservation

Implementation Analysis

The testing approach utilizes RSpec’s context isolation and mocking capabilities to validate REPL behavior. The suite employs before/after hooks for proper constant management and leverages aggregate failures for comprehensive assertions.

  • Dynamic constant handling for isolation
  • Binding context manipulation
  • Multi-stage input validation

Technical Details

  • RSpec as the testing framework
  • Shared examples for REPL provider validation
  • Ruby version-specific output handling
  • Exception context simulation
  • Dynamic constant management

Best Practices Demonstrated

The test suite exemplifies several testing best practices including proper isolation, comprehensive edge case coverage, and modular test organization. It demonstrates effective use of RSpec features and careful management of test state.

  • Proper test isolation through constant cleanup
  • Shared example usage for consistent validation
  • Version-specific test handling
  • Explicit context management

bettererrors/better_errors

spec/better_errors/repl/pry_spec.rb

            
require "spec_helper"
require "better_errors/repl/shared_examples"

if defined? ::Pry
  RSpec.describe 'BetterErrors::REPL::Pry' do
    before(:all) do
      load "better_errors/repl/pry.rb"
    end
    after(:all) do
      # Ensure the Pry REPL file has not been included. If this is not done,
      # the constant leaks into other examples.
      # In practice, this constant is only defined if `use_pry!` is called and then the
      # REPL is used, causing BetterErrors::REPL to require the file.
      BetterErrors::REPL.send(:remove_const, :Pry)
    end

    let(:fresh_binding) {
      local_a = 123
      binding
    }

    let!(:exception) { raise ZeroDivisionError, "you divided by zero you silly goose!" rescue $! }

    let(:repl) { BetterErrors::REPL::Pry.new(fresh_binding, exception) }

    it "does line continuation", :aggregate_failures do
      output, prompt, filled = repl.send_input ""
      expect(output).to eq("=> nil\n")
      expect(prompt).to eq(">>")
      expect(filled).to eq("")

      output, prompt, filled = repl.send_input "def f(x)"
      expect(output).to eq("")
      expect(prompt).to eq("..")
      expect(filled).to eq("  ")

      output, prompt, filled = repl.send_input "end"
      if RUBY_VERSION >= "2.1.0"
        expect(output).to eq("=> :f\n")
      else
        expect(output).to eq("=> nil\n")
      end
      expect(prompt).to eq(">>")
      expect(filled).to eq("")
    end

    it_behaves_like "a REPL provider"
  end
else
  puts "Skipping Pry specs because pry is not in the bundle"
end