This helper library is for writing tests concisely.
You can write a test as follows.
example_with("value is zero", value: 0) { expect(value).to eq 0 }
Above is the same as below.
context "value is zero" do
let(:value) { 0 }
it { expect(value).to eq 0 }
end
That’s basically all there is to it, but I think it will be more potent when used with a custom matcher.
Example of ActiveModel validation tests using a custom matcher
class Account
include ActiveModel::Model
include ActiveModel::Attributes
attribute :name, :string
validates :name, presence: true, length: { in: 3..20 }, format: { with: /\A[0-9a-zA-Z]*\z/, message: "alphanumeric characters only" }
end
let(:account) { Account.new(name: name) }
before do
account.valid?
end
# There is no "have_error" matcher, so you need to create one.
example_with(name: " ") { expect(account).to have_error.on(:name).with(:blank) }
example_with(name: "a" * 2) { expect(account).to have_error.on(:name).with(:too_short, count: 3) }
example_with(name: "a" * 3) { expect(account).not_to have_error }
example_with(name: "a" * 20) { expect(account).not_to have_error }
example_with(name: "a" * 21) { expect(account).to have_error.on(:name).with(:too_long, count: 20) }
example_with(name: "a0a") { expect(account).not_to have_error }
example_with(name: "a a") { expect(account).to have_error.on(:name).with(:invalid) }
example_with(name: "a@a") { expect(account).to have_error.on(:name).with("alphanumeric characters only") }
Add the following line to your spec_helper.rb
:
require "rspec/context_helper"
See spec how to write a test.
Defines an exmaple with metadata, shared context and local variables.
description
: context description
If description is omitted, it is automatically generated from other parameters.
_meta
: metadata to be defined
examples
_meta: :foo
_meta: [:foo, :bar]
_meta: { foo: "1" }
_meta: [:foo, bar: 2]
_shared
: shared context to be included
examples
_shared: :foo
_shared: [:foo, :bar]
_shared: { foo: "1" }
_shared: [:foo, bar: 2]
_shared: { foo: [:arg1, :arg2] }
_shared: { foo: { opt1: :bar } }
_shared: { foo: [:arg1, opt1: :bar] }
values
: helper methods to be defined by let
You need to use a proc in order to call helper methods in the example context.
example_with(foo: bar, bar: 2) { expect(foo).to eq 2 }
# => undefined local variable or method `bar'
example_with(foo: -> { bar }, bar: 2) { expect(foo).to eq 2 }
# => OK
So you need to use a nested proc in order to define a helper method that returns a proc.
example_with(foo: -> { "proc" }) { expect(foo.call).to eq "proc" }
# => undefined method `call' for "proc":String
example_with(foo: -> { -> { "proc" } }) { expect(foo.call).to eq "proc" }
# => OK
examples
foo: "1"
foo: "1", bar: 2
foo: -> { bar }, bar: 2
foo: -> { -> { "proc" } }
example_with("description") { expect(true).to eq true }
same as
context "description" do
it { expect(true).to eq true }
end
example_with(value: 1) { expect(value).to eq 1 }
same as
context "when value is 1" do
let(:value) { 1 }
it { expect(value).to eq 1 }
end
example_with(_shared: "logged in") { expect(logged_in).to eq true }
same as
context "when logged in" do
include_context "logged in"
it { expect(logged_in).to eq true }
end
example_with(_meta: :bar) { |e| expect(e.metadata[:bar]).to eq true }
same as
context "", :bar do
it { |e| expect(e.metadata[:bar]).to eq true }
end
example_with(_meta: { foo: 1 }) { |e| expect(e.metadata[:foo]).to eq 1 }
same as
context "", foo: 1 do
it { |e| expect(e.metadata[:foo]).to eq 1 }
end
Defines an example group with metadata, shared context and local variables.
context_with("description") { … }
same as
context "description" do
...
end
context_with(value: 1) { … }
same as
context "when value is 1" do
let(:value) { 1 }
...
end
context_with(_shared: "logged in") { … }
same as
context "when logged in" do
include_context "logged in"
...
end
context_with(_meta: :bar) { … }
same as
context "", :bar do
...
end
context_with(_meta: { foo: 1 }) { … }
same as
context "", foo: 1 do
...
end