Cirus Polis
Cirus Polis

Reputation: 35

Show the complete description of an example

In RSpec, how can we generate a string from an example, representing the current meta description of the current example?

Example:

RSpec.describe Api::V1::Public::Signin::ByEmailController, type: :controller do
  describe 'POST #create' do
    context 'when the provider is "email"' do
      context 'when there is a saved email' do
        context 'when the password is good' do
          it 'signs in' do
            expect(current_metadata_description).to eq 'Api::V1::Public::Signin::ByEmailController POST #create when the provider is "email" when there is a saved email when the password is good signs in'
          end
        end
      end
    end
  end
end

As we can see, the current meta description of the given example is:

Api::V1::Public::Signin::ByEmailController POST #create when the provider is "email" when there is a saved email when the password is good signs in

Thanks.

Edit:

The current_metadata_description is not provided by RSpec. I just invented it to give an example of what I would like to have.

Upvotes: 0

Views: 118

Answers (2)

engineersmnky
engineersmnky

Reputation: 29588

While I am unsure what your overall intentions are for doing this.

Rspec::Core::ExampleGroup.it yields a RSpec::Core::Example to the block. As with all yielding methods one can capture the yielded Object in a block local variable. RSpec::Core::Example has a full_description method which appears to be what you are looking for. RSpec Source.

For Example (no pun intended):

describe String do 
  context 'Down' do 
    context 'Deeper' do 
      it 'can describe itself' do |ex|
        # ex is the specific RSpec::Core::Example for this it block
        expect(ex.full_description).to eq('String Down Deeper can describe itself')
      end
    end
  end
end

running this will return

.
Finished in 0.003 seconds (files took 0.21998 seconds to load)
1 example, 0 failures

It is imperative that you capture the yielded value if you want the desired output as the block itself is executed in the context of an instance of RSpec::Core::ExampleGroup so calling self.class.metadata[:full_description] will contain the description of the RSpec::Core::ExampleGroup but not the RSpec::Core::Example itself (e.g. "String Down Deeper")

As described in the docs if this is for logging purposes (or something similar where you would like this information for each example) you can access the RSpec::Core::Example in Hooks excerpt:

# Useful for configuring logging and/or taking some action based
# on the state of an example's metadata.
#
#     RSpec.configure do |config|
#       config.before do |example|
#         log example.description
#       end
#
#       config.after do |example|
#         log example.description
#       end
#
#       config.around do |example|
#         log example.description
#         example.run
#       end
#     end

If you really wanted to patch this in (and I am not endorsing it) You could do the following

class RSpec::Core::ExampleGroup 
  def instance_exec(*args,&blk)
    if args.first.is_a?(RSpec::Core::Example)
      self.define_singleton_method(:current_metadata_description) do
        args.first.full_description
      end
    end
    super(*args,&blk)
  end
end

Then your test would be exactly as you stated.

Upvotes: 1

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34338

Try to run rspec with --format option:

bundle exec rspec --format documentation

Update:

I don't know any rspec method that would do that for you. One way I can think of is, write the spec description to a file while running the tests and then read the description from it in your custom current_metadata_description method. Here is a tutorial on Generating documentation from specs. Hope that helps!

Upvotes: 0

Related Questions