Parameterized testing utility for Ruby.
Add test dependency in your Gemfile.
group :test do
# For RSpec
gem "parameterized_testing-rspec", "~> 0.2"
# For minitest/spec
gem "parameterized_testing-minitest-spec", "~> 0.2"
end
With this gem, parameterized tests can be written as follows:
# parameterized_testing-rspec example
RSpec.describe "something" do
# #parameterized is available in the context of RSpec ExampleGroup.
parameterized(:a, :b, :result) do
# Declare the concrete input corresponding to the parameters with #input.
input { [1, 2, 3] } # shorthand syntax
input { { a: 4, b: 5, result: 9 } } # verbose syntax
input { ["foo", "bar", "foobar"] }
...
# Other than that, we can write tests in the same way as a conventional RSpec ExampleGroup.
subject { a + b }
it { is_expected.to eq result }
end
end
It is important to notice that #parameterized
collects inputs by actually instance_exec
uting
the block in a dedicated context in order to embed the line number of input to #context
. In this context, all other method calls are ignored.
If you want to perform some extra procedure in the context of RSpec ExampleGroup, place them outside of #parameterized
.
There is already a gem called rspec-parameterized
that supports parameterized testing.
parameterized_testing
does not depend on parser
, proc_to_ast
, or unparser
.
Code like the example above is conceptually1 expanded as follows:
RSpec.describe "something" do
sig_a_b_result = ::ParameterizedTesting::Signature.new(:a, :b, :result)
context 'input[0] at line 6' do
let(:_input_a_b_result) { sig_a_b_result.map([1, 2, 3]) }
let(:a) { __send__(:_input_a_b_result).fetch(:a) }
let(:b) { __send__(:_input_a_b_result).fetch(:b) }
let(:result) { __send__(:_input_a_b_result).fetch(:result) }
subject { a + b }
it { is_expected.to eq result }
end
context 'input[1] at line 7' do
let(:_input_a_b_result) { sig_a_b_result.map({ a: 4, b: 5, result: 9 }) }
...
end
context 'input[2] at line 8' do
let(:_input_a_b_result) { sig_a_b_result.map(["foo", "bar", "foobar"]) }
...
end
...
end
Since each input
is declared as a block, there are no helpers such as ref
or lazy
, which were in rspec-parameterized
.
You can use the parameterization block in the same way as in the RSpec example.
describe "something" do
parameterized(:op, :result) do
input { [->(x, y) { x + y }, a + b] }
input { [->(x, y) { x * y }, a * b] }
subject { op.call(a, b) }
parameterized(:a, :b) do
input { [2, 3] }
input { [5, 7] }
it "tests something" do
_(subject).must_equal result
end
end
end
end
$ git clone https://github.com/yubrot/ruby_parameterized_testing
$ cd gems/parameterized_testing
$ bin/setup
$ bundle exec rake --tasks
Bug reports and pull requests are welcome on GitHub at https://github.com/yubrot/ruby_parameterized_testing. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.