Verify not working in Ruby with Selenium::WebDriver - ruby

I am just starting to figure how to create unit tests using "test/unit". I copied the code generated by Selenium IDE and paste it into my Ruby test method.
But when running it with Ruby.exe, for some reason it is throwing an error:
Finished tests in 31.835891s, 0.0314 tests/s, 0.0942 assertions/s.
1) Error:
test_method(MyTestClass):
NameError: uninitialized constant Test::Unit::AssertionFailedError
teste-noticia.rb:30:in `rescue in verify'
teste-noticia.rb:29:in `verify'
teste-noticia.rb:42:in `test_method'
1 tests, 3 assertions, 0 failures, 1 errors, 0 skips
Anyone could help me to how assert correctly desired strings? Any good practice is welcome ;-).
Here is the code:
# encoding: utf-8
require "selenium-webdriver"
require "test/unit"
class MyTestClass < Test::Unit::TestCase
def setup
#driver = Selenium::WebDriver.for :firefox
#base_url = "http://www.yoursite.com"
#driver.manage.timeouts.implicit_wait = 30
#verification_errors = []
#wait = Selenium::WebDriver::Wait.new :timeout => 10
end
def teardown
#driver.quit
assert_equal [], #verification_errors
end
def element_present?(how, what)
#driver.find_element(how, what)
true
rescue Selenium::WebDriver::Error::NoSuchElementError
false
end
def verify(&blk)
yield
rescue Test::Unit::AssertionFailedError => ex
#verification_errors << ex
end
#your test methods go here
def test_method
#driver.get(#base_url + "/my-desired-path")
verify { assert_equal "Obama wins and will move U.S. forward", #driver.find_element(:css, "h1").text }
end
end
EDIT
My local gems:
C:\Users\wmj>gem list
*** LOCAL GEMS ***
addressable (2.3.2)
bigdecimal (1.1.0)
childprocess (0.3.6)
ffi (1.1.5 x86-mingw32)
io-console (0.3)
json (1.5.4)
libwebsocket (0.1.5)
minitest (2.5.1)
multi_json (1.3.7)
rake (0.9.2.2)
rdoc (3.9.4)
rubyzip (0.9.9)
selenium-webdriver (2.26.0)
test-unit (2.5.2)

I believe the issue is that you have required the 'minitest' gem, but are trying to use the classes in the 'test-unit' gem. 'Minitest' is installed by default in Ruby 1.9 instead of 'Test-Unit' (which was installed by default in 1.8). Minitest is only partially backwards compatible with Test-Unit.
Possible solutions:
Switch to Minitest:
It is the Test::Unit::AssertionFailedError in the verify method that is causing the exception. You could change it to the minitest equivalent, which appears to be MiniTest::Assertion. So your verify method would become:
def verify(&blk)
yield
rescue MiniTest::Assertion => ex
#verification_errors << ex
end
Use Test-Unit instead of Minitest:
Assuming you have the test-unit gem already installed (gem install test-unit), manually specify that you want to use that gem when doing require 'test/unit':
gem "test-unit"
require "test/unit"

Related

WebSocket and EventMachine timeout and error recovery

Using puma, faye-websocket-ruby and eventmachine, I am trying to implement a WebSocket server that is extended to support channels using redis.rb. Each client will supply a channel using a route currently in development as: "/C#{random number}". All of this logic needs to reside in the server, as the clients will be microprocessor-based Python systems that will not support higher-level libraries.
My code was based on ruby-websockets-chat-demo, as a starting point. One major change was to configure it to support multiple channels during WebSocket "on open".
The code is working when run normally. However, often when one client drops, the server hangs until it is restarted. I am trying to resolve that issue, but have not been able to do so so far. Initially, Heroku would throw an H12 timeout. I've implemented rack-timeout. I've tried rescuing timeouts within the server, but those never fire. I've implemented an "on error" event within the server but it never fires. Most often, the server just goes away until restarted. The client should fend for itself, but I need the server to recover and continue.
config.ru:
require './app'
require './middlewares/myserver_backend'
require 'rack-timeout'
use Rack::Timeout, service_timeout: 20, wait_timeout: 30, wait_overtime: 60, service_past_wait: false
use Myserver::MyserverBackend
run Myserver::App
Rack middleware "backend":
%w(faye/websocket thread redis json erb).each { |m| require m }
module Myserver
class MyserverBackend
KEEPALIVE_TIME = ENV['KEEPALIVE_TIME']
def initialize(app)
#app = app
#clients = []
#uri = URI.parse(ENV["REDISCLOUD_URL"])
#redis = Redis.new(host: #uri.host, port: #uri.port, password: #uri.password)
end
def call(env)
begin
if Faye::WebSocket.websocket?(env)
ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME})
ws.on :open do |event|
channel = URI.parse(event.target.url).path[1..URI.parse(event.target.url).path.length]
Thread.new do
redis_sub = Redis.new(host: #uri.host, port: #uri.port, password: #uri.password)
redis_sub.subscribe(channel) do |on|
on.message do |message_channel, message|
puts "MyserverBackend>> Redis message received on channel:#{message_channel}; Message is:#{message};"
#clients.each { |clients_ws, clients_channel| clients_ws.send(message) if clients_channel == message_channel }
end
end
end
#clients << [ws, channel]
#clients.each do |clients_ws, clients_channel|
puts "MyserverBackend>> Client:#{clients_ws.object_id}; Channel:#{clients_channel};"
end
end
ws.on :message do |event|
#clients.each do |clients_ws, clients_channel|
if clients_ws == ws
puts "MyserverBackend>> Websocket message received on channel:#{clients_channel}; Message is:#{event.data};"
#redis.publish(clients_channel, sanitize(event.data))
end
end
end
ws.on :close do |event|
# Close all channels for this client first
# ws gives a channel which we use to identify it here, but we're closing all of those that are open
#clients.each { |clients_ws, clients_channel| #redis.unsubscribe(clients_channel) if clients_ws == ws }
#clients.delete_if { |clients_ws, clients_channel| clients_ws == ws }
channel = URI.parse(event.target.url).path[1..URI.parse(event.target.url).path.length]
puts "MyserverBackend>> Websocket closure for:#{channel}; Event code:#{event.code} Event reason:#{event.reason};"
ws = nil
end
ws.on :error do |event|
puts "Error raised:#{nil}; ws:#{ws.object_id};"
ws.close unless ws.nil?
end
# Return async Rack response
ws.rack_response
else
#app.call(env)
end
rescue Rack::Timeout::RequestTimeoutError, Rack::Timeout::RequestExpiryError => exception
puts "Exception raised:#{exception}; ws:#{ws.object_id};"
ws.close(code=4999, reason=9999) unless ws.nil?
# ensure is executed immediately so it doesn't help...
end
end
private
def sanitize(message)
json = JSON.parse(message)
json.each { |key, value| json[key] = ERB::Util.html_escape(value) }
JSON.generate(json)
end
end
end
The Sinatra "frontend":
# https://github.com/heroku-examples/ruby-websockets-chat-demo
require 'rubygems'
require 'bundler'
require 'sinatra/base'
ENV['RACK_ENV'] ||= 'development'
Bundler.require
$: << File.expand_path('../', __FILE__)
$: << File.expand_path('../lib', __FILE__)
Dir["./lib/*.rb", "./lib/**/*.rb"].each { |file| require file }
env = ENV['OS'] == 'Windows_NT' ? 'development' : ENV['RACK_ENV']
module Myserver
class App < Sinatra::Base
get "/" do
erb :"index.html"
end
get "/assets/js/application.js" do
content_type :js
#scheme = env == "production" ? "wss://" : "ws://"
erb :"application.js"
end
end
end
The test client:
# https://github.com/faye/faye-websocket-ruby/issues/52
# https://github.com/faye/faye-websocket-ruby
%w(bundler/setup faye/websocket eventmachine json).each { |m| require m }
Dir["./lib/*.rb", "./lib/**/*.rb"].each { |file| require file }
class ClientWs
def self.em_run
env = ENV['OS'] == 'Windows_NT' ? 'development' : ENV['RACK_ENV']
EM.run do
uri = 'myserver.herokuapp.com'
#uri = 'localhost' if env == 'development'
channel = "C#{rand(999999999999).to_s}"
url = uri == 'localhost' ? "ws://#{uri}:3000/#{channel}" : "ws://#{uri}/#{channel}"
#ws = Faye::WebSocket::Client.new(url)
start = Time.now
count ||= 0
timer = EventMachine.add_periodic_timer(5+rand(5)) {
count += 1
send({'PING': channel, 'COUNT': count.to_s})
}
#ws.on :open do |event|
puts "{'OPEN':#{channel}}"
ClientWs.send({'OPEN': channel})
end
#ws.on :message do |event|
#ip_address ||= Addrinfo.ip(URI.parse(event.target.url).host).ip_address
begin
parsed = JSON.parse event.data
rescue => e
puts ">>>> [Error! Failed to parse JSON]"
puts ">>>> [#{e.message}]"
puts ">>>> #{event.data}"
end
puts ">> #{#ip_address}:#{channel}:#{event.data};"
end
#ws.on :close do |event|
timer.cancel
stop = Time.now - start
puts "#{stop} seconds;"
p [:close, event.code, event.reason]
ws = nil
ClientWs.em_run
end
end
end
def self.send message
payload = message.is_a?(Hash) ? message : {payload: message}
#ws.send(payload.to_json)
end
end
ClientWs.em_run
The Gemfile.lock:
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.5.1)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
eventmachine (1.2.0.1-x86-mingw32)
faye-websocket (0.10.4)
eventmachine (>= 0.12.0)
websocket-driver (>= 0.5.1)
i18n (0.7.0)
json (1.8.3)
json_pure (1.8.3)
minitest (5.9.0)
multi_json (1.12.1)
oj (2.16.1)
permessage_deflate (0.1.3)
progressbar (0.21.0)
puma (3.4.0)
rack (1.6.4)
rack-protection (1.5.3)
rack
rack-timeout (0.4.2)
rake (11.2.2)
redis (3.3.0)
rollbar (2.11.5)
multi_json
sinatra (1.4.7)
rack (~> 1.5)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
thread_safe (0.3.5)
tilt (2.0.5)
tzinfo (1.2.2)
thread_safe (~> 0.1)
websocket-driver (0.6.4)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
PLATFORMS
x86-mingw32
DEPENDENCIES
activesupport (= 4.2.5.1)
bundler
faye-websocket
json_pure
oj (~> 2.16.0)
permessage_deflate
progressbar
puma
rack
rack-timeout
rake
redis (>= 3.2.0)
rollbar
sinatra
RUBY VERSION
ruby 2.2.4p230
BUNDLED WITH
1.12.5
What client sees when attempting to connect to stalled server:
ruby client.rb
20.098119 seconds;
[:close, 1002, "Error during WebSocket handshake: Unexpected response code: 500"]
20.07921 seconds;
[:close, 1002, "Error during WebSocket handshake: Unexpected response code: 500"]
20.075731 seconds;
[:close, 1002, "Error during WebSocket handshake: Unexpected response code: 500"]
config/puma.rb:
env = ENV['OS'] == 'Windows_NT' ? 'development' : ENV['RACK_ENV']
if env.nil? || env == 'development' || env == 'test'
concurrency = 0 # Set to zero to ensure single mode, not clustered mode
max_threads = 1
end
# WEB_CONCURRENCY and RAILS_MAX_THREADS == 1 in Heroku for now.
concurrency ||= (ENV['WEB_CONCURRENCY'] || 2)
max_threads ||= (ENV['RAILS_MAX_THREADS'] || 5)
worker_timeout 15
workers Integer(concurrency)
threads_count = Integer(max_threads)
threads threads_count, threads_count
#preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
What I needed to do was complete the server's "on close" event. It needed to clean everything up and then restart itself, which it was not doing.
I don't like this as the final answer, however. The question would be, why is the server closing up shop, terminating and restarting just because a client dropped? Isn't there a cleaner way to sweep away the detritus of a failed client? Follow up: This fix does answer this particular question, in any case, in that completing onclose resolved the stated problem. Further enhancements threaded the client's WebSocket events in addition to the Redis events such that onclose only closes the client and not the server.
The new event is:
ws.on :close do |event|
if #debug
puts "MyserverBackend>> Close entered. Last error:#{$!.class}:#{$!.to_s};Module:#{$0};Line:#{$.};"
$#.each { |backtrace| puts backtrace }
exit
end
#clients.each do |clients_ws, clients_channel|
begin
#redis.unsubscribe(clients_channel)
rescue RuntimeError => exception
unless exception.to_s == "Can't unsubscribe if not subscribed."
raise
end
false
end
end
#clients.delete_if { |clients_ws, clients_channel| clients_ws == ws }
channel = URI.parse(event.target.url).path[1..URI.parse(event.target.url).path.length]
puts "MyserverBackend>> Websocket closure for:#{channel}; Event code:#{event.code} Event reason:#{event.reason};"
ws = nil
app = Myserver::App
myserver = MyserverBackend.new(app)
myserver
end

Run unit test with Ruby 2.0 and minitest 5.5 without Gemfile

I was learning Ruby by reading Programming Ruby and there is this example code:
require_relative 'count_frequency'
require_relative 'words_from_string'
require 'test/unit'
class TestWordsFromString < Test::Unit::TestCase
def test_empty_string
assert_equal([], words_from_string(''))
assert_equal [], words_from_string(' ')
end
def test_single_word
assert_equal ['cat'], words_from_string('cat')
assert_equal ['cat'], words_from_string(' cat ')
end
def test_many_words
assert_equal ['the', 'cat', 'sat', 'on', 'the', 'cat'], words_from_string('the cat sat on the mat')
end
def test_ignore_punctuation
assert_equal ['the', "cat's", 'mat'], words_from_string("the cat's mat")
end
end
When I tried to run it, an error occured:
MiniTest::Unit::TestCase is now Minitest::Test.
More detailed error message:
I'm using ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin14] and minitest (5.5.0, 5.4.3, 5.3.5, 4.3.2). I did some search and found that since minitest5.0, MiniTest::Unit::TestCase has changed to Minitest::Test. But I cannot do anything since it's in the source file of the gem. Some suggests that require minitest 4.** in Gemfile, but i'm just running a few scripts. There is no need for Gemfile I suppose. And I certainly don't want to uninstalling minitest5.**. So is there a way I could run this script with minitest5.5 and ruby 2.0?
The tests should still run. I have the same set up and even though I get that error, the tests are executed.
→ ruby --verbose etl_test.rb
MiniTest::Unit::TestCase is now Minitest::Test. From etl_test.rb:4:in `<main>'
Run options: --seed 61653
# Running:
....
Finished in 0.001316s, 3039.5137 runs/s, 3039.5137 assertions/s.
4 runs, 4 assertions, 0 failures, 0 errors, 0 skips
classyhacker:~/dev/github/exercism/ruby/etl
→ rbenv versions
system
1.9.3-p448
2.0.0-p451
2.1.0
2.1.1
2.1.2
* 2.1.3 (set by RBENV_VERSION environment variable)
jruby-1.7.8
classyhacker:~/dev/github/exercism/ruby/etl
→ gem list | grep minitest
minitest (5.5.1, 5.4.3, 4.7.5)
My test looks like
require 'minitest/autorun'
require_relative 'etl'
class TransformTest < MiniTest::Unit::TestCase
def test_transform_one_value
old = { 1 => ['A'] }
expected = { 'a' => 1 }
assert_equal expected, ETL.transform(old)
end
require minitest/autorun is also the suggested way in rubydoc http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest.html

Cannot rescue NameError

Can someone tell me what I am doing wrong here, please?
wtf.rb
require 'minitest/autorun'
class MyPlugin
def self.valid_plugin?(plugin_class)
begin
plugin_class.ancestors.include?(self)
rescue NameError
false
end
end
end
class MyPluginTest < Minitest::Test
def test_valid_plugin_handles_missing_constant
assert_equal false, MyPlugin.valid_plugin?(MyMissingConstant)
end
end
Environment
$ ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
$ gem list --local
*** LOCAL GEMS ***
bigdecimal (1.2.4)
bundler (1.7.3)
io-console (0.4.2)
json (1.8.1)
minitest (5.4.2, 4.7.5)
psych (2.0.5)
rake (10.1.0)
rdoc (4.1.0)
test-unit (2.1.2.0)
$ ruby wtf.rb
Run options: --seed 32486
# Running:
E
Finished in 0.001228s, 814.3322 runs/s, 0.0000 assertions/s.
1) Error:
MyPluginTest#test_valid_plugin_handles_missing_constant:
NameError: uninitialized constant MyPluginTest::MyMissingConstant
wtf.rb:15:in `test_valid_plugin_handles_missing_constant'
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
MyMissingConstant is evaluated before the valid_plugin? method is called. You have to either rescue at the call site, or pass a string and look up the constant within your method.
Kernel.const_get is probably the simplest way to do that. For more detail, look at question slike this one:
How to convert a string to a constant in Ruby?

Use test/unit with anonymous TestCase

This question belongs zu test-unit version 2.5.3
Problem solved with test-unit version 2.5.4
I have a test with many anonymous TestCases. It worked with test-unit 2.5.0, but the actual version 2.5.3 produces an error.
When I run this test:
gem 'test-unit', ">=2.5.2"
require 'test/unit'
Class.new( Test::Unit::TestCase ) do
def test_add
assert_equal( 2, 1+1)
end
end
no test is executed and I get the error undefined method sub' for nil:NilClass (NoMethodError) in testrunner.rb:361 (I use the actual test-unit-gem 2.5.3).
With a name for the TestCase, the problem disappears:
gem 'test-unit'
require 'test/unit'
X = Class.new( Test::Unit::TestCase ) do
def test_add
assert_equal( 2, 1+1)
end
end
In my real problem, I generate many TestCases. So I have a situation like:
gem 'test-unit'
require 'test/unit'
2.times {
X = Class.new( Test::Unit::TestCase ) do
def test_add
assert_equal( 2, 1+1)
end
end
}
If I execute this I get a warning already initialized constant X and the error:
comparison of Array with Array failed (ArgumentError) (in collector.rb:48:in sort_by').
My question(s):
How can I avoid the error?
Or: How can I create TestCases with dynamic assigned constants?
It seems this is down to a change in the latest version of the test-unit gem, which now requires a readable name for a class.
Something like this will work
gem 'test-unit', ">=2.5.2"
require 'test/unit'
Class.new( Test::Unit::TestCase ) do
def test_add
assert_equal( 2, 1+1)
end
def self.to_s
"GeneratedClass"
end
def self.name
to_s
end
end

Rspec2 issue with Rcov

In my Rakefile, I have a task defined like this:
namespace :test do
desc "Run all specs."
RSpec::Core::RakeTask.new(:spec) do |t|
t.pattern = 'spec/**/*_spec.rb'
t.verbose = false
end
RSpec::Core::RakeTask.new(:coverage) do |t|
t.rcov = true
t.rcov_opts = %q[--exclude "spec"]
t.verbose = true
end
end
When running test:coverage, I get this:
./spec/foo_spec.rb:3: undefined method `describe' for main:Object (NoMethodError)
from /Library/Ruby/Gems/1.8/gems/rcov-0.9.9/bin/rcov:516:in `load'
from /Library/Ruby/Gems/1.8/gems/rcov-0.9.9/bin/rcov:516
from /usr/bin/rcov:19:in `load'
from /usr/bin/rcov:19
rake aborted!
ruby -S rcov -Ispec:lib --exclude "spec" "./spec/foo_spec.rb" failed
Below my gem list:
diff-lcs (1.1.2)
rake (0.8.7)
rcov (0.9.9)
rspec (2.3.0)
rspec-core (2.3.1)
rspec-expectations (2.3.0)
rspec-mocks (2.3.0)
Any idea? Thanks in advance.
The solution, from David Chelimsky:
http://rubyforge.org/pipermail/rspec-users/2010-December/019077.html
require "rspec"
Cheers.

Resources