Authlogic with Capybara + Cucumber + Selenium Driver not working - ruby

This is the error I get when I run a cucumber test with #javascript with authlogic:
You must activate the Authlogic::Session::Base.controller with a controller object before creating objects
This is my authlogic support code in feature/support/authlogic.rb:
require "authlogic"
require "authlogic/test_case"
World(Authlogic::TestCase)
ApplicationController.skip_before_filter :activate_authlogic
Before do
activate_authlogic
end
This is how I created a session:
def create_session
Session.create(:name => "test", :password => "test-33")
end
Without #javascript, it will not give me the error about authlogic not being activated, but with #javascript it does. How do I fix this problem?

Selenium and capybara-webkit use separate threads when launching processes. When you run activate_authlogic it does the following
Authlogic::Session::Base.controller = (#request && Authlogic::TestCase::RailsRequestAdapter.new(#request)) || controller
This winds up setting a thread local variable for :authlogic_controller. The problem is that this gets lost when you start using new threads in scenarios tagged with #javascript.
For me, the fix was to monkeypatch authlogic code like so
module Authlogic
module Session
module Activation
module ClassMethods
def controller
if !Thread.current[:authlogic_controller]
Thread.current[:authlogic_controller] = Authlogic::TestCase::MockController.new
end
Thread.current[:authlogic_controller]
end
end
end
end
end
This replicates what is done in acivate_authlogic. Make sure you only patch your test environment.

Related

Sinatra does not start with twitter gem

when i try to start sinatra, i'm getting following error
/var/lib/gems/1.9.1/gems/sinatra-1.4.4/lib/sinatra/base.rb:1488:in start_server': undefined methodrun' for HTTP:Module (NoMethodError)
require 'sinatra/base'
require_relative "twt.rb"
class SinatraApp < Sinatra::Base
set :static, true
set :public_folder, File.dirname(__FILE__) + '/static'
get '/getuserinfo' do
#user = twit.getuserinfo
erb :userInfo
end
end
SinatraApp.run!
in "twt.rb" i require twitter (5.7.1)
require 'twitter'
class Twit
attr_accessor :client
def initialize(consumer_key,consumer_secret,access_token,access_token_secret)
#client = Twitter::REST::Client.new do |config|
config.consumer_key = consumer_key
config.consumer_secret = consumer_secret
config.access_token = access_token
config.access_token_secret = access_token_secret
end
end
def getUserInfo
return user = {
"name"=> client.current_user.name,
"id" => client.current_user.id
}
end
def showAllFriends
client.friends.each { |item| puts item.name }
end
def showFollowers
client.followers.each { |item| puts item.screen_name }
end
def showAllTweets
client.user_timeline.each {|item| puts item.text}
end
def showAllUserTweets(userScreenName)
client.user_timeline(userScreenName).each {|item| puts item.text}
end
def sendTweet(content)
client.update(content)
end
end
if i remove require_relative "twt.rb" line sinatra works fine.
When you run a Sinatra app using the built-in web server (as you do with SinatraApp.run!), Sinatra tries to determine which server to use by checking a list of servers in turn to see which is available. The actual list depends on the version of Ruby you are using, but one server that it always checks is net-http-server, which is simply named HTTP.
The way Sinatra checks for the availability of a server is by using a rack method that calls const_get to try and find the constant Rack::Handler::<server-name>. However, due to the way const_get works, if that constant is not available, but a top level constant with the same name as server-name is, then that will be returned, whatever class it is. (This is arguably a bug in Rack).
The Twitter gem depends on the http gem, and that in turn defines a HTTP module. (Naming a top-level module with something as generic as HTTP is arguably not a good idea).
So what is happening in this case is Sinatra is checking to see if the HTTP server is available, but Rack is returning the HTTP module from the http gem, which isn’t a server. Not being a Rack server it doesn’t have a run method, so when Sinatra tries to use it as one you get the error start_server': undefined method `run' for HTTP:Module.
One workaround is not to use the built-in server, such as the way you have discovered using a config.ru file and starting the app with rackup.
Another solution is to explicitly specify the server to use in your Sinatra app. For example you could install Thin, and then use:
set :server, 'thin'
In fact simply installing Thin would be sufficient as Thin is searched for before HTTP, but you are probably better explicitly setting the server to use. If you cannot install any other server for any reason you could use Webrick instead:
set :server, 'webrick'
i found the solution.
i launch sinatra with config.ru and it works now.
rack config.ru

simpler way to test my simple Rack app?

i have a Rack app like this:
app = Rack::Builder.new do
map '/' do
# ...
end
map '/edit' do
# ...
end
end.to_app
How would i test it without long-tail installation/setup/learn process.
RSpec and minitest are really great, but i do not really want to learn nor setup them.
Is there something i cat just plug in and write/run tests right away in plain Ruby?
I want to write tests as simple as i wrote the app above, without advanced techniques and gotchas.
In KISS I Trust!
you can try Specular + Sonar bundle.
Specular is for writing tests anywhere you need them.
Sonar is a mock "browser" that communicate to your app, just like rack-test does, but with some unique features and simpler workflow.
Using them is as simple as:
...
app.to_app
Spec.new do
include Sonar
app(app)
get
check(last_response.status) == 200
# etc...
end
puts Specular.run
so you put your specs right beside your app and write tests quickly in plain Ruby, without having to learn anything.
see the full example running at CIBox
(if it does not run automatically, click Run button)
PS: writing Rack apps this way is kinda a pain.
You can try a mapper, like Appetite one.
so your app may look like this:
class App < Appetite
map :/
def index
'index'
end
def edit
'edit'
end
end
see the same example but with app built by Appetite here
Simplest? Use Rack::Test with Test::Unit. gem install rack-test and run with ruby filename.rb
require "test/unit"
require "rack/test"
class AppTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
Rack::Builder.new do
map '/' do
run Proc.new {|env| [200, {'Content-Type' => 'text/html'}, "foo"] }
end
map '/edit' do
# ...
end
end.to_app
end
def test_index
get "/"
assert last_response.ok?
end
end
Update: RSpec style requested - gem install rspec; run with rspec filename.rb
require 'rspec'
require 'rack/test'
describe 'the app' do
include Rack::Test::Methods
def app
Rack::Builder.new do
map '/' do
run Proc.new {|env| [200, {'Content-Type' => 'text/html'}, "foo"] }
end
map '/edit' do
# ...
end
end.to_app
end
it 'says foo' do
get '/'
last_response.should be_ok
last_response.body.should == 'foo'
end
end
You could use rack-test but that again entails using minitest/unit test but is the most common way testing Rack apps.

Trouble w/ Rubymine and unit tests

DISCLAIMER: I am very new to ruby, still trying to get my feet wet, so this could be hugely stupid issue.
I'm trying to get a very simple project and one unit test working, and the Universe is throwing a LifeException (I just can't figure this out)
Using Rubymine 4.0.1 on Mac OS X, 10.7.3.
Launched RubyMine and created a new project (not Rails) "TestExample"
Created a new Ruby Class, file is my_class.rb.
class MyClass
def say_hi
puts "Hi!"
end
end
my = MyClass.new
my.say_hi
Create a new TestUnit Test Template, file is "my_test.rb"
require "test/unit"
class MyTest < Test::Unit::TestCase
def test_create
#my = MyClass.new
end
end
At this point I have two issues:
1. How do I 'require' my class in my tests? If I change the above test case to:
require "test/unit"
require "my_class"
class MyTest < Test::Unit::TestCase
def test_create
#my = MyClass.new
end
end
and attempt to run my "All tests in: TestExample" configuration, I get a "Exception message: cannot load such a file -- my_class". The Tests folder and working directory are pointed to the location of the files. (every file is in the same folder)
The other is a "Unable to attach test reporter to test framework".
I've googled and attempted to figure this out to no avail. I realize this is two questions in one, and if I could just get tests working, I'd be happy.
Thanks for any input and don't laugh to hard at my uber-ruby-noobness.
[Update] - This only happens when using the RVM: ruby-1-9.3-p125 SDK. If I use the ruby-1.8.7-p249(/usr/bin/ruby), it does work. This has to be some configuration issue.
For the first question, try:
require_relative 'my_class'
I can't answer the second.

Mocha Mock Carries To Another Test

I have been following the 15 TDD steps to create a Rails application guide - but have run into an issue I cannot seem to resolve. For the functional test of the WordsController, I have the following code:
class WordsControllerTest < ActionController::TestCase
test "should get learn" do
get 'learn'
assert_response :success
end
test "learn passes a random word" do
some_word = Word.new
Word.expects(:random).returns(some_word)
get 'learn'
assert_equal some_word, assigns('word')
end
end
In the Word class I have the following code:
class Word < ActiveRecord::Base
def self.random
all = Word.find :all
all[rand(all.size)]
end
end
When I run the tests, I experience the following error (shortened for brevity):
1) Failure: unexpected invocation: Word(...).random() satisfied expectations:
- expected exactly once, already invoked once: Word(...).random()
I have tried changing changing the order of the tests along with a multitude of other things, but time and time again I continue to receive the same test failure - that Word.random() has already been invoked.
I'm running Rails 3.0 beta 4 and Mocha 0.9.8. I've searched long and hard for a solution to my problem, but I can't seem to find it. I'm new to Ruby/Rails so am rather unfamiliar with the language and the frameworks.
Thanks in advance!
mocha needs to be loaded last. I struggled a lot with this problem too.
#Gemfile
group :test
gem 'mocha', '~>0.9.8', :require => false
...
end
and
test_helper.rb
....
#at the very bottom
require 'mocha'
I had the same problem, mocked functionality was not isolated to a test, it seems to be a problem with the load order of Mocha.
I had some issues getting Mocha to work with Rails3. I found a few stackoverflow posts regarding, but didn't stumble across the solution until I found a post on agoragames.com
Basically, in the Gemfile of your project, the require for Mocha should look like:
gem 'mocha', :require => false
Then in test/test_helper.rb, add a require line for mocha:
...
...
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'mocha'
class ActiveSupport::TestCase
...
...
I think the require line for mocha in the Gemfile means that you need to already have mocha installed as a gem, bundler won't take care of it for you.
How are you requiring mocha? Are you using bundler? It sounds a bit as if the mocha teardown hook isn't being called?
Additionally, it seems mocha_teardown is not being called with rails31. Mocks that are setup are never removed... (this additional hack fixes it)
class ActiveSupport::TestCase
def teardown
super
Mocha::Mockery.instance.teardown
Mocha::Mockery.reset_instance
end
end
Those solutions didn't work for me on their own, using Ruby 2.2.2, Rails 4.2.2, mocha 1.1.0, shoulda-context 1.2.1, factory_girl_rails 4.5.0 and a few more testing related gems.
What did it was also moving these two lines at the bottom of my test_helper.rb:
require 'mocha/setup'
require 'mocha/test_unit'
I also removed require 'test/unit'. It appears that mocha/test_unit already does that for me.

Testing a rake task in rspec (and cucumber)

I'm new to Ruby, and I've been trying to learn Rake, RSpec, and Cucumber. I found some code that will help me test my Rake tasks, but I'm having trouble getting it to work. I was told here: http://blog.codahale.com/2007/12/20/rake-vs-rspec-fight/ to drop this:
def describe_rake_task(task_name, filename, &block)
require "rake"
describe "Rake task #{task_name}" do
attr_reader :task
before(:all) do
#rake = Rake::Application.new
Rake.application = #rake
load filename
#task = Rake::Task[task_name]
end
after(:all) do
Rake.application = nil
end
def invoke!
for action in task.instance_eval { #actions }
instance_eval(&action)
end
end
instance_eval(&block)
end
end
into my spec_helper.rb file.
I've managed to take this code out and run it in my cucumber steps like this:
When /^I run the update_installers task$/ do
#rake = Rake::Application.new
Rake.application = #rake
load "lib/tasks/rakefile.rb"
#task = Rake::Task["update_installers"]
for action in #task.instance_eval { #actions }
instance_eval(&action)
end
instance_eval(&block)
Rake.application = nil
end
but when I try to get things working in rspec, I get the following error.
ArgumentError in 'Rake task
install_grapevine should install to
the mygrapevine directory'
wrong number of arguments (1 for 2)
/spec/spec_helper.rb: 21:in instance_eval'
/spec/spec_helper.rb: 21:inblock in invoke!'
/spec/spec_helper.rb: 20:in each'
/spec/spec_helper.rb: 20:ininvoke!'
/spec/tasks/rakefile_spec.rb:12:in `block (2 levels) in
'
Unfortunately, I've got just under a week of ruby under by belt, so the metaprogramming stuff is over my head. Could anyone point me in the right direction?
This works for me: (Rails3/ Ruby 1.9.2)
When /^the system does it's automated tasks$/ do
require "rake"
#rake = Rake::Application.new
Rake.application = #rake
Rake.application.rake_require "tasks/cron"
Rake::Task.define_task(:environment)
#rake['cron'].invoke
end
Substitute your rake task name here and also note that your require may be "lib/tasks/cron" if you don't have the lib folder in your load path.
I agree that you should only do minimal work in the Rake task and push the rest to models for ease of testing. That being said I think it's important to ensure that the code is ACTUALLY run in my cron tasks during my integration tests so I think very mild testing of the rake tasks is justified.
Since testing rake is just too much for me, I tend to move this problem around. Whenever I find myself with a long rake task that I want to test, I create a module/class in lib/ and move all the code from the task there. This leaves the task to a single line of Ruby code, that delegates to something more testable (class, module, you name it). The only thing that remains untested is whether the rake task invokes the right line of code (and passes the right parameters), but I think that is OK.
It might be useful to tell us which is the 21nd line of your spec_helper.rb. But given that the approach you posted digs deep in rake (referring to its instance variables), I would entirely abandon it for what I suggested in the previous paragraph.
I've just spent a little while getting cucumber to run a rake task so I thought I'd share my approach. Note: This is using Ruby 2.0.0 and Rake 10.0.4, but I don't think the behaviour has changed since previous versions.
There are two parts to this. The first is easy: with a properly set up instance of Rake::Application then we can access tasks on it by calling #[] (eg rake['data:import']). Once we have a task we can run it by calling #invoke and passing in the arguments (eg rake['data:import'].invoke('path/to/my/file.csv').
The second part is more awkward: properly setting up an instance of Rake::Application to work with. Once we've done require 'rake' we have access to the Rake module. It already has an application instance, available from Rake.application, but it's not yet set up — it doesn't know about any of our rake tasks. It does, however, know where to find our Rakefile, assuming we've used one of the standard file names: rakefile, Rakefile, rakefile.rb or Rakefile.rb.
To load the rakefile we just need to call #load_rakefile on the application, but before we can do that we need to call #handle_options. The call to #handle_options populates options.rakelib with a default value. If options.rakelib is not set then the #load_rakefile method will blow up, as it expects options.rakelib to be enumerable.
Here's the helper I've ended up with:
module RakeHelper
def run_rake_task(task_name, *args)
rake_application[task_name].invoke(*args)
end
def rake_application
require 'rake'
#rake_application ||= Rake.application.tap do |app|
app.handle_options
app.load_rakefile
end
end
end
World(RakeHelper)
Pop that code into a file in features/support/ and then just use run_rake_task in your steps, eg:
When /^I import data from a CSV$/ do
run_rake_task 'data:import', 'path/to/my/file.csv'
end
The behavior might have changed since the correct answer was posted. I was experiencing problems executing two scenarios that needed to run the same rake task (only one was being executed despite me using .execute instead of .invoke). I thought to share my approach to solve the issue (Rails 4.2.5 and Ruby 2.3.0).
I tagged all the scenarios that require rake with #rake and I defined a hook to setup rake only once.
# hooks.rb
Before('#rake') do |scenario|
unless $rake
require 'rake'
Rake.application.rake_require "tasks/daily_digest"
# and require other tasks
Rake::Task.define_task(:environment)
$rake = Rake::Task
end
end
(Using a global variable is suggested here: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)
In the step definition I simply called $rake
# step definition
Then(/^the daily digest task is run$/) do
$rake['collector:daily_digest'].execute
end
Any feedback is welcome.

Resources