GithubHelp home page GithubHelp logo

rspec-its's Introduction

RSpec::Its Build Status

RSpec::Its provides the its method as a short-hand to specify the expected value of an attribute.

Installation

Add this line to your application's Gemfile:

gem 'rspec-its'

And then execute:

$ bundle

Or install it yourself as:

$ gem install rspec-its

And require it as:

require 'rspec/its'

Usage

Use the its method to generate a nested example group with a single example that specifies the expected value of an attribute of the subject using should, should_not or is_expected. The its method can also specify the block expectations of an attribute of the subject using will or will_not.

its accepts a symbol or a string, and a block representing the example.

its(:size)    { should eq(1) }
its("length") { should eq(1) }

You can use a string with dots to specify a nested attribute (i.e. an attribute of the attribute of the subject).

its("phone_numbers.size") { should_not eq(0) }

The following expect-style method is also available:

its(:size) { is_expected.to eq(1) }

as is this alias for pluralized use:

its(:keys) { are_expected.to eq([:key1, :key2]) }

The following block expect-style method is also available:

its(:size) { will_not raise_error }

as is this alias for pluralized use:

its(:keys) { will raise_error(NoMethodError) }

When the subject implements the [] operator, you can pass in an array with a single key to refer to the value returned by that operator when passed that key as an argument.

its([:key]) { is_expected.to eq(value) }

For hashes, multiple keys within the array will result in successive accesses into the hash. For example:

subject { {key1: {key2: 3} } }
its([:key1, :key2]) { is_expected.to eq(3) }

For other objects, multiple keys within the array will be passed as separate arguments in a single method call to [], as in:

subject { Matrix[ [:a, :b], [:c, :d] ] }
its([1,1]) { should eq(:d) }

Metadata arguments are supported.

its(:size, focus: true) { should eq(1) }

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

rspec-its's People

Contributors

abrahamsangha avatar alexismontagne avatar alyssais avatar dependabot[bot] avatar imtayadeway avatar jamesottaway avatar jonrowe avatar ktdreyer avatar michaelachrisco avatar mvz avatar myronmarston avatar olleolleolle avatar orien avatar palfvin avatar pirj avatar rbuchss avatar toaster avatar ydah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rspec-its's Issues

are_expected undefined

This block will fail:

    describe 'first driver' do
      subject { driver_commissions.first }
      its(:keys) { are_expected.to eq([:driver_id,
                                       :backhauls,
                                       :freight_revenue,
                                       :customer_id,
                                       :delivery_date,
                                       :driver_rate,
                                       :freight_bill_number,
                                       :fuel_surcharge])}
    end

Rspec

  1) DriverCommissionHistoryAdapter#all first driver keys 
     Failure/Error: its(:keys) { are_expected.to eq([:driver_id,
     NameError:
       undefined local variable or method `are_expected' for #<RSpec::ExampleGroups::DriverCommissionHistoryAdapter::All::FirstDriver::Keys:0x3fbc5ebf>
     # ./spec/models/driver_commission_history_adapter_spec.rb:20:in `(root)'

This block will succeed:

    describe 'first driver' do
      subject { driver_commissions.first }
      its(:keys) { is_expected.to eq([:driver_id,
                                       :backhauls,
                                       :freight_revenue,
                                       :customer_id,
                                       :delivery_date,
                                       :driver_rate,
                                       :freight_bill_number,
                                       :fuel_surcharge])}
    end

Rspec

....................

Finished in 9.47 seconds (files took 4.72 seconds to load)
20 examples, 0 failures

described_class is changed when using its

According to rspec 3.x documentation, **described_class ** will be the class of the describe parameter, as long as it is no string. Hence subject will provide an instance of this class.

When using its, however, described_class and subject change to the parameter provided as the parameter to its. So any initialization in a before block on the subject causes a failure as the subject is not the described class anymore which I would expect.

Here an example:

require 'rspec/its'

describe Array do
  describe '#empty' do
    it { expect(subject).to eq([]) }
    it { should be_empty}
    its(:empty?) { should be true }
  end
end

I would expect to get all the specs passed. However, its(:empty?) fails with:

1) Array#empty empty? should equal true
    Failure/Error: its(:empty?) { should be true }

   expected true
        got false

The reason becomes clear with this block:

   before { p subject.class }

This will show that subject is a Symbol, not an Array.

To fix this, the describe block defined in method its should not take the attribute itself, but it should rather call to_s or inspect on it.

its([:attr]) has the proper value, its(:attr) does not

`require 'rails_helper'

RSpec.describe Session, type: :model do
subject { create :session } # or subject! no dif

its(:expire) { should eq(1) } # value nil
its([:expire]) { should eq(1) } # proper value
end`

If it is not a bug, my apologies, maybe it's my lack of knowledge

Is using `its` still recommended?

Judging by a few hints, I am unsure if using the its syntax is still recommended or not.

I wonder if its is in the same bucket as shoulda matchers - existing for backwards compatibility, and for older code bases.

The hints I am seeing:

  • The One-Liner Syntax page does not mention it
  • There are some very old issues and pull requests open
  • The fact that it is extracted to a separate gem (which hints it is deprecated but provided to let people ease out of its use)

Would love to have some "official" word on this from people in the inner rspec circle, or to be referred to an existing up to date rspec page that clearly states either way.

Possible to mark "its" examples as pending?

The documentation implies that I should be able to do something like this:

subject { true }
its(:nil?, pending: 'forever') { should be_truthy }

…and have the example marked as pending. But the :pending seems to be silently ignored in every its I have written.

deep hash support

How about support for nested hashes like:

its([:key, :deep, :down, :below]) {  }

for hashes like

{key: {deep: {down: {below: "value"}}}}

'its' for expecting exceptions

I was trying to use 'its' syntax for expecting exceptions:

 4: class Subject
 5:   def some_method
 6:     raise Exception
 7:   end
 8: end
 9: 
10: describe Subject do
11:     it { expect { subject.some_method }.to raise_error Exception }
12:     its(:some_method) { is_expected.to raise_error Exception }
13:     its(:some_method) { should raise_error Exception }
14: end

I expected all three tests to succeed, however:

.FF

Failures:

  1) Subject some_method
     Failure/Error: raise Exception
     Exception:
       Exception
     # ./exception.rb:6:in `some_method'
     # ./exception.rb:12:in `block (2 levels) in <top (required)>'

  2) Subject some_method
     Failure/Error: raise Exception
     Exception:
       Exception
     # ./exception.rb:6:in `some_method'
     # ./exception.rb:13:in `block (2 levels) in <top (required)>'

Finished in 0.0014 seconds (files took 0.07659 seconds to load)
3 examples, 2 failures

Failed examples:

rspec ./exception.rb:12 # Subject some_method
rspec ./exception.rb:13 # Subject some_method

its against BasicObject fails to generate description

When the subject is a BasicObject (which of course doesn't have respond_to?, is_a? and others) then RSpec (or rspec/its) cannot generate the test description.

Example code:

class Foo <BasicObject
  def name; 'hello'; end
end

RSpec.describe Foo do
  its(:name) { is_expected.to eq 'hello' }
end

This generates output similar to:

 example at .<spec file>:10 (Got an error when generating description from matcher: NoMethodError: undefined method `is_a?' for #<Foo:0x007fcd4c3bd938> -- /.../ruby-2.4.1/gems/activesupport-5.1.4/lib/active_support/core_ext/time/calculations.rb:16:in `===')

I'm not sure of there's the "right" way to fix this as it is not even possible to use respond_to? on the BasicObject.
But worth raising this.

When requiring the Ruby's timeout library I can no longer retrieve a nested attribute named timeout on an OpenStruct

The wrapper class here is a quick example of the behavior. While the example does not use the timeout library methods it is present in a larger project I am currently working on.

Given this yaml file:

default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

And a test file:

require 'ostruct'
require 'yaml'
require 'timeout'
require 'rspec/its'

class DatabaseConfg
  def development
    hash = YAML.load(File.read('database.yml'))
    struct = OpenStruct.new(hash['development'])
  end
end

describe DatabaseConfg do
  its('development.database') { should eq 'db/development.sqlite3' }
  its('development.timeout') { should eq 5000 }
end

When I execute the tests I see an error that is the same error if you ran timeout without any parameters

$ rspec example_spec.rb
./usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rspec-its-1.2.0/lib/rspec/its.rb:115:in `block (3 levels) in its': Object#timeout is deprecated, use Timeout.timeout instead.
F

Failures:

  1) DatabaseConfg development.timeout
     Failure/Error: its('development.timeout') { should eq 5000 }

     ArgumentError:
       wrong number of arguments (given 0, expected 1..3)
     # ./rspec_example_spec.rb:15:in `block (2 levels) in <top (required)>'

Finished in 0.00413 seconds (files took 0.13378 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./rspec_example_spec.rb:15 # DatabaseConfg development.timeout

The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported.

I'm currently trying to switch from RSpec 2.99.0 to 3.0.0. I really like its and therefore want to continue using it and included this gem as a consequence. This unfortunately doesn't work for me though. The project is open source, so you can see the results on Travis.

With RSpec 2.99.0 everything runs without any deprecation warnings, see the logs here. As soon as I switch to 3.0.0, the build will break with the following errors for its blocks:

Failure/Error: Unable to find matching line from backtrace
The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported.

See the build log here.

Accepting method arguments

Before I implement this, I should ask - would you accept a patch that passes arguments to the method?

subject { MathExample.new }
describe '#root' do
  its(:root, 9) { should == 3 }
  its(:root, 16) { should == 4 }
end

What do you think? Is this against the philosophy of the simplicity and readability of its? This is a short example, but I find myself wanting to do this where I have lots of short examples with different fixed inputs to a method. This is a lot more concise than the alternative:

subject(:math) { MathExample.new }
describe '#root' do
  it 'finds the square root of 9' do
    expect(math).root(9).to eq 3
  end

  it 'finds the square root of 16' do
    expect(math).root(16).to eq 4
  end
end

Wrong number of arguments

Rails 5.2

Using rspec-support 3.12.1
Using rspec-core 3.12.2
Using rspec-expectations 3.12.3
Using rspec-mocks 3.12.6
Using rspec 3.12.0
Using rspec-html-matchers 0.10.0
Using rspec-its 1.3.0
Using rspec-rails 4.0.1

When using [] for accessing hash-subject attributes

Failure/Error: its([:amount]) { is_expected.to eq(1)}

ArgumentError:
  wrong number of arguments (given 2, expected 3..5)

https://github.com/rspec/rspec-its/blob/main/lib/rspec/its.rb#L169

RSpec 3 is being released tomorrow

I plan to release RSpec 3 tomorrow. I noticed there are unreleased commits here but they don't appear to touch any of the actual lib code so I don't think a release is necessarily needed. Wanted to let you know, though @palfvin. (Feel free to close this).

rspec-its breaking InSpec

Hi,

When I use InSpec's parse_config_file resource to verify the content of an ini-like config file structured like so:

[beaver]
foo: baz

[/var/log/apache2/access.log]
bar: baz

And I have the following spec:

    describe parse_config_file('/etc/beaver/beaver.conf', {
        assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
        comment_character: '#'
    }) do
        its('beaver') {
            should include('foo' => 'baz')
        }

        its('/var/log/apache2/access.log') {
            should include('bar' => 'baz')
        }
    end

The following error occurs:

∅  undefined method `log' for nil:NilClass

I believe this is being caused by this line of code which is splitting the value by dot (.):
https://github.com/rspec/rspec-its/blob/master/lib/rspec/its.rb#L113

This is effectively causing InSpec (and any other rspec "wrapper" feeding that code path something which includes a dot) to break. Not being a core rspec developer I'm not sure how I could contribute to solving this problem via Pull Requests etc.

Any advice would be much appreciated.

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.