Rspec::BlockIsExpected

This gem does one very simple thing very well. It allows you to use block_is_expected similarly to how you would use is_expected if a block was wrapping the subject. Supports the same versions of Ruby that RSpec does, 1.8.7 - current ruby-head, as well as the JRuby equivalents.

subject { Integer(nil) }
it('raises') { block_is_expected.to raise_error(TypeError) }
Project AnonymousActiveRecord
gem name rspec-block_is_expected
license License: MIT
download rank Downloads Today
version Version
dependencies Depfu
continuous integration Build Status
test coverage Test Coverage
maintainability Maintainability
code triage Open Source Helpers
homepage on Github.com, on Railsbling.com
documentation on RDoc.info
Spread ~♡ⓛⓞⓥⓔ♡~ 🌏, 👼, :shipit:, Tweet Peter

If you only ever want to test subjects wrapped in blocks, and are comfortable with losing the standard is_expected behavior, see an alternative to this gem here.

Installation

Add this line to your application's Gemfile:

gem 'rspec-block_is_expected', :group => :test

And then execute:

$ bundle

Or install it yourself as:

$ gem install rspec-block_is_expected

Configuration

There is no configuration needed if you your test suite loads the bundle group (e.g. test) that you added the gem to.

Otherwise, you may load it manually near the top of your spec_helper.rb, and it will self configure.

require 'rspec/block_is_expected'

RSpec Matchers

block_is_expected can be used to chain expectations related to the block, but to_not doesn't work with multiple expectations. So negated matchers are required. A basic set of them are included with this gem, and can be loaded with:

require 'rspec/block_is_expected/matchers/not'

This gives you the following matchers:

RSpec::Matchers.define_negated_matcher :not_change, :change
RSpec::Matchers.define_negated_matcher :not_include, :include
RSpec::Matchers.define_negated_matcher :not_eq, :eq
RSpec::Matchers.define_negated_matcher :not_raise_error, :raise_error

Example

You have a module like this:

module MyTasks
  def my_rakelib
    Rake.add_rakelib('bananas')
  end
  module_function :my_rakelib
end

You have a spec like this:

require 'rake'

RSpec.describe(MyTasks) do
  describe 'my_rakelib' do
    subject(:my_rakelib) { described_class.my_rakelib }
    it 'updates rakelib' do
      block_is_expected.to not_raise_error &
                           change { Rake.application.options.rakelib }.from(['rakelib']).to(%w[rakelib bananas])
    end
  end
end

Integration with RuboCop

You'll likely get the following linting error from rubocop-rspec if you use block_is_expected.to ...:

RSpec/NoExpectationExample: No expectation found in this example.

To fix it properly you need to register block_is_expected as an "expectation". In your .rubocop.yml

inherit_gem:
  rspec-block_is_expected: rubocop.yml

Usage

The spec suite for this gem has some examples of usage, lightly edited here.

RSpec.describe 'TestyMcTest' do
  context 'errors raised' do
    subject { Integer(nil) }
    it('can be tested') do
      # Where you used to have:
      # expect { subject }.to raise_error(TypeError)
      block_is_expected.to raise_error(TypeError)
    end
  end
  context 'execution' do
    let(:mutex) { Mutex.new }
    subject { mutex.lock }
    it('can change state') do
      expect(mutex.locked?).to eq(false)
      # Where you used to have:
      # expect { subject }.to_not raise_error
      block_is_expected.to_not raise_error
      expect(mutex.locked?).to eq(true)
    end
  end
  context 'changed state' do
    let(:mutex) { Mutex.new }
    subject { mutex.lock }
    it('can be tested') do
      # Where you used to have:
      # expect { subject }.to change { mutex.locked? }.from(false).to(true)
      block_is_expected.to change { mutex.locked? }.from(false).to(true)
    end
  end
end

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

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.

Authors

Peter H. Boling of Rails Bling is the author.

Contributors

See the Network View and the CHANGELOG

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  6. Create new Pull Request

Bug reports and pull requests are welcome on GitHub at https://github.com/pboling/anonymous_active_record. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

Code of Conduct

Everyone interacting in the AnonymousActiveRecord project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Versioning

This library aims to adhere to Semantic Versioning 2.0.0. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions.

As a result of this policy, you can (and should) specify a dependency on this gem using the Pessimistic Version Constraint with two digits of precision.

For example in a Gemfile:

gem 'rspec-block_is_expected', '~> 1.0', group: :test

or in a gemspec

spec.add_development_dependency 'rspec-block_is_expected', '~> 1.0'