Search code examples
ruby-on-railsrubyrspeccronwhenever

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?


Solution

  • 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.