I am writing an ATM-system-like socket/server solution. I would appreciate if someone could tell me what I'm missing. For some reason, I get the following error running my stub test suite:
# Running tests:
.E
Finished tests in 0.002411s, 829.4384 tests/s, 414.7192 assertions/s.
1) Error:
test_0001_connects_to_a_host_with_a_socket(AtmClient::connection):
NoMethodError: undefined method `new' for #<SpoofServer:0x9dce2dc #clients=[], #server=#<TCPServer:fd 5>>
/media/wildfyre/Files/Programming/KTH/progp/Atm/spec/client/SpoofServer.rb:12:in `start'
/media/wildfyre/Files/Programming/KTH/progp/Atm/spec/client/client_spec.rb:12:in `block (3 levels) in <top (required)>'
2 tests, 1 assertions, 0 failures, 1 errors, 0 skips
My minispec file is:
require_relative '../spec_helper.rb'
require_relative '../../lib/AtmClient.rb'
require_relative 'SpoofServer.rb'
describe AtmClient do
it "can be created with no arguments" do
AtmClient.new.must_be_instance_of AtmClient
end
describe 'connection' do
it "connects to a host with a socket" do
spoof = SpoofServer.new.start
client = AtmClient.new.connect
spoof.any_incoming_connection?.must_be true
spoof.kill
end
end
end
My SpoofServer file is:
require 'socket'
class SpoofServer
def initialize
end
def start
#clients = []
#server = TCPServer.new 1234
#listener_thread = new Thread do
#clients.add #server.accept
end
end
def any_incoming_connection?
#clients.size > 0
end
def kill
#listener_thread.exit
#clients.each {|c| c.close}
end
end
As you can read in the trace of the calls stack:
NoMethodError: undefined method `new' for #<SpoofServer:...>
/.../spec/client/SpoofServer.rb:12:in `start'
The error is inside the start method defined in SpoofServer.rb, at line 12, the wrong line is:
#listener_thread = new Thread do
That should be:
#listener_thread = Thread.new do
As you have written it, what you are actually doing is to calling the new method passing the Thread class as argument. Since no new method is defined for instances of the SpoofServer class you get the NoMethodError exception.
In body of instance method SpoofServer#start, you can't call the class method SpoofServer.new by new.
Related
I am making a tool in ruby which can interact with databases.
I am using amalgalite as an adapter for sqlite3.
Code:
require 'amalgalite'
# this is class RQuery
class RQuery
def db_open(db_name)
#db = Amalgalite::Database.new "#{db_name}.db"
make_class
end
def exec_this(query)
#db.execute(query)
end
def make_class
tables_list = exec_this("select name from sqlite_master where type='table'")
tables_list.each do |table|
#class_created = Object.const_set(table[0].capitalize, Class.new)
#class_created.class_eval do
define_singleton_method :first do
RQuery.new.exec_this("select * from #{table[0]} order by #{table[0]}.id ASC limit 1")
end
end
end
end
def eval_this(input)
instance_eval(input)
end
def code
print '>>'
input = gets
exit if input =~ /^q$/
puts eval_this(input)
code
end
end
Now when I am running the code everything works fine until I call table_name.first
It gives output
vbhv#fsociety ~/git/R-Query/bin $ ruby main.rb
Enter the code or q for quit
>>db_open('vbhv')
users
persons
people
programmers
>>Users.first
/home/vbhv/git/R-Query/lib/r-query.rb:36:in `instance_eval': undefined method `execute' for nil:NilClass (NoMethodError)
Did you mean? exec
from /home/vbhv/git/R-Query/lib/r-query.rb:29:in `block (3 levels) in make_class'
from (eval):1:in `eval_this'
from /home/vbhv/git/R-Query/lib/r-query.rb:36:in `instance_eval'
from /home/vbhv/git/R-Query/lib/r-query.rb:36:in `eval_this'
from /home/vbhv/git/R-Query/lib/r-query.rb:43:in `code'
from /home/vbhv/git/R-Query/lib/r-query.rb:44:in `code'
from /home/vbhv/git/R-Query/lib/r-query.rb:44:in `code'
from main.rb:4:in `<main>'
Now the 'execute' function it is talking about is inside amalgalite. What am I doing wrong here?? Thanks in Advance!
The problem in this was that the new class formed dynamically doesn't know about the connection variable '#db'. Hence the code solves the problem.
#class_created.instance_variable_set(:#database, #db)
A big thanks to Jagdeep Singh.
I want to write a testsuite to run my unit tests in ruby. So far I have come up with:
require 'test/unit/ui/console/testrunner'
require 'test/unit/testsuite'
class RunTests
def self.Run(arg)
test_suite = Test::Unit::TestSuite.new("All ATP Tests")
test_suite << 'unit/TestName1.rb'
test_suite << 'unit/TestName2.rb'
test_suite << 'unit/TestName3.rb'
arg used here in env setup
Test::Unit::UI::Console::TestRunner::new(test_suite).start
end
end
the tests all have the structure:
require 'test/unit'
class TestCalssName < Test::Unit::TestCase
def setup
end
def test_testcasename
end
def teardown
end
end
When I test the runner out in irb I get an error about undefined method run within a testcase:
irb(main):002:0> RunTests::Run("-env=qa-old")
Loaded suite All ATP Tests
Started
Finished in 0.002 seconds.
0 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
0% passed
0.00 tests/s, 0.00 assertions/s
NoMethodError: undefined method `run' for "unit/TestTestName.rb":String
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/testsuite.rb:121:in `run_test'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/testsuite.rb:53:in `run'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/ui/testrunnermediator.rb:65:in `run_suite'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/ui/testrunnermediator.rb:44:in `run'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/ui/testrunnermediator.rb:100:in `with_listener'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/ui/testrunnermediator.rb:40:in `run'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/ui/testrunner.rb:40:in `start_mediator'
from /home/user/.gem/jruby/1.9/gems/test-unit-2.5.5/lib/test/unit/ui/testrunner.rb:25:in `start'
from /home/user/projects/verizon-smoke-tests/src/main/ruby/unit/RunATP.rb:27:in `Run'
from (irb):2:in `evaluate'
from org/jruby/RubyKernel.java:1119:in `eval'
from org/jruby/RubyKernel.java:1519:in `loop'
from org/jruby/RubyKernel.java:1282:in `catch'
from org/jruby/RubyKernel.java:1282:in `catch'
from /usr/local/jruby-1.7.9/bin/irb:13:in `(root)'
irb(main):003:0>
I tried putting a run method into the testcases but I still get the error (the exact same error about the run method being undefined). Am I missing something?
A
check if you're not calling run instead of Run, as Ruby is case-sensitive this might be the problem. We need the source code of "unit/TestTestName.rb" to get a better understanding of the problem.
EDIT
You are adding your TestCases as strings, like this :
test_suite << 'unit/TestName1.rb'
Since "unit/TestName1.rb" is a String, it has no run method that Ruby can call.
Ruby is expecting TestSuite objects in your test_suite object instead of Strings.
From Ruby Doc:
suite() :
Rolls up all of the test* methods in the fixture into one suite,
creating a new instance of the fixture for each method.
Instead, you should:
require on all your TestNameX.rb file
Add each TestCase to your TestSuite using the suite
It should be something like this:
require 'test/unit/ui/console/testrunner'
require 'test/unit/testsuite'
require 'unit/TestName1.rb'
require 'unit/TestName2.rb'
class RunTests
def self.Run(arg)
test_suite = Test::Unit::TestSuite.new("All ATP Tests")
test_suite << TestClassName1.suite
test_suite << TestClassName2.suite
arg used here in env setup
Test::Unit::UI::Console::TestRunner::new(test_suite).start
end
end
I am not sure about the TestRunner::new(test_suite).start, try:
Test::Unit::UI::Console::TestRunner.run(test_suite)
Feel free to have a look at the Ruby documentation
Test::Unit Test Suite
In Rspec, testing whether an instance is able to call method x.
DockingStation.rb
class DockingStation
def release_bike
end
end
Docking_spec.rb
require_relative '../lib/DockingStation'
describe DockingStation do
before(:each) do
#dockstat = DockingStation.new
end
describe "#DockingStation" do
it "Check release method" do
expect(#dockstat).to respond_to(:release_bike)
end
end
end
Currently getting the following error message:
1) DockingStation#DockingStation Check release method
Failure/Error: expect(#dockstat).to respond_to(:release_bike)
expected #<DockingStation:0x007fa518a6da00> to respond to :release_bike
# ./spec/Docking_spec.rb:10:in `block (3 levels) in <top (required)>'
What I'm expecting is for the object #dockstat instantiated in the Docking_spec.rb to respond to the release_bike method defined in DockingStation.rb, but this is not the case.
require_relative '../DockingStation'
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)
I have a module in app/misc/dsl/builder.rb that has this code
module Dsl
class Builder
def initialize(context, &block)
return if not block_given?
parent_context = block.binding.eval "self"
parent_context.extend Proxy
parent_context.object = context
parent_context.instance_eval &block
end
end
def self.set_context(context, &block)
Dsl::Builder.new(context, &block)
end
end
Note: this directory misc is preloaded in application.rb
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**/}'),
Rails.root.join('app', 'misc', '{**/}')
]
Then, somewhere in the text (lets say at foo.rb) I have this code:
Dsl.set_context(obj) do
#some code with obj receiving messages
end
The test stack we are using consists on Zeus+Guard+Rspec. Now, lets say I rewrite the code to something not working
Dsl.set_context(obj) do
asdqwe #this message does not exists
end
From times to times, I receive this baffling message
1) SomeOtherClass search_hash receiving keywords params should query for those keywords
Failure/Error: subject.search_hash
NoMethodError:
undefined method `set_context' for Dsl:Module
# ./app/misc/product_query.rb:116:in `base_search_hash'
# ./app/misc/product_query.rb:25:in `search_hash'
# ./spec/misc/product_query_spec.rb:78:in `block (4 levels) in <top (required)>'
# -e:1:in `<main>'
instead of the correct message that should be regarding undefined method asdqwe
Any clue about this?
Look here
it says:
Rails 3 has been updated such that classes/modules (henceforth, C/M)
are lazy loaded from the autoload paths as they are needed
so, you can do require_relative 'app/misc/dsl/builder.rb' in your rspec_helper.rb (can it be better with just require?) The problem must be that the loader doesn't know in advance where to find Dsl.set_context, but he will know once you have referenced Dsl::Builder
Hope it helps