Reputation: 5931
I monkeypatched URI and wrote tests for it:
describe URI do
describe '.sanitize_domain' do
let(:expectation) { 'toolbar.google.com' }
subject { described_class.sanitize_domain(url) }
context 'when url is correct' do
context 'when url misses both http and www prefixes' do
let(:url) { 'toolbar.google.com/public' }
it { is_expected.to eq(expectation) }
end
context 'when url contains www' do
let(:url) { 'www.toolbar.google.com/public' }
it { is_expected.to eq(expectation) }
end
context 'when url contains https' do
let(:url) { 'https://toolbar.google.com/public' }
it { is_expected.to eq(expectation) }
end
context 'when url contains both http and www' do
let(:url) { 'http://www.toolbar.google.com/public' }
it { is_expected.to eq(expectation) }
end
context 'when multiple urls are given' do
let(:url) { 'http://www.toolbar.google.com/Default.asp, http://www.toolbar.google.com/' }
it { is_expected.to eq(expectation) }
end
end
end
end
As you can see, it { is_expected.to eq(expectation) }
is repeated in each context.
I think there is a solution to dry it up a bit.
I could use shared_examples here, but IMHO it would be overkill to do that for a single it
and readability would decrease.
I tried to extract expectation
to before(:context) { it { is_expected } }
but the it
keyword isn't available inside before
block. Here is the error message from that attempt:
it
is not available from within an example (e.g. anit
block) or from constructs that run in the scope of an example (e.g.before
,let
, etc). It is only available on an example group (e.g. adescribe
orcontext
block).
Upvotes: 3
Views: 480
Reputation: 37607
For tests that are both minimal and readable, just extract a method:
describe URI do
describe '.sanitize_domain' do
context 'when url is correct' do
it 'sanitizes a URL without http and www prefixes' do
expect_sanitized_domain_to_handle 'toolbar.google.com/public'
end
it 'sanitizes a URL which contains www' do
expect_sanitized_domain_to_handle 'www.toolbar.google.com/public'
end
it 'sanitizes a URL which contains https' do
expect_sanitized_domain_to_handle 'https://toolbar.google.com/public'
end
it 'sanitizes a URL which contains both http and www' do
expect_sanitized_domain_to_handle 'https://www.toolbar.google.com/public'
end
it 'sanitizes a string containing multiple URLs' do
expect_sanitized_domain_to_handle 'http://www.toolbar.google.com/Default.asp, http://www.toolbar.google.com/'
end
def expect_sanitized_domain_to_handle(url)
expect(URL.sanitize_domain(url)).to eq('toolbar.google.com')
end
end
end
end
Or, to get the expected return value into the test where you can see it, and change it if you need a test with a different return value:
it 'sanitizes a URL from a different site' do
expect_sanitized_domain given: 'http://stackoverflow.com/questions/32331374/the-same-test-case-for-few-contexts-in-rspec-how-to-dry-it',
to_return: 'stackoverflow.com'
end
def expect_sanitized_domain(given:, to_return:)
expect(URL.sanitize_domain(given)).to eq(to_return)
end
Upvotes: 1
Reputation: 121000
inner_contextes_urls = [
['when url misses both http and www prefixes', 'toolbar.google.com/public'],
['when url contains www', 'www.toolbar.google.com/public']
# ...
]
inner_contextes_urls.each do |(title, url)|
context "#{title}" do
let(:url) { "#{url}" }
it { is_expected.to eq(expectation) }
end
end
Upvotes: 1