I'm following the exercises from Ruby Koans and in about_proxy_object_project.rb there's this bit of code:
class Proxy
def initialize(target_object)
#object = target_object
end
# This method was added by me
def method_missing(method_name, *args, &block)
#object.send method_name
end
end
That gets called like this:
def test_tv_methods_still_perform_their_function
tv = Proxy.new(Television.new) # Television is a class with a :channel attr_accessor and a power method
tv.channel = 10
tv.power
assert_equal 10, tv.channel
assert tv.on?
end
The problem is that the line tv.channel = 10 is "breaking" the interpreter and throwing:
[BUG] Stack consistency error (sp: 53, bp: 54)
ruby 2.0.0p0
(...)
full stack trace follows
I've tried the same code with Ruby 1.9.3 and it's working. I'm using Ruby 2.0.0-p195.
So, is this an error/bug? Or I'm doing something horribly wrong?
Yes. It is a Ruby bug in ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-linux]. At the end of the stack trace, it says:
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
You should report this to Ruby core. Please do so for the sake of the Ruby community.
As pointed out by matt, it is fixed in Ruby 2.0.0p247.
I don't see you doing anything wrong.
Related
The piece of code below gives me a NoMethodError. I'm a little confused why it gives me an error, and why I can't find anything about nesting methods in modules. Could someone please explain why this isn't working? Can I nest "defs" in modules?
module HowToBasic
module_function
def say_id_and_say_name(id)
# nested method
def say_id(id)
p id
end
# errors here with `say_id_and_say_name':
# undefined method `say_id' for HowToBasic:Module (NoMethodError)
# from teststuff.rb:24:in `<main>'
say_id(id)
end
end
HowToBasic.say_id_and_say_name("99999")
Version:
ruby 2.3.1p112
I had a look and couldn't find anything about this:
relates to includes NoMethodError when trying to access method defined in included module
relates to classes https://bugs.ruby-lang.org/issues/11665
seems weird Access a Ruby module's method within same module
you're missing self keyword in method definition - without it say_id_and_say_name is just an instance method, thus it can't be invoked on Module.
module HowToBasic
module_function
def self.say_id(id)
p id
end
def self.say_id_and_say_name(id)
say_id(id)
end
end
HowToBasic.say_id_and_say_name("99999")
I have been using the MiniTest that comes with Ruby 2.1 without a problem. I would subclass MiniTest::Unit:TestCase create a couple methods like 'test_simple', and everything just worked. I would use Expectations and Asserts without a problem.
I have upgraded Minitest to 5.4.0 using a gem. Everywhere I use Expectations (musts and wonts) I get a strangle error. Example of the test class.
gem 'minitest'
require "minitest/autorun"
require "rest-client"
require "json"
require "pp"
# require './testcase_addins'
class TestUserKey < Minitest::Test
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
When I run this, the assert line passes without a problem, but must_be line throws this error:
1) Error:
TestUserKey#test_simple:
NoMethodError: undefined method `assert_operator' for nil:NilClass
(eval):4:in `must_be'
user_key_testcase.rb:14:in `test_simple'
The strange part is what is the nil:NilClass in the error can't be nil; it's 0. Even I change the Fixnum to a String, I still get the same error.
If I change the test to a spec test, everything works again. So I can't use Expectations with in Unit Tests? IF that is the case, could someone explain why?
The short answer is that with 5.4.0 your test class must inherit from MiniTest::Spec in order to use expectations.
I tested this on a new ubuntu machine with ruby 2.1.2 installed via RVM:
rvm install ruby-2.1.2
This code works with the stock ruby 2.1.2 (no 5.4.0 minitest gem installed, slightly cleaned up from your example code above):
#!/usr/bin/env ruby
require 'minitest/unit'
require "minitest/autorun"
class TestUserKey < MiniTest::Unit::TestCase
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
Running this code works fine. To reproduce the error listed above, install minitest 5.4.0:
gem install minitest -v 5.4.0
Now the code fails with "NoMethodError: undefined method `assert_operator' for nil:NilClass". You now have both versions of minitest installed:
~/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/minitest/ # stock ruby version of minitest
~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/ # minitest v5.4.0 installed via rubygems
Now that everything is set up, we can dig into what exactly is happening. The expectations are defined with a call to infect_an_assertion, like this:
infect_an_assertion :assert_operator, :must_be, :reverse
For 5.4.0 that call happens in ~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/lib/minitest/expectations.rb. It's roughly the same in both versions, it just happens in a different place.
infect_an_assertion is also roughly the same for both versions. For :must_be it winds up making this call, which is identical between the two versions of minitest:
MiniTest::Spec.current.#{meth}(args.first, self, *args[1..-1])
They're doing some metaprogramming here, the call at runtime will look more like this since meth is set to assert_operator:
MiniTest::Spec.current.assert_operator(...)
The important part is MiniTest::Spec.current. In 5.4.0 this method returns nil, which results in a NoMethodError exception when it tries to call assert_operator on nil.
In the stock minitest from ruby 2.1.2:
Here MiniTest::Spec inherits from MiniTest::Unit::TestCase. TestCase defines the method current and returns a value that was set in the initialize method. You can see this all happening around line 1303 of ~/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/minitest/unit.rb:
def initialize name # :nodoc:
#__name__ = name
#__io__ = nil
#passed = nil
##current = self # FIX: make thread local
end
def self.current # :nodoc:
##current # FIX: make thread local
end
Therefore, when you inherit from MiniTest::Unit::TestCase in your test class with the stock minitest, current is defined as a method and is guaranteed to return a value when the above call to MiniTest::Spec.current is made. This is why it works in the stock ruby 2.1.2 minitest.
In minitest 5.4.0
In 5.4.0, Minitest::Spec inherits from Minitest::Test, which does not define current (nor do any of its parents). The current method is defined directly on Minitest::Spec. It simply returns Thread.current[:current_spec]:
# line 83 of ~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/lib/minitest/spec.rb
def self.current # :nodoc:
Thread.current[:current_spec]
end
The value of Thread.current[:current_spec] is set in the Minitest::Spec constructor on line 87 of the same file:
def initialize name # :nodoc:
super
Thread.current[:current_spec] = self
end
The problem is that when your test class inherits from Minitest::Test, the Minitest::Spec constructor never gets called and Thread.current[:current_spec] is never initialized. That means the call in infect_an_assertion to Minitest::Spec.current returns nil, which results in the NoMethodError you're seeing when it tries to call assert_operator on nil. The solution is to make your test class inherit from Minitest::Spec so that the constructor is called and Thread.current[:current_spec] gets a value.
Here is a slightly modified version of the original code that works with minitest 5.4.0:
#!/usr/bin/env ruby
gem 'minitest'
require "minitest/autorun"
class TestUserKey < Minitest::Spec
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
Hope this helps!
From the minitest readme, it seems like the must style syntax is a part of the spec syntax, which would require you to use methods like describe and it instead of defining your own unit test methods.
tried this on ruby 2.0.0 / 247 or head:
require 'objspace'
ObjectSpace.trace_object_allocations -> undefined method `trace_object_allocations'
for ObjectSpace:Module
Docs say it should work http://www.ruby-doc.org/stdlib-2.0/libdoc/objspace/rdoc/ObjectSpace.html any idea what I'm missing ?
For higher ruby versions you still may get errors like:
undefined method `memsize_of' for ObjectSpace:Module
To solve this issue -> You need to require 'objspace'. According to https://ruby-doc.org/stdlib-2.3.1/libdoc/objspace/rdoc/ObjectSpace.html#method-c-memsize_of
Only available when installing ruby-head aka ruby 2.1
From the output of puts ObjectSpace.methods.sort after requiring objspace, it looks like that method doesn't exist.
irb(main):005:0> puts ObjectSpace.methods.sort
...
reachable_objects_from
remove_class_variable
remove_instance_variable
respond_to?
send
singleton_class
singleton_methods
taint
tainted?
tap
to_enum
to_s
trust
undefine_finalizer
untaint
untrust
untrusted?
=> nil
irb(main):009:0> ObjectSpace.methods.include? :trace_object_allocations
=> false
You can see that it contains the ::reachable_objects_from method, which is mentioned in the docs, but not the one you're looking for, unfortunately.
I have been working on my Ruby. When trying to execute this simple example from the Ruby Object documentation, I get this error:
undefined method `instance_variable_defined?'
This is my code:
class Fred
def initialize(p1, p2)
#a, #b = p1, p2
end
end
fred = Fred.new('cat', 99)
fred.instance_variable_defined?(:#a) #=> true
fred.instance_variable_defined?("#b") #=> true
fred.instance_variable_defined?("#c") #=> false
What have I done wrong? I tested this on another machine with Ubuntu 10.04 and it works fine. I'm using Centos 5.5 by the way.
Does anyone knows how to fix this?
The only thing I can think of is that you're using an ancient version of Ruby (1.8.5 or earlier), as Object#instance_variable_defined? has been in Ruby since 1.8.6.
I have this code in Ruby waitr ..
$LOAD_PATH.unshift File.join(File.dirname(__FILE__),'..') if $0 == __FILE__
require 'test/unit'
require 'Watir'
require 'Watir/contrib/enabled_popup'
class TC_Dialog_Test<Test::Unit::TestCase
$ie=Watir::IE.new
$ie.bring_to_front()
$myDir = File.expand_path(File.dirname(__FILE__))
def setup
$ie.goto "file://#{$myDir}/aa.html"
end
def test_confirm_OK
sleep(3)
$ie.button(:id, 'btnConfirm').click_no_wait
$hwnd = $ie.enable_popup(5)
if ($hwnd)
$popup =WinClicker.new
$popup.makeWindowsActive($hwnd)
sleep(3)
# $popup.clickWindowsButton($hwnd,"OK")
puts "you pressed Comfirm-ok"
sleep(3)
end
end
end
when runnung this code get this error results ...
test_confirm_OK(TC_Dialog_Test):
WIN32OLERuntimeError: unknown property or method `document'
HRESULT error code:0x800706b5
The interface is unknown.
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/ie.rb:417:in `method_missing'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/ie.rb:417:in `document'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/container.rb:767:in `ole_inner_elements'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/container.rb:838:in `locate_input_element'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/input_elements.rb:10:in `locate'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:47:in `assert_exists'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:278:in `enabled?'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:53:in `assert_enabled'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:214:in `click_no_wait'
Mo.rb:16:in `test_confirm_OK'
You are using Watir 1.5.3, but the current stable is 1.8.1. I suggest you to update your gem to the latest and try again. There is a good chance that the WIN32OLE object for IE has changed it's behavior and old gem is conflicting with it. (Have you updated IE or smth since last successful run?)
I got the same error using Watir 1.8.1. I don't know if there is anything wrong with your code, but in my case the tests ran fine on other machines.
I am running my tests in RubyMine 3.1.x. Running RubyMine as Administrator allowed Ruby to have the rights to interact with IE properly and the problem went away.
Edit:
Found the forum post which originally helped me solve the problem.