diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..2b354a7
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,21 @@
+name: Test
+on: [push, pull_request]
+jobs:
+ test:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest]
+ ruby: ['3.0', '3.1', '3.2']
+ name: test (Ruby ${{ matrix.ruby }} on ${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Check out
+ uses: actions/checkout@v3
+ - name: Set up Ruby ${{ matrix.ruby }}
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
+ - name: Run tests
+ run: bundle exec rake
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..20abc76
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+# macOS
+.DS_Store
+
+# direnv
+.direnv
+.envrc
+
+# Editors
+.nova
+.vscode
+*.sublime*
+
+# Ruby
+gems.locked
+pkg/*
+*.gem
+.bundle
+.yardoc
diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 0000000..a3ec5a4
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+3.2
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..6b011b3
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+## Main
+
+#### Initial Implementation
+* Require Ruby 3.0
+* Substitution of instance variables
+* Substitution of global variables
+* Helper for Minitest spec notation
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..5d62dd8
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2013 Sven Schwyn
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c4a4b8e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,145 @@
+[![Version](https://img.shields.io/gem/v/minitest-substitute.svg?style=flat)](https://rubygems.org/gems/minitest-substitute)
+[![Tests](https://img.shields.io/github/actions/workflow/status/svoop/minitest-substitute/test.yml?style=flat&label=tests)](https://github.com/svoop/minitest-substitute/actions?workflow=Test)
+[![Code Climate](https://img.shields.io/codeclimate/maintainability/svoop/minitest-substitute.svg?style=flat)](https://codeclimate.com/github/svoop/minitest-substitute/)
+[![Donorbox](https://img.shields.io/badge/donate-on_donorbox-yellow.svg)](https://donorbox.org/bitcetera)
+
+# Minitest::Substitute
+
+Simple Minitest helper to replace values such as an instance variable of an object or an environment variable for the duration of a block or a group of tests.
+
+This comes in very handy when you have to derive from default configuration in order to test some aspects of your code.
+
+* [Homepage](https://github.com/svoop/minitest-substitute)
+* [API](https://www.rubydoc.info/gems/minitest-substitute)
+* Author: [Sven Schwyn - Bitcetera](https://bitcetera.com)
+
+## Install
+
+This gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:
+
+```
+gem cert --add <(curl -Ls https://raw.github.com/svoop/minitest-substitute/main/certs/svoop.pem)
+```
+
+Add the following to the Gemfile or gems.rb of your [Bundler](https://bundler.io) powered Ruby project:
+
+```ruby
+gem 'minitest-substitute'
+```
+
+And then install the bundle:
+
+```
+bundle install --trust-policy MediumSecurity
+```
+
+Finally, require this gem in your `test_helper.rb` or `spec_helper.rb`:
+
+```ruby
+require 'minitest/substitute'
+```
+
+## Usage
+
+This lightweight gem implements features on a "as needed" basis, as of now:
+
+* substitution of instance variables
+* substitution of global variables
+
+Please [create an issue describing your use case](https://github.com/svoop/minitest-substitute/issues) in case you need more features such as the substitution of class variables or substitution via accessor methods.
+
+### Block
+
+To substitute the value of an instance variable for the duration of a block:
+
+```ruby
+class Config
+ def initialize
+ @version = 1
+ end
+end
+
+Config.instance_variable_get('@version') # => 1
+with '@version', 2, on: Config do
+ Config.instance_variable_get('@version') # => 2
+end
+Config.instance_variable_get('@version') # => 1
+```
+
+Same goes for global variables:
+
+```ruby
+$verbose = false # => false
+with '$verbose', true do
+ $verbose # => true
+end
+$verbose # => false
+```
+
+And it works for hashes as well which comes in handy when you have to temporarily override the value of an environment variable:
+
+```ruby
+ENV['EDITOR'] # => 'vi'
+with "ENV['EDITOR']", 'nano' do
+ ENV['EDITOR'] # => 'nano'
+end
+ENV['EDITOR'] # => 'vi'
+```
+
+### Group of Tests
+
+When using spec notation, you can change a value for all tests within a `describe` group:
+
+```ruby
+class Config
+ def initialize
+ @version = 1
+ end
+end
+
+describe Config do
+ subject do
+ Config.new
+ end
+
+ describe 'original version' do
+ it "returns the original version" do
+ _(subject.instance_variable_get('@version')).must_equal 1
+ end
+ end
+
+ describe 'sustituted version' do
+ with '@version', 2, on: Config
+
+ it "returns the substituted version" do
+ _(subject.instance_variable_get('@version')).must_equal 2
+ end
+ end
+end
+```
+
+For consistency with other Minitest helpers, the following alternative does exactly the same:
+
+```ruby
+with '@version', on: Config do
+ 2
+end
+```
+
+(The spec integration is borrowed from [minitest-around](https://rubygems.org/gems/minitest-around) for elegance and compatibility.)
+
+## Development
+
+To install the development dependencies and then run the test suite:
+
+```
+bundle install
+bundle exec rake # run tests once
+bundle exec guard # run tests whenever files are modified
+```
+
+You're welcome to [submit issues](https://github.com/svoop/minitest-substitute/issues) and contribute code by [forking the project and submitting pull requests](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
+
+## License
+
+The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
diff --git a/bin/console b/bin/console
new file mode 100755
index 0000000..2ecbcfc
--- /dev/null
+++ b/bin/console
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require "bundler/setup"
+require "minitest/substitute"
+
+# You can add fixtures and/or initialization code here to make experimenting
+# with your gem easier. You can also use a different console, if you like.
+
+require "irb"
+IRB.start(__FILE__)
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 0000000..dce67d8
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+set -euo pipefail
+IFS=$'\n\t'
+set -vx
+
+bundle install
+
+# Do any other automated setup that you need to do here
diff --git a/certs/svoop.pem b/certs/svoop.pem
new file mode 100644
index 0000000..b77d81b
--- /dev/null
+++ b/certs/svoop.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhydWJ5
+L0RDPWJpdGNldGVyYS9EQz1jb20wHhcNMjIxMTA2MTIzNjUwWhcNMjMxMTA2MTIz
+NjUwWjAjMSEwHwYDVQQDDBhydWJ5L0RDPWJpdGNldGVyYS9EQz1jb20wggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcLg+IHjXYaUlTSU7R235lQKD8ZhEe
+KMhoGlSUonZ/zo1OT3KXcqTCP1iMX743xYs6upEGALCWWwq+nxvlDdnWRjF3AAv7
+ikC+Z2BEowjyeCCT/0gvn4ohKcR0JOzzRaIlFUVInlGSAHx2QHZ2N8ntf54lu7nd
+L8CiDK8rClsY4JBNGOgH9UC81f+m61UUQuTLxyM2CXfAYkj/sGNTvFRJcNX+nfdC
+hM9r2kH1+7wsa8yG7wJ2IkrzNACD8v84oE6qVusN8OLEMUI/NaEPVPbw2LUM149H
+PVa0i729A4IhroNnFNmw4wOC93ARNbM1+LW36PLMmKjKudf5Exg8VmDVAgMBAAGj
+dzB1MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSfK8MtR62mQ6oN
+yoX/VKJzFjLSVDAdBgNVHREEFjAUgRJydWJ5QGJpdGNldGVyYS5jb20wHQYDVR0S
+BBYwFIEScnVieUBiaXRjZXRlcmEuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAYG2na
+ye8OE2DANQIFM/xDos/E4DaPWCJjX5xvFKNKHMCeQYPeZvLICCwyw2paE7Otwk6p
+uvbg2Ks5ykXsbk5i6vxDoeeOLvmxCqI6m+tHb8v7VZtmwRJm8so0eSX0WvTaKnIf
+CAn1bVUggczVdNoBXw9WAILKyw9bvh3Ft740XZrR74sd+m2pGwjCaM8hzLvrVbGP
+DyYhlBeRWyQKQ0WDIsiTSRhzK8HwSTUWjvPwx7SEdIU/HZgyrk0ETObKPakVu6bH
+kAyiRqgxF4dJviwtqI7mZIomWL63+kXLgjOjMe1SHxfIPo/0ji6+r1p4KYa7o41v
+fwIwU1MKlFBdsjkd
+-----END CERTIFICATE-----
diff --git a/checksums/minitest-flash-0.1.0.gem.sha512 b/checksums/minitest-flash-0.1.0.gem.sha512
new file mode 100644
index 0000000..2b30a77
--- /dev/null
+++ b/checksums/minitest-flash-0.1.0.gem.sha512
@@ -0,0 +1 @@
+c240bed743a19830b5eeeb6682ff03b00944e13dd24ffdbd31810fd2e9f870c9039cfdef37d055053770e9b184508dbd4e80db974512d5018d2384d355871c61
diff --git a/doc/green.mp3 b/doc/green.mp3
new file mode 100644
index 0000000..73e2f0f
Binary files /dev/null and b/doc/green.mp3 differ
diff --git a/doc/red.mp3 b/doc/red.mp3
new file mode 100644
index 0000000..412e5f4
Binary files /dev/null and b/doc/red.mp3 differ
diff --git a/doc/screenshot.gif b/doc/screenshot.gif
new file mode 100644
index 0000000..ffd4293
Binary files /dev/null and b/doc/screenshot.gif differ
diff --git a/gems.rb b/gems.rb
new file mode 100644
index 0000000..be173b2
--- /dev/null
+++ b/gems.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gemspec
diff --git a/guardfile.rb b/guardfile.rb
new file mode 100644
index 0000000..5eb22ed
--- /dev/null
+++ b/guardfile.rb
@@ -0,0 +1,7 @@
+clearing :on
+
+guard :minitest do
+ watch(%r{^spec/(.+)_spec\.rb})
+ watch(%r{^lib/(.+)\.rb}) { "spec/lib/#{_1[1]}_spec.rb" }
+ watch(%r{^spec/spec_helper.rb}) { 'spec' }
+end
diff --git a/lib/minitest/substitute.rb b/lib/minitest/substitute.rb
new file mode 100644
index 0000000..c565d7b
--- /dev/null
+++ b/lib/minitest/substitute.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require_relative 'substitute/version'
+
+require_relative 'substitute/with'
+require_relative 'substitute/spec'
+
+include Minitest::Substitute::With
diff --git a/lib/minitest/substitute/spec.rb b/lib/minitest/substitute/spec.rb
new file mode 100644
index 0000000..d7b278f
--- /dev/null
+++ b/lib/minitest/substitute/spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'minitest/spec'
+
+Minitest::Spec::DSL.class_eval do
+ class Substitutor
+ include Minitest::Substitute::With
+ end
+
+ # Substitute the variable value for the duration of the current description
+ #
+ # @param variable [String] instance or global variable name
+ # @param substitute [Object] temporary substitution value
+ # @param on [Object, nil] substitute in the context of this object
+ # @yield temporary substitution value (takes precedence over +substitute+ param)
+ def with(variable, substitute=nil, on: self)
+ before do
+ substitute = yield if block_given?
+ Substitutor.send(:commit_substitution, variable, substitute, on: on)
+ end
+ after do
+ Substitutor.send(:rollback_substitution, variable, on: on)
+ end
+ end
+
+ # Minitest does not support multiple before/after blocks
+ remove_method :before
+ def before(_type=nil, &block)
+ include(Module.new do
+ define_method(:setup) do
+ super()
+ instance_eval &block
+ end
+ end) # .then &:include
+ end
+
+ remove_method :after
+ def after(_type=nil, &block)
+ include(Module.new do
+ define_method(:teardown) do
+ instance_eval &block
+ ensure
+ super()
+ end
+ end) #.then &:include
+ end
+end
diff --git a/lib/minitest/substitute/version.rb b/lib/minitest/substitute/version.rb
new file mode 100644
index 0000000..c15c281
--- /dev/null
+++ b/lib/minitest/substitute/version.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Minitest
+ module Substitute
+ VERSION = '0.1.0'
+ end
+end
diff --git a/lib/minitest/substitute/with.rb b/lib/minitest/substitute/with.rb
new file mode 100644
index 0000000..0d02032
--- /dev/null
+++ b/lib/minitest/substitute/with.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Minitest
+ module Substitute
+ module With
+ class << self
+ attr_accessor :original
+ end
+
+ # Substitute the variable value for the duration of the given block
+ #
+ # @param variable [String] instance or global variable name
+ # @param substitute [Object] temporary substitution value
+ # @param on [Object, nil] substitute in the context of this object
+ # @yield block during which the substitution is made
+ # @return [Object] return value of the yielded block
+ def with(variable, substitute, on: self)
+ commit_substitution(variable, substitute, on: on)
+ yield.tap do
+ rollback_substitution(variable, on: on)
+ end
+ end
+
+ private
+
+ def commit_substitution(variable, substitute, on:)
+ Minitest::Substitute::With.original = on.instance_eval variable.to_s
+ on.instance_eval "#{variable} = substitute"
+ end
+
+ def rollback_substitution(variable, on:)
+ on.instance_eval "#{variable} = Minitest::Substitute::With.original"
+ end
+ end
+ end
+end
diff --git a/minitest-substitute.gemspec b/minitest-substitute.gemspec
new file mode 100644
index 0000000..320fc4d
--- /dev/null
+++ b/minitest-substitute.gemspec
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require_relative 'lib/minitest/substitute/version'
+
+Gem::Specification.new do |spec|
+ spec.name = 'minitest-substitute'
+ spec.version = Minitest::Substitute::VERSION
+ spec.summary = 'Substitute values for the duration of a block or a group of tests'
+ spec.description = <<~END
+ END
+ spec.authors = ['Sven Schwyn']
+ spec.email = ['ruby@bitcetera.com']
+ spec.homepage = 'https://github.com/svoop/minitest-substitute'
+ spec.license = 'MIT'
+
+ spec.metadata = {
+ 'homepage_uri' => spec.homepage,
+ 'changelog_uri' => 'https://github.com/svoop/minitest-substitute/blob/main/CHANGELOG.md',
+ 'source_code_uri' => 'https://github.com/svoop/minitest-substitute',
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/minitest-substitute',
+ 'bug_tracker_uri' => 'https://github.com/svoop/minitest-substitute/issues'
+ }
+
+ spec.files = Dir['lib/**/*']
+ spec.require_paths = %w(lib)
+
+ spec.cert_chain = ["certs/svoop.pem"]
+ spec.signing_key = File.expand_path(ENV['GEM_SIGNING_KEY']) if ENV['GEM_SIGNING_KEY']
+
+ spec.extra_rdoc_files = Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt']
+ spec.rdoc_options += [
+ '--title', 'Minitest::Substitute',
+ '--main', 'README.md',
+ '--line-numbers',
+ '--inline-source',
+ '--quiet'
+ ]
+
+ spec.required_ruby_version = '>= 3.0.0'
+
+ spec.add_runtime_dependency 'minitest', '~> 5'
+
+ spec.add_development_dependency 'debug'
+ spec.add_development_dependency 'rake'
+ spec.add_development_dependency 'minitest'
+ spec.add_development_dependency 'minitest-flash'
+ spec.add_development_dependency 'minitest-focus'
+ spec.add_development_dependency 'guard'
+ spec.add_development_dependency 'guard-minitest'
+ spec.add_development_dependency 'yard'
+end
diff --git a/rakefile.rb b/rakefile.rb
new file mode 100644
index 0000000..48fe8d3
--- /dev/null
+++ b/rakefile.rb
@@ -0,0 +1,30 @@
+require 'bundler/gem_tasks'
+
+require 'rake/testtask'
+
+Rake::TestTask.new do |t|
+ t.libs << 'lib'
+ t.test_files = FileList['spec/lib/**/*_spec.rb']
+ t.verbose = false
+ t.warning = !ENV['RUBYOPT']&.match?(/-W0/)
+end
+
+namespace :yard do
+ desc "Run local YARD documentation server"
+ task :server do
+ `rm -rf ./.yardoc`
+ Thread.new do
+ sleep 2
+ `open http://localhost:8808`
+ end
+ `yard server -r`
+ end
+end
+
+Rake::Task[:test].enhance do
+ if ENV['RUBYOPT']&.match?(/-W0/)
+ puts "⚠️ Ruby warnings are disabled, remove -W0 from RUBYOPT to enable."
+ end
+end
+
+task default: :test
diff --git a/spec/factory.rb b/spec/factory.rb
new file mode 100644
index 0000000..3a9e8d8
--- /dev/null
+++ b/spec/factory.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class Config
+ def initialize
+ @version = 1
+ end
+end
+
+$_spec_config_instance = Config.new
+$_spec_global_variable = :original
diff --git a/spec/lib/minitest/substitute/spec_spec.rb b/spec/lib/minitest/substitute/spec_spec.rb
new file mode 100644
index 0000000..d22ee3c
--- /dev/null
+++ b/spec/lib/minitest/substitute/spec_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require_relative '../../../spec_helper'
+require_relative '../../../factory'
+
+describe :with do
+ 10.times do # test value reset even though order is random
+ describe "instance variable" do
+ context 'untouched' do
+ it "returns the original value" do
+ _($_spec_config_instance.instance_variable_get(:@version)).must_equal 1
+ end
+ end
+
+ context 'substituted' do
+ with '@version', 2, on: $_spec_config_instance
+
+ it "returns the substitute value" do
+ _($_spec_config_instance.instance_variable_get(:@version)).must_equal 2
+ end
+ end
+ end
+ end
+
+ 10.times do # test value reset even though order is random
+ describe "global variable" do
+ context 'untouched' do
+ it "returns the original value" do
+ _($_spec_global_variable).must_equal :original
+ end
+ end
+
+ context 'substituted' do
+ with "$_spec_global_variable", 'oggy'
+
+ it "returns the substitute value" do
+ _($_spec_global_variable).must_equal 'oggy'
+ end
+ end
+ end
+ end
+
+ 10.times do # test value reset even though order is random
+ describe "environment variable" do
+ context 'untouched' do
+ it "returns the original value" do
+ _(ENV['WITH_SPEC_ENV_VAR']).must_be :nil?
+ end
+ end
+
+ context 'substituted' do
+ with "ENV['WITH_SPEC_ENV_VAR']", 'foobar'
+
+ it "returns the substitute value" do
+ _(ENV['WITH_SPEC_ENV_VAR']).must_equal 'foobar'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/minitest/substitute/version_spec.rb b/spec/lib/minitest/substitute/version_spec.rb
new file mode 100644
index 0000000..a8773bf
--- /dev/null
+++ b/spec/lib/minitest/substitute/version_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative '../../../spec_helper'
+
+describe Minitest::Substitute::VERSION do
+ it "must be defined" do
+ _(Minitest::Substitute::VERSION).wont_be_nil
+ end
+end
diff --git a/spec/lib/minitest/substitute/with_spec.rb b/spec/lib/minitest/substitute/with_spec.rb
new file mode 100644
index 0000000..d9073e6
--- /dev/null
+++ b/spec/lib/minitest/substitute/with_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require_relative '../../../spec_helper'
+require_relative '../../../factory'
+
+describe :with do
+ describe "instance variable" do
+ it "substitutes the value for the duration of a block" do
+ _($_spec_config_instance.instance_variable_get(:@version)).must_equal 1
+ with '@version', 2, on: $_spec_config_instance do
+ _($_spec_config_instance.instance_variable_get(:@version)).must_equal 2
+ end
+ _($_spec_config_instance.instance_variable_get(:@version)).must_equal 1
+ end
+ end
+
+ describe "global variable" do
+ it "substitutes the value for the duration of a block" do
+ _($_spec_global_variable).must_equal :original
+ with "$_spec_global_variable", 'oggy' do
+ _($_spec_global_variable).must_equal 'oggy'
+ end
+ _($_spec_global_variable).must_equal :original
+ end
+ end
+
+ describe "environment variable" do
+ it "substitutes the value for the duration of a block" do
+ _(ENV['WITH_SPEC_ENV_VAR']).must_be :nil?
+ with "ENV['WITH_SPEC_ENV_VAR']", 'foobar' do
+ _(ENV['WITH_SPEC_ENV_VAR']).must_equal 'foobar'
+ end
+ _(ENV['WITH_SPEC_ENV_VAR']).must_be :nil?
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..6565587
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+gem 'minitest'
+
+require 'pathname'
+require 'debug'
+
+require 'minitest/autorun'
+require Pathname(__dir__).join('..', 'lib', 'minitest', 'substitute')
+
+require 'minitest/focus'
+
+class Minitest::Spec
+ class << self
+ alias_method :context, :describe
+ end
+end