Rspec: No such file or directory # rb_sysopen - - ruby

I'm trying to write a simple test for a ruby script that uses gets and I'm experiencing some weird behavior.
When I run the test with rspec it passes fine, but as soon as I run rspec with any flags, like rspec -f json or rspec -O rand the test will fail and give me No such file or directory # rb_sysopen - -O, where -O is whatever the flag that was run.
Stranger still is that if I run rspec and specify the test file like rspec spec/gets_spec.rb, I get a completely different error:
Failure/Error: expect { require_relative '../gets' }.to output("Hello, Lena!\n").to_stdout
expected block to output "Hello, Lena!\n" to stdout, but output "Hello, Describe \"gets.rb\" do!\n"
Diff:
## -1,2 +1,2 ##
-Hello, Lena!
+Hello, Describe "gets.rb" do!
# ./spec/gets_spec.rb:14:in `block (2 levels) in <top (required)>'
I'm having trouble figuring out the right way to write my test so that this doesn't happen but I'm not sure what part of my code needs to change.
I'm using ruby 2.6.3
I learned about testing input from this question
The script, gets.rb, looks like
puts "Hello, #{gets.chomp.capitalize}!"
My test looks like
describe "gets.rb" do
before do
$stdin = StringIO.new("lena")
end
after do
$stdin = STDIN
end
it "should output 'Hello, name!'" , points: 1 do
allow($stdin).to receive(:gets).and_return("lena")
expect { require_relative "../gets" }.to output("Hello, Lena!\n").to_stdout
end
end
Here's the full failure message:
Failures:
1) gets.rb should output 'Hello, name!'
Failure/Error: expect { require_relative '../gets' }.to output("Hello, Lena!\n").to_stdout
Errno::ENOENT:
No such file or directory # rb_sysopen - -O
#./gets.rb:1:in `gets'
# ./gets.rb:1:in `gets'
# ./gets.rb:1:in `<top (required)>'
# ./spec/gets_spec.rb:14:in `require_relative'
# ./spec/gets_spec.rb:14:in `block (3 levels) in <top (required)>'
# ./spec/gets_spec.rb:14:in `block (2 levels) in <top (required)>'

You can try to use a little different approach:
describe "gets.rb" do
it "should output 'Hello, name!'" do
allow_any_instance_of(Object).to receive(:gets).and_return("lena")
expect { require_relative "../gets.rb" }.to output("Hello, Lena!\n").to_stdout
end
end
allow_any_instance_of I took from https://makandracards.com/makandra/41096-stubbing-terminal-user-input-in-rspec
Reading user input in console applications is usually done using Kernel#gets.
The page suggests to use Object.any_instance.stub(gets: 'user input') but it's deprecated syntax already and I've updated it.

Related

If I'm testing an rspec extension, how do I suppress the results of tests which fail as part of the test?

I'm trying to write specs for an extension to rspec.
This is the gist of what I'm trying to test:
require 'rspec-let-and-after-extension'
RSpec.describe "let(...).and_after" do
it 'is called if the `let` is invoked even if the example fails' do
call_order = []
RSpec.describe do
let(:foo) { }.and_after { call_order << :and_after }
it { foo; call_order << :example; raise 'failed!' }
end.run
expect(call_order).to eq [:example, :and_after]
end
end
One of the important behaviours is that if running the example fails, the cleanup code still runs. So I test this by recording the order of the calls and raising an exception from the example.
Problem is, when I run it, it sees this block as a second example, which then fails with errors:
.F
Failures:
1)
Got 0 failures and 2 other errors:
1.1) Failure/Error: it { foo; call_order << :example; raise 'failed!' }
RuntimeError:
failed!
# ./spec/spec.rb:43:in `block (4 levels) in <top (required)>'
# ./spec/spec.rb:44:in `block (2 levels) in <top (required)>'
1.2) Failure/Error: it { foo; call_order << :example; raise 'failed!' }
RuntimeError:
failed!
# ./spec/spec.rb:43:in `block (4 levels) in <top (required)>'
Finished in 0.00167 seconds (files took 0.08011 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/spec.rb:43 #
As you can see, the output did have one dot, so the actual example passed. But then there is an F, because it has seen the internal example, run that, and unsurprisingly that one failed.
How do I make rspec not see this nested example as one of the examples it's supposed to run, so that this example completes with a single dot?
(If you're wondering about what the rspec devs themselves do about their tests, it looks like they use cucumber. Do they use cucumber because they couldn't figure this out either? :))
You can use the new sandboxing API (available in 3.2+).
RSpec.configure do |rspec|
rspec.around do |ex|
RSpec::Core::Sandbox.sandboxed do |config|
# re-configure any configuration defined by your extension here
# before allowing the example to run. The sandbox runs with a fresh
# config instance, which means any configuration you have set in
# `rspec-let-and-after-extension` will not apply while the example
# is running.
# config.extend MyExtensionModule
ex.run
end
end
end

Ruby script raising unexpected backtrace

I have a method that should raise a custom error with a message. When I catch the error and raise my own custom error, it is still raising and printing the backtrace of the original error. I just want the custom error and message. Code below.
Method:
def load(configs)
begin
opts = {access_token: configs['token'],
api_endpoint: configs['endpoint'],
web_endpoint: configs['site'],
auto_paginate: configs['pagination']}
client = Octokit::Client.new(opts)
repos = client.org_repos(configs['org'])
repos.each do |r|
Project.create(name: r.name)
end
rescue Octokit::Unauthorized
raise GitConfigError, "boom"
end
#rescue Octokit::Unauthorized
end
class GitConfigError < StandardError
end
My test (which is failling):
context 'with incorrect git configs' do
before do
allow(loader).to receive(:load).and_raise Octokit::Unauthorized
end
it { expect{loader.load(configs)}.to raise_error(GitConfigError, "boom" ) }
end
Test Output:
GitProjectLoader#load with incorrect git configs should raise GitConfigError with "boom"
Failure/Error: it { expect{loader.load(configs)}.to raise_error(GitConfigError, "boom" ) }
expected GitConfigError with "boom", got #<Octokit::Unauthorized: Octokit::Unauthorized> with backtrace:
# ./spec/lib/git_project_loader_spec.rb:24:in `block (5 levels) in <top (required)>'
# ./spec/lib/git_project_loader_spec.rb:24:in `block (4 levels) in <top (required)>'
# ./spec/lib/git_project_loader_spec.rb:24:in `block (4 levels) in <top (required)>'
If you intend to test the handling of the Octokit::Unauthorized error, then raise the error anywhere before the rescue kicks in. Preferably, someplace where it would actually be raised.
Something like this, for example:
before do
allow(Octokit::Client).to receive(:new).and_raise(Octokit::Unauthorized)
end
And then:
expect{ loader.load(configs) }.to raise_error(GitConfigError, "boom" )
As a side note, I would discourage enclosing all lines of your method in a begin;rescue;end structure; you should enclose only the lines from which you are expecting errors.
You are not testing your code as you think. You have mocked it out.
The line
allow(loader).to receive(:load).and_raise Octokit::Unauthorized
replaces the load method on loader with a stub which just raises the named error.
Remove your before block, and it should test your code as intended. Note as written it will make a real request via Octokit, unless you mock that out instead.

RSpec "Failure/Error: Unable to find matching line from backtrace" On every test

I am working through some Ruby problem sets. I'm using Ubuntu 14.04, rbenv 0.4.0-98-g13a474c, rspec 3.1.4, and ruby 2.0.0p353. I'm running into the following errors for every test I run and I'm hoping someone might be able to guide me in the right direction to a solution.
I have run rspec tests successfully in the past but I can't seem to figure out the issue with my current setup.
Here is the message I receive for every test I run:
6) age is an integer
Failure/Error: Unable to find matching line from backtrace
ArgumentError:
wrong number of arguments (0 for 1)
# /usr/lib/ruby/vendor_ruby/rspec/mocks.rb:10:in `setup'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/mocking_adapters/rspec.rb:19:in `setup_mocks_for_rspec'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example.rb:366:in `run_before_example'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example.rb:150:in `block in run'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example.rb:328:in `with_around_example_hooks'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example.rb:148:in `run'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example_group.rb:500:in `block in run_examples'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example_group.rb:496:in `map'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example_group.rb:496:in `run_examples'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/example_group.rb:463:in `run'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:111:in `block (2 levels) in run_specs'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:111:in `map'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:111:in `block in run_specs'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/reporter.rb:53:in `report'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:107:in `run_specs'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:85:in `run'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:69:in `run'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/lib/rspec/core/runner.rb:37:in `invoke'
# /var/lib/gems/1.9.1/gems/rspec-core-3.1.4/exe/rspec:4:in `<top (required)>'
# /usr/local/bin/rspec:23:in `load'
# /usr/local/bin/rspec:23:in `<main>'
#
# Showing full backtrace because every line was filtered out.
# See docs for RSpec::Configuration#backtrace_exclusion_patterns and
# RSpec::Configuration#backtrace_inclusion_patterns for more information.
Edit: Here is an example of one of the spec files, however, the issue comes up on about 20 spec files. I know my solutions are correct and my peers aren't having the same issues I am:
first_name = "M"
last_name = "R"
age = 23
describe 'first_name' do
it "is defined as a local variable" do
expect(defined?(first_name)).to eq 'local-variable'
end
it "is a String" do
expect(first_name).to be_a String
end
end
describe 'last_name' do
it "is defined as a local variable" do
expect(defined?(last_name)).to eq 'local-variable'
end
it "be a String" do
expect(last_name).to be_a String
end
end
describe 'age' do
it "is defined as a local variable" do
expect(defined?(age)).to eq 'local-variable'
end
it "is an integer" do
expect(age).to be_a Fixnum
end
end

rspec bugs when trying to run rake

I'm trying to teach myself some ruby using the app academy tutorials and after doing the readings, installing rvm,rubygems and rspec2 when I even try to run the first most basic code (00_hello) with rake I get the whole error :
(in /home/deadpool/Documents/learn_ruby)
/home/deadpool/Documents/learn_ruby/rspec_config.rb:3:in `block in <top (required)>': undefined method `color=' for #<RSpec::Core::Configuration:0x0000000293dee0> (NoMethodError)
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core.rb:67:in `configure'
from /home/deadpool/Documents/learn_ruby/rspec_config.rb:1:in `<top (required)>'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration.rb:162:in `require'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration.rb:162:in `block in requires='
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration.rb:162:in `map'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration.rb:162:in `requires='
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration_options.rb:22:in `block in configure'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration_options.rb:21:in `each'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/configuration_options.rb:21:in `configure'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/command_line.rb:17:in `run'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/runner.rb:55:in `run_in_process'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/runner.rb:46:in `run'
from /home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/runner.rb:10:in `block in autorun'
rake aborted!
ruby -S bundle exec rspec -I/home/deadpool/Documents/learn_ruby/00_hello -I/home/deadpool/Documents/learn_ruby/00_hello/solution -f documentation -r ./rspec_config "/home/deadpool/Documents/learn_ruby/00_hello/hello_spec.rb" failed
/home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/rake_task.rb:117:in `rescue in block (2 levels) in initialize'
/home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/rake_task.rb:113:in `block (2 levels) in initialize'
/home/deadpool/.rvm/gems/ruby-2.0.0-p481/gems/rspec-core-2.0.0/lib/rspec/core/rake_task.rb:109:in `block in initialize'
Tasks: TOP => default => spec
(See full trace by running task with --trace)
I tried to google some of the errors, but with no success. I had previously another error with the rake file using rspec v2 and the current version is 3.0.0, so I had to install the older and I think it might be another setup problem. Thanks if someone can help me or direct me.
rspec_config.rb file :
RSpec.configure do |c|
c.fail_fast = true
c.color = true
end
hello.rb file:
def hello
"Hello!"
end
def greet(who)
"Hello, #{who}!"
end
UPDATE
Getting new error as :-
While I changed c.color = true to c.color_enabled = true
(in /home/deadpool/Documents/learn_ruby)
the hello function says hello (FAILED - 1)
Failures: 1) the hello function says hello Failure/Error:
Unable to find matching line from backtrace undefined method run_all' for []:Array
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/hooks.rb:116:inrun_hook_filtered'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/example_group.rb:176:in eval_before_alls'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/example_group.rb:231:inrun'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/command_line.rb:26:in block (2 levels) in run'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/command_line.rb:26:inmap'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/command_line.rb:26:in block in run'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/reporter.rb:11:inreport'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/command_line.rb:23:in run'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/runner.rb:55:inrun_in_process'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/runner.rb:46:in run'
# /home/deadpool/.rvm/gems/ruby-2.1.2/gems/rspec-core-2.0.0/lib/rspec/core/runner.rb:10:inblock in autorun'
UPDATE
hello_spec.rb file :
require "hello"
describe "the hello function" do
it "says hello" do
hello.should == "Hello!"
end
end
describe "the greet function" do
it "says hello to someone" do
greet("Alice").should == "Hello, Alice!"
end
it "says hello to someone else" do
greet("Bob").should == "Hello, Bob!"
end
end
UPDATE
So, I updated rspec to v3.0.0 and changed Rakefile gem 'rspec', '~>3.0.0' and c.color = true back. Everything is working now(getting some deprecation warnings, but nothing critical), getting the output that is in the tutorial. Guess I just had to updae my rspec and change the version in the Rakefile. Thank you so much :)
Your error log is showing you are in rspec-core-2.0.0 version and your error is saying -
rspec_config.rb:3:in `block in <top (required)>': undefined method `color=' for
#<RSpec::Core::Configuration:0x0000000293dee0> (NoMethodError)
Now Deprecate config options confirms that below versions of 2.99.0.rc1 / 2014-05-18 or 2.99.0 methods were - #color_enabled, #color_enabled= and #color?. Which are changed since 2.99.0 to #color, #color= and #color_enabled?.
I got the information from the changelog as I linked -
Deprecate #color_enabled, #color_enabled= and #color? in favour of #color, #color= and #color_enabled? output. (Jon Rowe)
Thus you need to write as
RSpec.configure do |c|
c.fail_fast = true
c.color_enabled = true
end
Regarding your new error, I found it as a bug undefined methodrun_all' for []:Array`. Which has been fixed in this patch. Check this Rspec issue.
My suggestion use Rspec 3.0, at least you will be happy. In this case revert the color_enabled to color.
Hope this would help you.

Pure Ruby rspec test passes without method being defined

I have an rspec test on a pure Ruby model:
require 'spec_helper'
require 'organization'
describe Organization do
context '#is_root?' do
it "creates a root organization" do
org = Organization.new
expect { org.is_root?.to eq true }
end
end
end
My organization model looks like this:
class Organization
attr_accessor :parent
def initialize(parent = nil)
self.parent = parent
end
end
The output when running the tests:
bundle exec rspec spec/organization_spec.rb:6
Run options: include {:locations=>{"./spec/organization_spec.rb"=>[6]}}
.
Finished in 0.00051 seconds
1 example, 0 failures
When I run the test, it passes, despite the fact that the method is_root? doesn't exist on the model. I usually work in Rails, not pure Ruby, and I've never seen this happen. What is going on?
Thanks!
It should be:
expect(org.is_root?).to eq true
When you pass block to expect it is being wrapped in ExpectationTarget class (strictly speaking BlockExpectationTarget < ExpectationTarget). Since you didn't specify what you expect from this object, the block is never executed, hence no error is raised.
You are passing a block to expect, which is never being called. You can see this by setting an expectation on that block
expect { org.is_root?.to eq true }.to_not raise_error
1) Organization#is_root? creates a root organization
Failure/Error: expect { puts "HI";org.is_root?.to eq true }.to_not raise_error
expected no Exception, got #<NoMethodError: undefined method `is_root?' for #<Organization:0x007ffa798c2ed8 #parent=nil>> with backtrace:
# ./test_spec.rb:15:in `block (4 levels) in <top (required)>'
# ./test_spec.rb:15:in `block (3 levels) in <top (required)>'
# ./test_spec.rb:15:in `block (3 levels) in <top (required)>'
Or by just putting a plain raise or puts inside the block, neither of which will be called:
expect { puts "HI"; raise; org.is_root?.to eq true }
The block form is used for expecting that a piece of code raises an exception or not. The correct syntax for checking values is:
expect(org.is_root?).to eq(true)

Resources