How to start/stop sinatra app in cucumber hook - ruby

PROBLEM SOLVED:
I've figured out how to solve my problem:
in the before hook I fork the current process to start my sinatra web app:
Before do
if $pid.nil?
$pid = fork do
App.run!
end
end
end
Notice I have to have the forked PID attributed to a global variable so it doesnt get flushed after each scenario in cucumber. Besides that, I make sure to start my sintra app once in the entire cucumber execution.
Then at the end of my cucumber execution, I kill the child process and wait for it to be cleared prior to terminating the cucumber session:
at_exit do
unless $pid.nil?
Process.kill "TERM", $pid
Process.wait $pid
end
end
ORIGINAL QUESTION:
I am looking to stub a web app which contain content that will then be used by my application to fetch that content from that stub and do its trick...
What I am looking to achieve is start Sinatra app within cucumber hook... then stop it at end of execution... is that possible?
Below is where I've got so far...
#myapp.rb
require 'sinatra'
class App < Sinatra::Base
set :server, 'webrick'
get '/' do
'Hello!!!'
end
end
Then in hook:
Before do
App.run!
end
The first issue there is that the sinatra app won't run in the background... after solving that problem then I would need to understand if it's easy enough to stop the sinatra session as well...

Related

Capybara doesn't close browser when Net::ReadTimeout error happens

I am running tests for a Rails app with Capybara, Cucumber and Selenium Webdriver (Ruby). I have a question: why Capybara doesn't close browser when Net::ReadTimeout happens even I had a hook which asked browser to quit after each test scenario? How can I force it to close the browser when Net::ReadTimeout occurs?
This is my hooks.rb
after do |scenario|
if scenario.failed?
page.driver.browser.save_screenshot("#{scenario.__id__}.png")
end
Capybara.current_session.driver.browser.manage.delete_all_cookies
Capybara.current_session.driver.quit
end
I have another solution that works for me.
add gem capybara-screenshot
configure your spec_helper.rb in such way:
Capybara::Screenshot.autosave_on_failure = true
Capybara::Screenshot.prune_strategy = :keep_last_run
Capybara.default_wait_time = 60

How to use same browser window for automated test using selenium-webdriver (ruby)?

I am automating test cases for a website using selenium-webdriver and cucumber in ruby. I need each feature to run in a particular order and using the same browser window. Atm each feature creates a new window to run test in. Though in some test cases this behavior is desired- in many cases it is not. From my research so far it seems there are mixed answers about whether or not it is possible to drive the same browser window with selenium throughout test cases. Most answers I have run into were for other languages and were work arounds specific to a browser (I am developing my test while testing IE but will be expected to run these test in other browsers). I am working in Ruby and from what I have read it seems as though I'd have to make a class for the page? I'm confused as to why I would have to do this or how that helps.
my env.rb file:
require 'selenium-webdriver'
require 'rubygems'
require 'nokogiri'
require 'rspec/expectations'
Before do
#driver ||= Selenium::WebDriver.for :ie
#accept_next_alert = true
#driver.manage.timeouts.implicit_wait = 30
#driver.manage.timeouts.script_timeout = 30
#verification_errors = []
end
After do
##driver.quit
##verification_errors.should == []
end
Some information I've gathered so far of people with similar problems:
https://code.google.com/p/selenium/issues/detail?id=18
Is there any way to attach an already running browser to selenium webdriver in java?
Please ask me questions if anything about my question is not clear. I have many more test to create but I do not want to move on creating test if my foundation is sloppy and missing requested capabilities. (If you notice any other issues within my code please point them out in a comment)
The Before hook is run before each scenario. This is why a new browser is opened each time.
Do the following instead (in the env.rb):
require "selenium-webdriver"
driver = Selenium::WebDriver.for :ie
accept_next_alert = true
driver.manage.timeouts.implicit_wait = 30
driver.manage.timeouts.script_timeout = 30
verification_errors = []
Before do
#driver = driver
end
at_exit do
driver.close
end
In this case, a browser will be opened at the start (before any tests). Then each test will grab that browser and continue using it.
Note: While it is usually okay to re-use the browser across tests. You should be careful about tests that need to be run in a specific order (ie become dependent). Dependent tests can be hard to debug and maintain.
I had a similar problem in creating a spec_helper file. I did the following (simplified for locally-run firefox) for my purposes and it works very, very reliably. RSpec will use the same browser window for all it blocks in your _spec.rb file.
Rspec.configure do |config|
config.before(:all) do
#driver = Selenium::WebDriver.for :firefox
end
config.after(:all) do
#driver.quit
end
end
If you switch to :each instead of :all, you can use a separate browser instance for each assertion block... again, with :each RSpec will give a new browser instance for each it. Both are useful depending on the circumstance.
As the answers solve the problem but do not answer the question "How to connect to an existing session".
I managed to do this with the following code since it is not officially supported.
# monkey-patch 2 methods
module Selenium
module WebDriver
class Driver
# Be able to set the driver
def set_bridge_to(b)
#bridge = b
end
# bridge is a private method, simply create a public version
def public_bridge
#bridge
end
end
end
end
caps = Selenium::WebDriver::Remote::Capabilities.send("chrome")
driver = Selenium::WebDriver.for(
:remote,
url: "http://chrome:4444/wd/hub",
desired_capabilities: caps
)
used_bridge = driver.bridge
driver.get('https://www.google.com')
# opens a new unused chrome window
driver2 = Selenium::WebDriver.for(
:remote,
url: "http://chrome:4444/wd/hub",
desired_capabilities: caps
)
driver2.close() # close unused chrome window
driver2.set_bridge_to(used_bridge)
driver2.title # => "Google"
Sadly this did not test work between 2 rescue jobs, will update this in the future when I made it work for my own use case.

Delayed Job passenger production undefined method error

I am using delayed job version 2.1.4 with action mailer 3.0.8 to send my emails in background.
UserMailer.delay.newsletter(email)
It works with me fine in development and production Rails console.
But when it is called from my live production passenger server, it creates DJ but when this DJ runs, it throws
{undefined method `newsletter' for #<Class:0xc08afa0>
I think the problem
Any help?
The problem is with rails/passenger in production mode with class methods
So, I made a work around solution... I will try to call instance method and avoid to call class method.
Lets see an example; assuming I need to call the following method in background..
UserMailer.deliver_newsletter(email)
Then, I created a new class DelayClassMethod
class DelayClassMethod
def initialize(receiver_name, method_name, options={})
#receiver_name = receiver_name
#method_name = method_name
#parameters = options[:params] || []
end
def perform
eval(#receiver_name).send(#method_name, *#parameters)
end
end
and can run the method in background now by
DelayClassMethod.new("UserMailer", "deliver_newsletter", :params=>[email]).delay
So, I am running an instance method now in background which will run the class method.
Another example..
Assume I want to run
Product.list_all_by_user_and_category(user, category).delay
Then it can be run by
DelayClassMethod.new("Product", "list_all_by_user_and_category", :params => [user, category]).delay
My hunch is that you have multiple versions of the delayed_job in production. Are you using bundler to start your delayed job process?
I would recommend when doing bundle install in production, I would use the --binstubs flag to generate a wrapper around the delayed_job and use that executable to start the jobs.

QtRuby with DRb or EventMachine

I would like to write an application in Ruby using Qt which will communicate over the network with other instances.
How can I integrate Qt's event loop with DRb or EventMachine?
EDIT:
I found the answer when I will have more time I will post it
require 'eventmachine'
require 'Qt4'
app = Qt::Application.new(ARGV)
hello_button = Qt::PushButton.new("Hello EventMachine")
hello_button.resize(100,20)
hello_button.show
EventMachine.run do
EM.add_periodic_timer(0.01) do
app.process_events
end
end

How to debug/test email transfers in Sinatra/Ruby

Im using Pony to send email withing my sinatra applications. But the problem - i cant figure out how to debug or test it. Lest say, in php you can configure sendmail fake app (in php.ini) that will store all outgoing email as plain textfiles with all data in it.
How about ruby apps? Is it possible?
You surely found the solution already yourself
In the pony.rb file there is this code part which sends the mail:
def self.transport(tmail)
..
end
You can simply add a method to return the env:
def debug?
true #false
end
and do something special if debug mode is on
def self.transport(tmail)
puts "Debug message" if debug?
if File.executable? sendmail_binary
transport_via_sendmail(tmail)
else
transport_via_smtp(tmail)
end
end

Resources