possible to debug/pry from methadone's App class? - ruby-on-rails

I started a blank project with methadone, an awesome framework for building command line apps. The only problem is that I am unable to debug from within the App class that's in bin/my_app
The App class is a file created when you run methadone. Here's how I'm trying to use pry
#!/usr/bin/env ruby
require 'optparse'
require 'methadone'
require 'my_app'
require 'pry'
class App
include Methadone::Main
include Methadone::CLILogging
main do
binding.pry # <= pry here
end
...
When I run rake features I can tell the running process is trying to do something with pry since it pauses for a few seconds. I get the following error and then rake/cucumber is aborted.
process still alive after 3 seconds (ChildProcess::TimeoutError)
I can use pry just fine from the cucumber steps, rspec, or any other place, just not from anywhere in this App class.
One very interesting thing is that if I run my command line app from the console it WILL stop where pry is. It just wont pop into pry when using cucumber.
How can I get the app to work with pry when I'm running rake features?
Update
Sorry, I should clarify that methadone comes with aruba. So my cucumber scenario would look like this
When I successfully run `my_app arg1`
However, it WILL go into debug/pry if I run it with
bundle exec bin/my_app

Use pry-remote to connect to a pry session in the Aruba-managed subprocess.
(Disclosure: I paired with #Dty to come to this solution)

Aruba runs the app in a totally separate process, so I would guess what's happening is that when aruba runs your app, pry starts up at a prompt and waits for input. Since it doesn't get any, aruba times out after three seconds (the default it will wait for an app to complete). This is why you see the "process still alive" issue.
I'm not 100% sure how you could get the standard input of your shell that's running rake features to connect to your app's standard input so you could issue pry commands, but I don't think aruba was designed to allow this.
You have a couple of options:
Tag your scenario with #announce, and use When I run interactively... followed by several When I type - these commands should go to the interactive pry console that's waiting. Kind of kludgy, but it might work
Execute a unit test of your App class. You'll need to replace the call to go! with something like go! if $0 == __FILE__ so that you can require your executable in a test and manipulate App directly.
I have not tried either of these, but the second option feels a bit better and could also be improved with support from the library, if you can figure out a good way to do this.

Related

Rails and Selenium: how to stop/pause execution of a test in the browser?

I'm having a hard (but very interesting time) diving into Behavior Driven Development using Cucumber, RSpec, Selenium, and Rails.
I have my setup ready for testing with Selenium, and it's funny to watch Firefox pop up and run automatically through my scenarios. But one thing I'd like to do is pause or stop execution at a certain point, so I can inspect what Selenium sees at a certain point.
I know of the save_and_open_page command, but this only shows me plain HTML without formatting. So maybe there is a stop_execution method or something that stops Selenium without closing the browser?
Install pry, then put binding.pry in your test where you want it to pause. When you're done, press Ctrl+D or type exit in the REPL that gets opened to continue execution.
or just:
visit '/'
sleep(inspection_time=5)
visit '/dreamland'
All the answers need installing new gems or even setting a sleep which is not the best approach. You can put this line anywhere in you step:
ask "Continue?"
It will stop execution until you enter y (Yes)
So, for example it would look like this:
expect(page).to have_button('Submit')
ask "Continue?"
click_button('Submit')
Use Debugger where you want to stop/pause the execution.
or
In Selenium IDE you can right click on the commands line and you can select Set/Clear Start point to stop/pause the execution.
Okay, I got it working by installing ruby-debug19 (for Ruby 1.9.3), and then just setting a breakpoint somewhere in a Cucumber step.
http://rails.vandenabeele.com/blog/2011/12/21/installing-ruby-debug19-with-ruby-1-dot-9-3-on-rvm/
Another option is to use the Capybara-firebug gem which adds a "Then stop and let me debug" step which basically seems to do the same (I don't know whether it relies on the ruby-debug gems).
try to use selenium.sleep(ms)
this will make the test execution wait for the specified amount of time
You can use do this without installing any gems in rails 5 or above by using byebug. Just type byebug on the line that you want the test to pause at.
Example:
visit post_url(id: posts(:one).id)
byebug
click_on "...", match: :first
Doing this will pause the test after the new page loads but before the next button is clicked. If using an older version of rails you may have to install the byebug gem but it is useful for troubleshooting and I recommend using it regardless.

Running selenium/watir inside the context of the rails server

How can I run a watir test in the context of the app that's being tested? I'd like my test to browse the app and then access ActionMailer::Base.deliveries for emails or check models directly. This is how I understand what's being described here.
UPDATE: They probably use Capybara to be able to acces the email array and be in the context of the "server" which is instantiated just for the test.
I suggest checking out the Rails unit testing docs, then writing a simple Rails test case that starts your app - then try adding a line or two of Watir code to access your app:
http://guides.rubyonrails.org/testing.html
As far as I know you should be able to write a Rails unit test, then put Watir code inside one of your test methods - and if all goes well you should be able to instantiate your web app, use Watir to launch a browser to test it, and in the same method(s) perform non-Watir low-level testing (e.g. checking models/data/etc.)
I've never used Watir inside a Rails test, but I don't see why it wouldn't work.
Watir is about driving browsers to automate functional testing. You could I suppose use it for unit testing of the top level UI stuff, but more often in a 'unit test' context that would be done using a headless browser emulation, Capybara, celerity, or watir-webdriver using the headless option, purely for speed of operation since driving an actual browser can be slow even with a fast browser like chrome.
Most of the times people use Watir it's for more functional tests, often from a test runner framework like Cucumber, sometimes Rspec depending on your needs. You might combine that with other ruby code to access or create test data, to validate something made it into the DB from the UI, but everything in the Watir gem is all about the browser and interacting with it much like a human would, and driving the browser is it's function within the set of tools you might use.
I had the same need and found the following solution: https://stackoverflow.com/a/9687562/90741. I reproduce it here, as the linked question seems to be dead, with its owner...
I had the same need (Watir+RSpec), but the problem is: there is no Rack stack running by default during tests...
I found this solution:
In spec_helper.rb:
HTTP_PORT = 4000
test_instance_pid = fork do
exec 'unicorn_rails -E test -p %d' % HTTP_PORT
end
at_exit do
Process.kill "INT", test_instance_pid
Process.wait
end
Which start the test stack once for all spec tests, and kill it at the end. (In this sample, I am using unicorn, but we can imagine using any other server)
In the spec, I reuse the HTTP_PORT constant to build URL:
browser.goto "http://localhost:#{HTTP_PORT}/"

Speeding up rails tests during development by keeping Rails in memory?

When running rspec tests on my rails app using "rake" or "rake spec", it takes a long time to initialize Rails and start running tests.
Is there a way to keep Rails loaded in memory and run tests against it? I'm hoping there's something similar to using "grails interactive" like this How to speed up grails test execution but for Rails.
It's almost what Spork is all about.
See the most awesome railscast "How I test" http://railscasts.com/episodes/275-how-i-test
This uses guard to run a relevant test every time you save a file so you know almost instantly if the code you have written has caused a pass or a fail. Also if you are running on linux then you can use the libnotify and libnotify-rails gems which pop up a window for you (totally unobtrusively) indicating a pass or failure so you don't have to keep checking the console.
There is a Railscast called Spork that specifically discusses this problem at http://railscasts.com/episodes/285-spork and offers an excellent solution with a detailed walkthrough.

run ruby script in rails application

This may be a stupid question but I was just wondering where, or if its possible to run a ruby script which is kind of unrelated to the rails application I would like it to run in. To clarify, I am working on an automation test suite that is written mainly in bash, but I want to create a front end (my rails application) that allows other users to run automated tests not through the command line. So I guess basically I want a user to select certain parameters, from a database or form fields, then take those parameters and pass them to a ruby script which calls my bash automation script.
I hope this is clear. Thanks!
If you want to call a script from a rails app it gets complex. You would want to use a background job or some sort of queue to run these jobs because they do block the server and your users would be waiting for the call to complete and the results to load, most likely hitting a timeout.
See delayed_job
and you might want to try creating a small wrapper script in ruby that can interface with your application.
Good luck!
for short tasks you should use system or popen
when tasks are longer then they are still needed in case of delayed_job
You can add a script to your scripts folder in the root of your rails app. Start your script like this:
your script can be [name here].rb
The reason why we load in the environment is so we can use rails models and rails related things in your script:
#!/bin/env ruby
ENV['RAILS_ENV'] = "production" # Set to your desired Rails environment name
require '/[path to your rails app on your server]/config/environment.rb'
require 'active_record'
If you want to run this on your server, then you have to edit your crontab on your server. Or you can use the whenever gem (which I''m having trouble with, but the entire universe doesn't). Conversely, if you have heroku, then there's the heroku scheduler that makes running scripts easy.
You can run Ruby code with rails runner.
… let us suppose that you have a model called “Report”. The Report model has a class method called generate_rankings, which you can call from the command line using
$ rails runner 'Report.generate_rankings'
Since we have access to all of Rails, we can even use the Active Record finder method to extract data from our application.
$ rails runner 'User.pluck(:email).each { |e| puts e }'
charles.quinn#highgroove.com
me#seebq.com
bill.gates#microsoft.com
obie#obiefernandet.com
Example taken from The Rails 5 Way by Obie Fernandez.

Gems slowing down Rails test startup, can I selectively disable these?

I have a terrible Rails test startup time. When running a single functional test that may take 2 seconds to run, the total time from execution to returning to the command line could be up to 10-15 seconds.
There are two gems I know are definitely getting in the way. A Facebook and Flickr gem (Facebooker, Flickraw).
Facebooker will always print the following message when any test is run:
/vendor/gems/facebooker-0.9.5/lib/facebooker.rb:23: warning: already initialized constant VERSION
And Flickraw appears to be making a network connection every single time to retrieve a list of what I believe are API calls it can make.
Can I selectively turn these gems off during test time? I'd really like to get my test run as close to how long the actual test takes to run as possible. Also, I have tried the rails_test_server gem and am having some difficulties as this is a very large project and the gem is hitting some conflicts somewhere in the project that I haven't resolved. But I believe this Facebook and Flickr gem problem should have a resolution somewhere.
How do you use those gems? Do you have a require somewhere in your config/environment.rb? If so you could add those requires to the development and production environment files, but not to the test environment file.
If you're able to run your application without loading all of the gems, that's probably a good indication that either you didn't really use the gem in the first place, or your tests are insufficient.
But yeah, the right way of doing this would be to move the gem loading into the development and production specific environment files.

Resources