i am trying to create a list method stub for Chef::DataBag class as follows:
$ cat spec/spec_helper.rb
require "rspec"
RSpec.configure { |config|
config.mock_framework = :rspec
config.mock_with :rspec
}
$ cat spec/test_spec.rb
require "spec_helper"
require "chef"
RSpec.describe "test" do
describe "simple test" do
it "mocks chef databag" do
allow(Chef::DataBag).to recieve(:list).and_return {}
end
end
end
$ grep "rspec \|chef " Gemfile.lock | head -n 2
gem "chef", "11.16.4"
gem "rspec", "3.1.0"
when executing rspec i get the following error.
$ bundle exec rspec spec/test_spec.rb
F
Failures:
1) test simple test mocks chef databag
Failure/Error: allow(Chef::DataBag).to recieve(:list).and_return {}
NoMethodError:
undefined method `recieve' for #<RSpec::ExampleGroups::Test::SimpleTest:0x000000049964f8>
# ./spec/test_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.00048 seconds (files took 0.53998 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/test_spec.rb:6 # test simple test mocks chef databag
that is how i verified that Chef::DataBag has the list method:
$ bundle exec ruby -e "require 'chef'; puts Chef::DataBag.methods" | grep list
list
can you please point out what is wrong?
You misspelled "receive." Try this:
allow(Chef::DataBag).to receive(:list).and_return {}
Related
$ gem install gmp
Building native extensions. This could take a while...
Successfully installed gmp-0.7.43
Parsing documentation for gmp-0.7.43
Done installing documentation for gmp after 0 seconds
1 gem installed
$ cat gmp-test.rb
require 'gmp'
$ /opt/src/ruby-3.2.0/bin/ruby gmp-test.rb
<internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- /home/dunham/.local/share/gem/ruby/3.2.0/gems/gmp-0.7.43/lib/../ext/gmp (LoadError)
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
from /home/dunham/.local/share/gem/ruby/3.2.0/gems/gmp-0.7.43/lib/gmp.rb:9:in `<top (required)>'
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:159:in `require'
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:159:in `rescue in require'
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:149:in `require'
from gmp-test.rb:1:in `<main>'
<internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- gmp (LoadError)
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
from gmp-test.rb:1:in `<main>'
Library seems to be dead. It's expecting gmp.so to be in ext directory but it ends up in lib directory, it's probably new rubygems doing things differently.
>> require "gmp"
<internal:/home/alex/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in 'require':
cannot load such file -- /home/alex/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/gmp-0.7.43/lib/../ext/gmp (LoadError)
$ ls $(dirname $(gem which gmp))
gmp.rb gmp.so
# move ^ that to ../ext/
$ mv $(dirname $(gem which gmp))/gmp.so $(dirname $(gem which gmp))/../ext/
>> require "gmp"
=> true
>> GMP::Z(0)
=> 0
Update
From the linked logs looks like you're still not loading gmp.so which is where all the classes are defined. You can copy gmp.so into your app:
# copy `gmp.rb`
$ cp $(gem which gmp) .
# copy `gmp.so`
$ cp $(dirname $(gem which gmp))/gmp.so .
# or if you moved it to ext
$ cp $(dirname $(gem which gmp))/../ext/gmp.so .
$ touch app.rb
$ ls
app.rb gmp.rb gmp.so
gmp.rb defines GMP.sprintf method, if this is not a required method and you don't use it, you can remove this file.
# gmp.rb
# require 'rbconfig'
#
# ENV['PATH'] = [File.expand_path(
# File.join(File.dirname(__FILE__), "..", "ext")
# ), ENV['PATH']].compact.join(';') if RbConfig::CONFIG['host_os'] =~ /(mswin|mingw|mingw32)/i
#
# require File.dirname(__FILE__) + '/../ext/gmp'
# unless RUBY_VERSION =~ /^1.8/
module GMP
def self.sprintf(format, *args)
first_pct = format.index '%'
result = format[0...first_pct]
#format.gsub(/(?<!%)%[0#+ ']*[0-9]*.?[0-9]*[a-zA-Z][^%]*/) do |fragment|
format.gsub(Regexp.new('(?<!%)%[0#+ \']*[0-9]*.?[0-9]*[a-zA-Z][^%]*')) do |fragment|
arg = args.shift
if fragment =~ /%[0#+ ']*[0-9]*.?[0-9]*[ZQF]/
result << sprintf2(fragment, arg)
elsif fragment =~ /%[0#+ ']*[0-9]*.?[0-9]*[PR]/ && GMP.const_defined?(:MPFR_VERSION)
result << GMP::F.sprintf2(fragment, arg)
else
result << (fragment % arg)
end
end
result
end
end
# end
# app.rb
require_relative "gmp.so"
p GMP::Z
p GMP::Z(0)
p GMP::Q
p GMP::F
require_relative "gmp.rb"
p GMP.sprintf "%Zd", GMP.Z(0)
$ ruby --yjit -v
ruby 3.2.0 (2022-12-25 revision a528908271) +YJIT [x86_64-linux]
$ ruby --yjit app.rb
GMP::Z
0
GMP::Q
GMP::F
"0"
We have written a large number of selenium UI tests that very occasionally fail due to dumb reasons like a web server being too slow. Additionally, we make heavy use of rspec tags to only run the tests that we want to run. We want to retry ONLY the tests that are tagged with something AND that have previously failed. In the following example, running rspec --tag all --only_failures runs the last two tests, when I only want it to run the 2nd test.
spec_helper.rb
RSpec.configure do |config|
config.example_status_persistence_file_path = "RunResults.txt"
end
test_spec.rb
require 'rspec'
require 'spec_helper'
require './test'
RSpec.describe Test do
it "should pass", :all, :one do
expect(1).to eql(1)
end
it "should fail", :all, :two do
expect(1).to eql(2)
end
it "should fail", :three do
expect(1).to eql(2)
end
end
RunResults.txt
example_id | status | run_time |
------------------------ | ------ | --------------- |
./spec/test_spec.rb[1:1] | passed | 0.00055 seconds |
./spec/test_spec.rb[1:2] | failed | 0.01796 seconds |
./spec/test_spec.rb[1:3] | failed | 0.00017 seconds |
RSpec
$ rspec --tag all --only_failures
Run options: include {:all=>true, :last_run_status=>"failed"}
.FF
Failures:
1) Test should fail
Failure/Error: expect(1).to eql(2)
expected: 2
got: 1
(compared using eql?)
# ./spec/test_spec.rb:11:in `block (2 levels) in <top (required)>'
2) Test should fail
Failure/Error: expect(1).to eql(2)
expected: 2
got: 1
(compared using eql?)
# ./spec/test_spec.rb:15:in `block (2 levels) in <top (required)>'
Finished in 0.01949 seconds (files took 0.24733 seconds to load)
3 examples, 2 failures
Failed examples:
rspec ./spec/test_spec.rb:10 # Test should fail
rspec ./spec/test_spec.rb:14 # Test should fail
I'm trying to create a command line program with sub-commands using OptionParser. I'm following "ruby's OptionParser to get subcommands".
The problem is that it does not allow for a use case like this:
ruby main.rb --version
#=> main.rb in `<main>': undefined method `order!' for nil:NilClass (NoMethodError)
But it does allow for this:
ruby main.rb foo --options
ruby main.rb --options foo
ruby main.rb --options foo --options
How would I be properly handle command line arguments, in the case that no subcommand is given.
My example code is:
global = OptionParser.new do |opts|
opts.banner = "Usage: opt.rb [options] [subcommand [options]]"
opts.on("-v", "--version", "Print the version") do |v|
options[:version] = v
end
opts.separator ""
opts.separator subtext
end
The lines with the error:
global.order!
command = ARGV.shift
subcommands[command].order!
If global.order! uses all of ARGV, then command is nil. So... check for that.
global.order!
command = ARGV.shift
unless command
STDERR.puts "ERROR: no subcommand"
STDERR.puts global # prints usage
exit(-1)
end
subcommands[command].order!
Maybe this'll help:
require 'optparse'
VERSION = '1.0.0'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }
opt.on_tail('-v', '--version') do
puts VERSION
exit
end
end.parse!
puts options
Saving it as "test.rb" and running it with ruby test.rb returns:
{}
Running it with ruby test.rb -f or --foo returns:
{:foo=>true}
Running it with ruby test.rb -v or --version returns:
1.0.0
For more fun, running ruby test.rb -h or --help returns:
Usage: test [options]
-f, --foo Foo it
even though I didn't define -h or --help.
If I wanted the -v and --version flags to appear in the list then I'd change them from a on_tail method to a normal on method:
require 'optparse'
VERSION = '1.0.0'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }
opt.on('-v', '--version', 'Returns the version') do
puts VERSION
exit
end
end.parse!
puts options
which would return:
Usage: test [options]
-f, --foo Foo it
-v, --version Returns the version
I can add:
puts ARGV
to the end of the script and see that OptionParser is correctly handling flags and parameters:
>ruby test.rb bar --foo
{:foo=>true}
bar
>ruby test.rb --foo bar
{:foo=>true}
bar
See "Pass variables to Ruby script via command line" for more information.
There is no way your example code will handle your sample inputs using --options. No handler for --options is defined. Nor is subtext. Your code returns:
undefined local variable or method `subtext' for main:Object (NameError)
Stripping the block to:
global = OptionParser.new do |opts|
opts.on("-v", "--version", "Print the version") do |v|
options[:version] = v
end
end
and running again returns:
invalid option: --options (OptionParser::InvalidOption)
So, again, your example doesn't match the results you say you're getting.
I have the following rb script which generate puppet facts according to the packages installed and which seems to be working ok in my puppet environment:
begin
pack = Facter::Core::Execution.execute('rpm -qa | grep ^ts')
packages = pack.split("\n")
packagehash = Hash.new
packages.each do |f|
packagehash[f.split("-")[0]] = f.split("-")[1] + ("-") + f.split("-")[2].split(".")[0]
end
rescue
end
begin
unless packagehash.empty?
packagehash.each_pair do |k,v|
Facter.add("bs_rpm_#{k}") {
setcode { "#{v}" }
}
end
end
rescue
end
I wrote the following spec which runs a small dummy test to see if my rspec env in general is ok:
require 'spec_helper'
describe 'bs package spec' do
before do
Facter.fact(:kernel).stubs(:value).returns("windows")
end
it "should run windows" do
Facter.fact(:kernel).value.should == "windows"
end
it "should create new facts" do
Facter::Core::Execution.stubs(:execute).with('rpm -qa | grep ^ts').returns('ts3_hostt01-1.0.0-34.x86_64\n')
Facter.fact(:bs_rpm_ts3_hostt01).value.should == "1.0.0-34"
end
end
But then when running rake spec I get the following error:
[dan#kyvltvm00022 bs_master]$ rake spec
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color
.F
Failures:
1) bs package spec should create new facts
Failure/Error: Facter::Core::Execution.stubs(:execute).with('rpm -qa | grep ^ts').returns('ts3_hostt01-1.0.0-34.x86_64\n')
NameError:
uninitialized constant Facter::Core
# ./spec/unit/facter/bs_package_spec.rb:13:in `block (2 levels) in <top (required)>'
Finished in 0.00692 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/unit/facter/bs_package_spec.rb:12 # bs package spec should create new facts
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color failed
[dan#kyvltvm00022 bs_master]$ exit
shell returned 1
[dan#kyvltvm00022 bs_master]$
What am I doing wrong or might be missing that is not loading Facter::Core ?? My spec_helper looks like this:
[dan#kyvltvm00022 bs_master]$ cat spec/spec_helper.rb
dir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift File.join(dir, 'lib')
# Don't want puppet getting the command line arguments for rake or autotest
ARGV.clear
require 'puppet'
require 'facter'
require 'mocha'
gem 'rspec', '>=2.0.0'
require 'rspec/expectations'
require 'puppetlabs_spec_helper/puppet_spec_helper'
RSpec.configure do |config|
# FIXME REVISIT - We may want to delegate to Facter like we do in
# Puppet::PuppetSpecInitializer.initialize_via_testhelper(config) because
# this behavior is a duplication of the spec_helper in Facter.
config.before :each do
# Ensure that we don't accidentally cache facts and environment between
# test cases. This requires each example group to explicitly load the
# facts being exercised with something like
# Facter.collection.loader.load(:ipaddress)
Facter::Util::Loader.any_instance.stubs(:load_all)
Facter.clear
Facter.clear_messages
end
end
[dan#kyvltvm00022 bs_master]$
[UPDATE]
After checking my test system I noticed the facter gem was missing core so I updated the code and test as follows:
pack is now:
pack = Facter::Util::Resolution.exec('rpm -qa | grep ^ts')
and the stub in my test now is:
Facter::Util::Resolution.stubs(:exec).with('rpm -qa | grep ^ts').returns('ts3_hostt01-1.0.0-34.x86_64\n')
And the result now is this:
[dan#kyvltvm00022 bs_master]$ rake spec
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color
.F
Failures:
1) bs package spec should create new facts
Failure/Error: Facter.fact(:bs_rpm_ts3_hostt01).value.should == "1.0.0-34"
NoMethodError:
undefined method `value' for nil:NilClass
# ./spec/unit/facter/bs_package_spec.rb:14:in `block (2 levels) in <top (required)>'
Finished in 0.00747 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/unit/facter/bs_package_spec.rb:12 # bs package spec should create new facts
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color failed
[dan#kyvltvm00022 bs_master]$
What am i doing wrong in my test?
Looking through the facter code, this is the file you're requiring:
https://github.com/puppetlabs/facter/blob/master/lib/facter.rb
It doesn't require core/execution itself... without digging too much further in could you just try this in your spec_helper:
require 'facter/core/execution'
I'm a beginner in programming and wrote this little program:
Test.rb:
# encoding: utf-8
require 'open-uri'
require 'nokogiri'
def parse_file
doc = Nokogiri::XML(File.open("test.xml"))
parse_xml(doc)
end
def parse_xml(doc)
doc.root.elements.each do |node|
parse_tracks(node)
end
end
def parse_tracks(node)
if node.node_name.eql? 'kapitel'
puts 'New Kapitel'
end
end
I know how to execute this code:
ruby test.rb
But how can I call the def parse_file?
Simply add whatever you want to the end of your file. Ruby scripts are simply scripts, they are being interpreted:
…
end
parse_file # ⇐ HERE YOU GO
You can either call the method at the end of your test.rb file:
def parse_file
# ...
end
parse_file
And run it with
$ ruby test.rb
Or leave the file as it is, require it as a library and call the method manually:
$ ruby -r test.rb -e "parse_file"
Rather than hard-coding your file path, you can pass it as an argument when calling your script. Arguments can be accessed via the ARGV array:
def parse_file(file)
doc = Nokogiri::XML(File.open(file))
parse_xml(doc)
end
parse_file(ARGV.first)
Now you can run it with:
$ ruby test.rb test.xml
Another option is to make the script executable. Add a shebang as the first line of you file:
#!/usr/bin/env ruby
And set the execute flag:
$ chmod +x test.rb
Now you can run it with:
$ ./test.rb test.xml
just add
parse_file
in the end of your ruby file