How to use RSpec expectations in irb
You are close, but calling include
on top-level you will be calling Module#include
. To get around it you need to remove the original include method so that RSpec's include
gets called instead.
First let's figure out where the system include
comes from:
> method :include
=> #<Method: main.include>
Ok. It looks like it's defined in main
. This is the Ruby top-level object. So let's rename and remove the original include:
> class << self; alias_method :inc, :include; remove_method :include; end
Now we can get down to business:
> require 'rspec'
> inc RSpec::Matchers
> [1,2,3].should include(1)
=> true
How can I use rspec expectations and matchers outside of Rspec?
When you include
a module, it makes its methods available to instances of the class. Your test
method is a singleton method (a "class method"), not an instance method, and thus will never have access to methods provided by mixed-in modules. To fix it, you can do:
class BF
include ::RSpec::Matchers
def test
expect(1).to eq(1)
end
end
BF.new.test
If you want the RSpec::Matchers
methods to be available to singleton methods of BF
, you can instead extend
the module:
class BF
extend ::RSpec::Matchers
def self.test
expect(1).to eq(1)
end
end
BF.test
How to experiment with rspec from within irb
You can play around with RSpec test doubles in irb
by requiring "rspec/mocks/standalone"
:
$ irb
> require 'rspec/mocks/standalone'
> b = double("book")
=> #<RSpec::Mocks::Mock:0x3fd88d0157e8 @name="book">
Using expect matcher in Rspec
If using Cucumber, you can simply include the 'rspec/expectations' in your env.rb file and then use the expected syntax in your step definitions.
env.rb:
require 'rspec/expectations'
steps.rb:
Then(/^I should be able to use rspec$/) do
expected = "this"
actual= "this"
expect(actual).to eql(expected)
end
My mistake was mistakingly testing this syntax in the ruby console. You cannot do that since Cucumber does some automagic stuff for you.
"When cucumber sees the Spec::Matchers and Spec::Expectations modules defined, it will implicitly include them in the World in which the steps are executed."
Launch irb while running RSpec tests for debugging purposes?
Use pry.
Simple, fast, with syntax highlighting. After install, you just need to write:
binding.pry
in your code to stop executing and display developer debugging console
After you fall in love with pry, there is also useful gem called 'pry-nav'
RSpec not_to does not show the correct result
The return value of false
doesn't mean it failed, it just means 4
isn't nil
. If it failed, it would have raised an error.
RSpec uses a NegativeOperatorMatcher
class to test not_to
expectations (source code here):
class NegativeOperatorMatcher < OperatorMatcher
def __delegate_operator(actual, operator, expected)
return false unless actual.__send__(operator, expected)
fail_with_message("expected not: #{operator} #{expected.inspect}\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
end
end
So basically, it returns false unless the actual value equals the expected value, in which case it continues on to fail the spec (i.e. there's no situation where a negative matcher like not_to
will ever return true
).
is a one-line test like this possible in rspec
In irb:
require 'rspec-expectations'
include RSpec::Matchers
"bat".length.should eq(3)
How to test for stdout that is inside a .each iteration block, using rspec?
Todd's answer is fine and I'd strongly recommend you read it carefully: refactor your app in a way that UI (CLI in your case) is minimal and easy to test. But when you want full coverage you'd need to test that std output eventually.
The way you're using it now:
expect(initialize_program(1, 3)).to output("whatever").to_stdout
Means that initialize_program(1, 3)
is evaluated immediately when the matcher is called, and it's too soon - it has to do it's magic(*) first, and then run your code. Try like this:
expect { initialize_program(1, 3) }.to output("whatever").to_stdout
Now, instead passing results of calling initialize_program(1, 3)
into the matcher, you pass a block that "knows how" to call initialize_program(1, 3)
. So what the matcher does:
- saves the block for later
- does it magic to capture whatever goes to the STDOUT (see below)
- calls the block, calling the
initialize_program(1, 3)
, capturing whatever was supposed to go to STDOUT - compares it with what you've set up in your expectation (the
output("whatever")
part)
https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/output-matcher
- The mentioned magic is not that magical anyway:
https://github.com/rspec/rspec-expectations/blob/44d90f46a2654ffeab3ba65eff243039232802ce/lib/rspec/matchers/built_in/output.rb#L49
and
https://github.com/rspec/rspec-expectations/blob/44d90f46a2654ffeab3ba65eff243039232802ce/lib/rspec/matchers/built_in/output.rb#L141
It just creates StringIO, and replaces global var $stdout with it.
Related Topics
Rails Before_Filter for Specific Actions in Controller
Aptana 3 Ruby Debugger - Exception in Debugthread Loop: Undefined Method 'Is_Binary_Data'
Ruby: "&& Return" VS "And Return"
Ruby/Ror: Calling Original Method via Super()
Why Isn't My Cocoapods Post_Install Hook Updating My Preprocessor MACros
Run Rails Commands Outside of Console
How to Set a Custom User Agent in Ruby
Rails, Activerecord: Self[:Attribute] VS Self.Attribute
How to Loop Through a Daterange with Different Intervals
How to Escape Strings for Terminal in Ruby
Natural Language Date Parser for Ruby/Rails
How to Run Irb.Start in Context of Current Class
Should I Learn MACruby or Rubycocoa
How to Use Ruby Metaprogramming to Add Callbacks to a Rails Model
How to Expect Some (But Not All) Arguments with Rspec Should_Receive