RspecInContext
This gem is here to help you write better shared_examples in Rspec.
Ever been bothered by the fact that they don't really behave like methods and that you can't pass it a block ? There you go: rspec_in_context
Installation
Add this line to your application's Gemfile:
gem 'rspec_in_context'And then execute:
$ bundle
Or install it yourself as:
$ gem install rspec_in_context
Usage
Add this into Rspec
You must require the gem on top of your spec_helper:
require 'rspec_in_context'Then include it into Rspec:
RSpec.configure do |config|
  [...]
  
  config.include RspecInContext
endDefine a new in_context
You can define in_context block that are reusable almost anywhere. They completely look like normal Rspec.
Inside a Rspec block (scoped)
# A in_context can be named with a symbol or a string
define_context :context_name do
  it 'works' do
    expect(true).to be_truthy
  end
endThose in_context will be scoped to their current describe/context block.
Outside a Rspec block (globally)
Outside of a test you have to use RSpec.define_context. Those in_context will be defined globally in your tests.
Use the context
Anywhere in your test description, use a in_context block to use a predefined in_context.
Important: in_context are scoped to their current describe/context block. If you need globally defined context see RSpec.define_context
# A in_context can be named with a symbol or a string
RSpec.define_context :context_name do
  it 'works' do
    expect(true).to be_truthy
  end
end
[...]
Rspec.describe MyClass do
  in_context :context_name # => will execute the 'it works' test here
endThings to know
Inside block execution
- You can chose exactly where your inside test will be used:
By using 
execute_testsin your define context, the test passed when you use the context will be executed here 
define_context :context_name do
  it 'works' do
    expect(true).to be_truthy
  end
  context "in this context pomme exists" do
    let(:pomme) { "abcd" }
    
    execute_tests
  end
end
[...]
in_context :context_name do
  it 'will be executed at execute_tests place' do
    expect(pomme).to eq("abcd") # => true
  end
end- You can add variable instantiation relative to your test where you exactly want:
 
instanciate_context is an alias of execute_tests so you can't use both.
But it let you describe what the block will do better.
Variable usage
- You can use variable in the in_context definition
 
define_context :context_name do |name|
  it 'works' do
    expect(true).to be_truthy
  end
  context "in this context #{name} exists" do
    let(name) { "abcd" }
    
    execute_tests
  end
end
[...]
in_context :context_name, :poire do
  it 'the right variable will exists' do
    expect(poire).to eq("abcd") # => true
  end
endScoping
- In_contexts can be scope inside one another
 
define_context :context_name do |name|
  it 'works' do
    expect(true).to be_truthy
  end
  context "in this context #{name} exists" do
    let(name) { "abcd" }
    
    execute_tests
  end
end
define_context "second in_context" do
  context 'and tree also' do
    let(:tree) { 'abcd' }
    it 'will scope correctly' do
      expect(tree).to eq(poire)
    end
  end
end
[...]
in_context :context_name, :poire do
  it 'the right variable will exists' do
    expect(poire).to eq("abcd") # => true
  end
  in_context "second in_context" # => will work
end- in_context are bound to their current scope
 
Namespacing
- You can add a namespace to a in_context definition
 
define_context "this is a namespaced context", namespace: "namespace name"Or
define_context "this is a namespaced context", ns: "namespace name"Or
RSpec.define_context "this is a namespaced context", ns: "namespace name"- When you want to use a namespaced in_context, you have two choice:
 
Ignore any namespace and it will try to find a corresponding in_context in any_namespace (the ones defined without namespace have the priority);
define_context "namespaced context", ns: "namespace name" do
  [...]
end
in_context "namespaced context"Pass a namespace and it will look only in this context.
define_context "namespaced context", ns: "namespace name" do
  [...]
end
in_context "namespaced context", namespace: "namespace name"
in_context "namespaced context", ns: "namespace name"Making in_context adverstise itself
The fact that a in_context block is used inside the test is silent and invisible by default.
in_context will still wrap its own execution inside a anonymous context.
But, there's some case where it helps to make the in_context to wrap its execution in a named context block.
For example:
define_context "with my_var defined" do
  before do
    described_class.set_my_var(true)
  end
  it "works"
end
define_context "without my_var defined" do
  it "doesn't work"
end
RSpec.describe MyNiceClass do
  in_context "with my_var defined"
  in_context "without my_var defined"
endUsing a rspec -f doc will only print "MyNiceClass works" and "MyNiceClass doesn't work" which is not really a good documentation.
So, you can define a context specifying it not to be silent or to print_context.
For example :
define_context "with my_var defined", silent: false do
  before do
    described_class.set_my_var(true)
  end
  it "works"
end
define_context "without my_var defined", print_context: true do
  it "doesn't work"
end
RSpec.describe MyNiceClass do
  in_context "with my_var defined"
  in_context "without my_var defined"
endWill print "MyNiceClass with my_var defined works" and "MyNiceClass without my_var defined doesn't work". Which is valid and readable documentation.
Development
After checking out the repo, run bin/setup to install dependencies. You can also run bin/console for an interactive prompt that will allow you to experiment.
After setuping the repo, you should run overcommit --install to install the different hooks.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/denispasin/rspec_in_context.