Debugging controller methods by running functional tests - ruby-on-rails-3.1

I am in a situation where I need to step through the controller method when I run a functional test. I use ruby-debug to debug through my application. My app is a rails 3.1 app which uses ruby-1.8.7 . I can debug my code by using
rails server --debugger OR
rails console --debugger
I can also stop the code by inserting "debugger" in a model and run it's respective unit test.
But I am not able to do the same thing with the controllers. That is I am not able to stop the code by inserting "debugger" in the methods of the controller and run it's respective functional test.
Has anyone faced this issue before?
Also I use devise for authentication so I need to add the following lines to my test_helper
class ActionController::TestCase
include Devise::TestHelpers
def login_user
#request.env["devise.mapping"] = Devise.mappings[:user]
#user.confirm!
sign_in #user
end
end
Not sure I that is going to effect the debugger in anyway.

I was unable to stop at a debugger inserted in my controller method when I ran the functional tests because I was hitting a before_filter

Related

Launch sinatra from a test/spec or another ruby script

I'm experimenting, and I'm trying to launch dummy Sinatra application from RSpec and kill it when the spec is finished. Something like:
# spec/some_spec.rb
before(:all)
# launch sinatra dummy app
end
after (:all)
# kill sinatra dummy app
end
it 'should return list of whatever' do
expect(JSON.parse(make_request('0.0.0.0:4567/test.json')))
.to include('whatever')
end
I could use system("ruby test/dummy/dummy_app.rb"), but how can I kill that process only? Does anyone know how I can launch the Sinatra inside a test (or from another ruby script)? I know about WebMocks, but I want to see if I can manage to make my test work this way.
Look under RSpec on "Testing Sinatra with Rack::Test". I'd suggest you use that code as boilerplate to get started.
Just add this to your describe block:
def app
Sinatra::Application
end
I would suggest you read up RSpec.
Since you want to test an external system, by the looks of your comment, instead of system "curl whatewer.com", you can use Net::HTTP to make requests and then test against the response.
Have a look at "Testing an external API using RSpec's request specs".
As I'm writing request specs to ensure the features won't be broken I decided to rather write separate Cucumber features. The nice thing is that I can use Capybara, and thanks to Selenium Web Drive, I can launch a server before I run my tests.
So, I created a dummy Sinatra application (that will represent the external service to which the actual code I'm testing is doing requests (including a nasty system('curl whatever.com')).
All I have to do is stub out the methods passed to curl to use Capybara.current_session.server.host and Capybara.current_session.server.port.
Once I'm done with my re-factoring all I have to do is remove the Capybara server variables, and Selenium web drive from the cucumber/capybara configuration.
Tests after a brief change will be still working and will be valid.
Update
In the end I wrote it all with RSpec request tests, as doing it in Cucumber was little bit time consuming and I already spend too much time on this.
I mark these kind of request tests with RSpec tag and Before I lunch these I manually lunch simple Sinatra/Grape dummy API application to which the request are made. (Then I run RSpec tests with this tag)
So basically I end up with specs for functionality that uses net/http that uses WebMock and don't need a server, and request tests for which I need to run the server before I run the specs. So the original question remains, how to lunch a server before tests start
After I cover all the functionality I'm gonig to rewrite the curl to net/http however I'm going to keep those requests specs as I discovered they are nice idea when it comes to crazy API scenarios (like testing https + diggested authentication)

Sinatra settings returning strange result

I have a very simple Sinatra application:
require 'sinatra'
get '/' do
settings.inspect
end
And when I go to the root path I get: Sinatra::Application which is not at all what I expected. The application also doesn't respond well when I call the development? method (NoMethodError). I get the feeling this is because of my environment. I'm running Sinatra 1.4.4 with Ruby 1.9.3 on Windows 8. Any ideas on how to figure this out?
This is right, it’s just the way Sinatra works.
The settings instance method calls the class method (with self.class.settings) and the class method simply returns self, which is Sinatra::Application in the case of classic apps, and whatever your app class is in the case of modular apps.
When you add a setting in Sinatra with set, a new method is created on the app class for it, rather than there being a separate settings object. There is no way, as far as I know, to iterate over just the settings of your app.

Testing a ruby class without the required module files

I'm working on a project in Ruby on Rails. We have a controller action that uses a module within a gem. This gem isn't finished yet and it isn't on the file system.
I was told to mock the module in order to test the controller. Is there a way to test this without the actual gem? Would mocking the 'require' calls work?
We are currently using Mocha for Mocking and Stubbing.
There is a way to mock the imports in python. Maybe there is a similar answer to mocking the requires in ruby.
How to mock an import
Or please let me know what would be the best way to handle this.
Update: The person who told me to mock it, suggested adding a stub file, but that would require adding test code to the controller and I don't want to do that.
Update 2: The controller uses methods declared in the Module.
If you are writing tests to mock the method calls, they would fail. For example,
controller.should_receive(:method_in_non_existent_module).with(args) #=> errors
In a correct Red->Green TDD scenario , this is alright because the next step would be to require the gem/file, include the module and add the method call in the controller and make the test pass. But you'll not be able to make the tests pass since you can't require the file because it doesn't exist yet.
May be the developer who asked you to mock the method meant to do so not in your tests, but in your actual code. For example, he's writing a gem 'dongle-jokes' which has a method that gets the most popular dongle joke from the most recent tech conference. He doesn't want the gem to be a blocker for you to finish the controller and the views so he asks you to use a dummy interface that spits out a dummy response.
Write the tests that fail
Add a file lib/dongle-jokes.rb
Add the following to that file.
module DongleJokes
def joke
"Dongle jokes aren't funny!"
end
end
Require the file and include the module, use the method in the controller.
The test should pass now. You can remove lib/dongle-jokes.rb when you start using the actual gem.
If you're working in Rails you shouldn't need to add a require to the controller anyway, as when you add the gem to your gemfile it will be required automatically on Rails startup.
What your colleague most likely meant was that you should stub the module itself. Are you using rspec for your tests? If so you should be able to use stub_const. Let's say the module is called Payments. You can then write test code like the following:
before do
stub_const("Payments", stub)
Payments.stub(process: "payments successful")
end

Minitest #setup and #teardown not called when test run via Rake

I have a MiniTest suite. I'm using the basic Minitest::Unit::TestCase, not specs. I have setup and teardown methods defined in my TestCase subclass. They work perfectly when I run a test file like so: ruby test/whatever_test.rb. But when I run rake test, setup and teardown are not called. The relevant portion of my Rakefile is:
require 'rake/testtask'
Rake::TestTask.new do |t|
t.test_files = FileList['test/*_test.rb']
t.verbose = true
end
Why wouldn't the setup and teardown be run when Rake::TestTask is used?
I'd paste the test case code into here, but there's quite a lot of it. I'll certainly paste in some subset of it, if there's a particular section you'd like to see.
I'm running Minitest 4.3.2 on Ruby 1.9.3-p194.
The problem was that another test case was overwriting the setup and teardown methods. I had accidentally given two test cases the same class name, which is why the overwriting happened. Naturally, this error didn't happen when I ran a single test case, which explains the difference in behavior when using Rake.
In my case, I was writing tests for socket communication and had added a helper method named send. Since MiniTest uses send internally to call the teardown methods, it was instead calling my own send instead of the method-dispatch.

Stubbing Sinatra helper in Cucumber

I am currently struggling with stubbing out a helper method of my Sinatra app from within Cucumber.
I have a Sinatra app with simple session authentication (by cookies) and I want to turn of authentication by stubbing out the logged_in? helper method for my Cucumber scenarios.
There seems to be a problem with Sinatra and Cucumber concerning sessions so I thought about just using Mocha to work around the problem.
However I don't know how I can access the Sinatra::Application instance from within a Given-Block to stub out the method.
It seems like I need to directly override my Authentication mechanism within a Before do ... end-block
So I ended up with a hooks.rb placed in features/support/ file overwriting my logged_in? and the current_user method.
Before do
MySinatraApplicationClass.class_eval do
helpers do
def logged_in?
return true
end
def current_user
# This returns a certain Username usually stored
# in the session, returning it like
# that prohibits different user logins, but for
# now this is enough for me
"Walter"
end
end
end
end
The only thing I had to take care of, is that the no other actions within the application directly read from session but rather use those helpers.
Sadly I think this way of handling session based Sinatra applications through Cucumber is already described somewhere else and I just thought my problem was different.
You can get the right context by using Sinatra::Application.class_eval
Edit: See original poster's answer for full explanation.

Resources