A long-lived project that still receives updates
subject { Integer(nil) }; it('raises') { block_is_expected.to raise_error(TypeError) }
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 2.2
>= 10.5
>= 3
~> 0.1, >= 0.1.16
 Project Readme

Rspec::BlockIsExpected

CI Build Test Coverage Maintainability Depfu


Liberapay Patrons Sponsor Me on Github

Buy me coffee donation button Patreon donate button

This gem does five, three sir, five things.

  1. Provides block_is_expected to set expectations on the result of running the subject as a block.
  2. Provides, via shared example groups, shortcut RSpec macros for setting an expectation on errors being raised (or not).
    it_behaves_like "block_is_expected to not raise"
    it_behaves_like "block_is_expected to raise error", RuntimeError
  3. Provides RSpec negated matchers that can be used with block_is_expected:
    not_change
    not_raise_error
    And two others that are so generally useful I end up defining them on every project:
    not_include
    not_eq

Just show me the money

First, configure in your rspec helper, or similar:

require "rspec/block_is_expected"

Then,

  1. Custom expectation on result of subject as block
    subject { Integer("1") }
    it("raises") { block_is_expected.to(not_raise_error) }
  2. Subject will not raise an exception
    subject { Integer("1") }
    it_behaves_like "block_is_expected to not raise"
  3. Subject will raise an exception
    subject { Integer(nil) }
    it_behaves_like "block_is_expected to raise error", TypeError
Project bundle add rspec-block_is_expected --group test
name, license, docs, standards RubyGems.org License: MIT RubyDoc.info SemVer 2.0.0 Keep-A-Changelog 1.0.0
version & activity Gem Version Total Downloads Download Rank
dependencies Depfu
continuous integration CI Build Heads Style
test coverage Test Coverage
maintainability Maintainability
code triage Open Source Helpers
homepage on Github.com, on Railsbling.com
... ๐Ÿ’– Liberapay Goal Progress, ๐ŸงŠ, ๐Ÿ›–, ๐Ÿงช, ๐ŸŒ, ๐Ÿ‘ผ, โš—๏ธ, Tweet @galtzo

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.

Ruby Compatibility

Supports the same versions of Ruby that RSpec does, 1.8.7 - current ruby-head, as well as the JRuby equivalents.

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

Switch to main branch

We recently migrated from master to main as the default branch. If this affected your local checkout:

git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a

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

Contributing

See CONTRIBUTING.md. contributing: https://gitlab.com/pboling/rspec-block_is_expected/-/blob/main/CONTRIBUTING.md

Contributing

See CONTRIBUTING.md. contributing: https://gitlab.com/pboling/rspec-stubbed_env/-/blob/main/CONTRIBUTING.md

Running Specs

The basic compatibility matrix:

appraisal install
appraisal rake test

Sometimes also:

BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal update

NOTE: This results in bad paths to the gemspec. gemspec path: "../../" needs to be replaced with gemspec :path => "../" in each Appraisal gemfile.

Except, is unlikely to be possible to install all of the supported Rubies & Railsies in a single container... See the various github action workflows for more inspiration on running certain oldies.

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 => [:development, :test]

or in a gemspec

spec.add_development_dependency("rspec-block_is_expected", "~> 1.0")

Legal

License: MIT