Rails: Automatically running failed tests - ruby-on-rails

I frequently run "rake", see some tests fail, and have to manually cut-and-paste failures into a new command, "ruby SomeTest -n some_test_method" to run individual tests. Is there any way to automate that?
It feels like standard behaviour for IDEs to show errors and allow quick re-playing, so I wonder if anyone has figured out how to do it quickly on the command line.

Guard is what you're looking for:
https://github.com/guard/guard
Guard watches the filesystem for changes and automatically triggers a command. With guard you can automatically run tests the second they're saved.
For minitest use:
https://github.com/guard/guard-minitest
For test unit:
https://github.com/guard/guard-test
For Rspec:
https://github.com/guard/guard-rspec

Related

How to run non-parallel in more than one process?

I am using parallel_tests gem and more specifically parallel_rspec. I have 2 sets of tests that can't run in parallel as they interfere with the state of some other tests.
Currently I am doing
parallel_rspec spec --single 'spec/set_A'
I now have the need to also run set_B non-parallely but how do I ensure that it runs in its own process and not with set_A's process above?
I have tried parallel_rspec spec --single 'spec/set_A|set_B' but it runs both sets in a single process which makes that process run for a really long time. Passing to separate --single flags also doesn't seem to achieve that.

How do I test the behavior executed by "whenever?"

I'm using whenever to schedule a task in Rails, and I would like to find a way to test the behavior being executed.
Is there a way to trigger the event in a test (like RSpec) so I can make assertions about the results? The executed task is a class method that by itself works because I've tested it manually in the Rails console, but is there a way to trigger the event so that this behavior happens and I can assert it works the same way within the config/schedule.rb?
I used a simple trick to assert my expectations like below
require 'spec_helper'
require 'whenever'
describe 'Schedule' do
it 'sends email 10th of each month before 08 AM EST' do
expected = "0 7 10 * * /bin/bash -l -c 'cd && script/rails runner -e production '\\''Delayed::Job.enqueue(MyMailerJob.new([2,3,4]), priority: 10)'"
expect(cron_output).to include(expected)
end
end
def cron_output
Whenever::JobList.new(file: Rails.root.join("config", "schedule.rb").to_s).
generate_cron_output.
gsub(Dir.pwd, '')
end
The "whenever event"
The only thing that changes in what whenever wraps (ie, cron) compared to your regular spec run is system environment, and more specifically environment variables.
You can see the commands whenever will install in cron using its executable :
$ whenever
Cron always start with a raw environment. If you check your crontab content (using crontab -e) you'll see on top variables that are set. You can set additional variables, there. For example :
SHELL="/bin/bash"
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
MAILTO="your_user"
HOME="/home/your_user"
RAILS_ENV="production"
You should not need those, though, because whenever uses a nice trick : it calls all commands using /bin/bash -l -c. This ensures it uses a login shell, which loads ~/.bashrc file. So any variable that is exported in your bashrc file will be accessible within cron execution.
Also note some distributions (like gentoo) have a check in the skel bashrc file that quit if shell is not interactive (so you have to set your environment variables before it if they are needed in cron).
Tests with similar env
To answer about testing, this is probably not a good idea. There's nothing related to your codebase here, only related to your system (similarly, you don't test which version of postgres or imagemagick is installed on your system in your specs).
You can somewhat simulate, for debugging sake, what happens in cron while invoking rspec doing such :
env - HOME=/home/<your_user>/ /bin/bash -l -c 'rspec spec/'
This will ensure environment is emptied (env -), then set HOME as a minimal env, then call a login shell just like whenever commands do.

Travis failing when Cucumber task pending?

As title says, my travis-ci instance is telling me that my build is failing when I have cucumber step definitions that are pending (not undefined) - is there a way to stop this behaviour?
I can understand the reason why, but the undefined behaviour I have is undefined by purpose - I have no intention on doing that feature RIGHT NOW, but I know I want to keep the step definition down so I don't forget what I came up with. The reason I ask is because this behaviour (with it failing when I have a pending task) could end up masking real failures that actually matter.
There is a similar answer here which should be useful for you, the answer that he gives is:
I think cucumber gives non-zero process exit code either because of
skipped or because of pending tests. Try to get it to not run any
skipped, then any pending, then any skipped or pending tests and see
what exit codes it gives. To see the exit code (in Unix), run it with
something like:
cucumber ...args to select tests... ; echo $?
So basically you want to figure out what args you can provide to cucumber to have it pass and then provide a .travis.yml that runs that command. an example rake task for cucumber jasmine and rspec is here:
task :travis do
["rspec spec", "rake jasmine:ci", "rake cucumber"].each do |cmd|
puts "Starting to run #{cmd}..."
system("export DISPLAY=:99.0 && bundle exec #{cmd}")
raise "#{cmd} failed!" unless $?.exitstatus == 0
end
end
And read the docs for more info on creating a .travis.yml.
If all of that doesn't work, just create a bash script that catches the output and returns 0 in the right cases, I really doubt this is required though since I'm sure there's an option to cucumber to make it ignore pending.
EDIT: the cucumber docs say:
Pending steps
When a Step Definition’s Proc invokes the #pending method, the step is
marked as yellow (as with undefined ones), reminding you that you have
work to do. If you use --strict this will cause Cucumber to exit with
1.
Which seems to imply that they will not exit with 0 if you don't call --strict

Optimizing Rails loading for maintenance scripts

I wrote a script that does maintenance tasks for a rails application. The script uses a class that uses models defined in the application. Just an example, let's say application defines model User, and my class (used within the script), sends messages to it, like User.find id.
I am looking for ways to optimize this script, because right now it has to load the application environment: require '../config/environment'. This takes ~15 seconds.
Had the script not use application codebase to do its job, I could have replaced model abstractions with raw SQL. But unfortunatly I can't do that because I would have to repeat the code in the script that is already present in the codebase. Not only would this violate DRY principle and require alot of work, the script would not be very maintainable, in case the model methods that I am using change.
I would like to hear ideas how to approach this problem. The script is not run from the application itself, but from the shell (with Capistrano for instance).
I hope I've described the problem clear enough. Thank you.
Could you write a little daemon that is in a read on a pipe (or named fifo, or unix domain socket, or, with more complexity, a tcp port) that accepts 'commands' that would be run on your database?
#!/usr/bin/ruby
require '../config/environment'
while (true) do
File.open("/tmp/fifo", "r") do |f|
f.each_line do |line|
case line
when "cleanup" then puts "clean!"
when "publish" then puts "published!"
else puts "invalid command, ignoring"
end
end
end
end
You could start this thing up with vixie cron's #reboot specifier, or you could run it via capistrano commands, or run it out of init or init scripts. Then you write your capistrano rules (that you have now) to simply echo commands into the fifo:
First,
mkfifo /tmp/fifo
In one terminal:
$ ./env.rb
In another terminal:
$ echo -n "cleanup" > /tmp/fifo
$ echo -n "publish" > /tmp/fifo
$ echo -n "go away" > /tmp/fifo
The output in the first terminal looks like this:
clean!
published!
invalid command, ignoring
You could make the matching as friendly (perhaps allow plain echo, rather than require echo -n as my example does) or unfriendly as you want. And the commands that get run can of course call into your model files to do their work.
Please make sure you choose a good location for your fifo -- /tmp/ is probably a bad place, as many distributions clear it on reboot. Also make sure you set the fifo owner and permission (chown and chmod) appropriately for your application -- you might not want to allow your Firefox's flash plugin to write to this file and command your database.

cucumber command that will print out just the feature and scenario names

Is there a cucumber command that will print out just the feature info and the scenario names?
I recently began a project and want to print out the cucumber features and scenarios I wrote to describe the scope of the project and get it confirmed with the client.
Do you mean cucumber -d?
$ cucumber -h
-d, --dry-run Invokes formatters without executing the steps.
This also omits the loading of your support/env.rb file if it exists.
Implies --no-snippets.
Implies --dry-run --formatter pretty.

Resources