Last active
March 14, 2025 16:03
-
-
Save thiagoa/5e8287f8a863a3bc60293005c6c00785 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Using TestOptions | |
# | |
# TestOptions is a Minitest extension that enables setup functionality | |
# at the test declaration level. This allows you to declaratively | |
# control test behavior through options passed at the class or | |
# individual test level. | |
# | |
# Use TestOptions for contextual/generic behavior that is not | |
# essential for understanding the test's purpose, such as VCR, | |
# freezing time, environment variables, etc. | |
# | |
# For example, if you've registered a VCR test helper with | |
# TestOptions, you can enable VCR for all tests in a Minitest file | |
# like this: | |
# | |
# include TestOptions.new(vcr: true) | |
# | |
# With `vcr: true`, VCR will run for all tests with the default | |
# options. | |
# | |
# You can also provide default VCR options that apply to all tests: | |
# | |
# include TestOptions.new(vcr: {match_requests_on: [:uri, :body]}) | |
# | |
# Or override those options on a per-test basis: | |
# | |
# test "my test", vcr: {match_requests_on: [:uri, :method]} do | |
# # ... | |
# end | |
# | |
# If no options are provided for a test, the default options (if any) | |
# will be used. | |
# | |
# You can also opt out of VCR for an individual test if it was | |
# enabled for all tests: | |
# | |
# include TestOptions.new(vcr: true) | |
# | |
# test "my test", vcr: false do | |
# # ... | |
# end | |
# | |
# Or even, you can opt out of VCR for the entire file but enable it on | |
# a per-test basis: | |
# | |
# include TestOptions.new | |
# | |
# test "my test 1" do | |
# # ... | |
# end | |
# | |
# test "my test 2", vcr: true do | |
# # ... | |
# end | |
# | |
### Registering Helper Extensions | |
# | |
# You can extend TestOptions by registering custom helper extensions. | |
# A helper is a module or class that responds to the following | |
# methods: | |
# | |
# Note: `test_options` refers to either the test-specific options or | |
# the default options if no specific ones are provided. It includes | |
# configuration for all registered helper extensions. | |
# | |
# - `configure_extension(test_class, test_options)` — A hook that runs | |
# before each test's setup. Use it to include modules, extend the | |
# test class, or perform other setup actions. Check whether the | |
# relevant options for your extension are present in `test_options` | |
# before applying any configuration. | |
# | |
# - `setup(test_object, test_options)` — Runs during the Minitest | |
# `setup` phase, before each test. `test_object` is the current test | |
# instance. | |
# | |
# - `teardown(test_object, test_options)` — Runs during the Minitest | |
# `teardown` phase, after each test. Works similarly to | |
# `setup`. | |
class TestOptions < Module | |
module Core | |
def test(test_name, **options, &block) | |
test_name = test_name.gsub(/\s+/, "_") | |
if options.any? | |
test_options << [test_name, options.freeze] | |
end | |
super(test_name, &block) | |
end | |
def test_options_for(current_test_name) | |
current_test_name = current_test_name.sub(/^test_/, "") | |
test_options.find do |test_name, test_options| | |
if test_name == current_test_name | |
break test_options | |
end | |
end | |
end | |
def test_options | |
@test_options ||= [] | |
end | |
end | |
class_attribute :helpers, default: [] | |
def self.register_helper(helper) | |
helpers << helper | |
end | |
def initialize(**default_options) | |
default_options = default_options.freeze | |
define_singleton_method :included do |test_class| | |
test_class.extend Core | |
get_options = ->(test_object) do | |
test_name = test_object.name | |
test_options = test_object.class.test_options_for(test_name) | |
test_options || default_options || {} | |
end | |
self.class.helpers.each do |helper| | |
helper.configure_extension(test_class, default_options) | |
test_class.setup do | |
options = get_options.call(self) | |
helper.configure_extension(test_class, options) | |
helper.setup(self, options) | |
end | |
test_class.teardown do | |
options = get_options.call(self) | |
helper.teardown(self, options) | |
end | |
end | |
end | |
end | |
end | |
TestOptions.register_helper VcrTestOptionsExtension | |
TestOptions.register_helper FreezeTimeTestOptionsExtension |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment