rspec-guard detecting changes in spec folder, but not lib folder - guard

Like the title says, it detects changes in spec folder, not in lib folder.
Guardfile
guard :rspec, cmd: "bundle exec rspec" do
require "guard/rspec/dsl"
dsl = Guard::RSpec::Dsl.new(self)
# Feel free to open issues for suggestions and improvements
# RSpec files
rspec = dsl.rspec
watch(rspec.spec_helper) { rspec.spec_dir }
watch(rspec.spec_support) { rspec.spec_dir }
watch(rspec.spec_files)
# Ruby files
ruby = dsl.ruby
files = ruby.lib_files
save_path = '/data/sites/scripts/sw_scripts/ruby/files.txt'
File.write(save_path, ruby.lib_files.inspect)
dsl.watch_spec_files_for(ruby.lib_files)
end
Gemfile
source 'https://rubygems.org'
gem 'nokogiri'
gem 'thor'
gem 'rmagick'
group :development do
gem 'guard-rspec', require: false
gem 'simplecov', :require => false
end
group :development, :test do
gem 'pry-byebug'
gem 'rspec', ">=3.0"
end
What I did:
read lots of Guard documentation - it's hopelessly outdated, Guardfile has changed it's syntax (it contains some regexes while there was no regexes in my autogenerated Guardfile, links to 3+ year old tutorials etc)
put puts statement in Guardfile to see what is ruby.lib_files
it didn't work so I used File.write(path, ruby.lib_files.inspect)
file contained regexp
So I went into irb and confirmed that regexp is correct, it matches all lib files from Dir['**/*']
r = /^(lib\/.+)\.rb$/
`pwd`
=> "correct_dir\n"
files = Dir['**/*']
=> ** 149 files **
puts files.select { |f| r =~ f }
=> ** 36 files (snippet) **
lib/gallery_util/gallery_source.rb
lib/gallery_util/legacy_gallery_updater.rb
lib/gallery/specs/specs.rb
lib/gallery/specs/report.rb
lib/gallery/specs/universal_property.rb
lib/gallery/front_page_creator.rb
...
So all files are recognized, but when I run guard for any of the lib files it doesn't work at all. I get this output when I run guard in debug mode:
09:55:44 - DEBUG - Interactor was stopped or killed
09:55:44 - DEBUG - Hook :run_on_modifications_begin executed for Guard::RSpec
09:55:44 - DEBUG - Hook :run_on_modifications_end executed for Guard::RSpec
09:55:44 - DEBUG - Start interactor
Only thing that comes to mind is that guard for some reason doesn't look into lib folder recursively. I doubt that possible, why would anyone decide that?
Other thing that it depends on location of .git.
.git is 2 folders above this one (because this is collection of independent scripts that work togather and I want them in 1 repo, not 5+)
How to fix it? How to force guard to watch lib folder recursively?

It seems that guard needs spec folders structure to match identically the lib folder structure. It can't figure out matching spec if you have files
lib/gallery/front_page.rb
spec/front_page_spec.rb
No you have to create it like this:
lib/gallery/front_page.rb
spec/lib/gallery/front_page_spec.rb
I assume this would work as well (but haven't tried it)
lib/gallery/front_page.rb
spec/gallery/front_page_spec.rb
To guard maintainers: surely would be nice if that was documented somewhere.

I am new to Guard and spent the last two days to understand why RSpec doesn't start when a 'something_test.rb' file is modified and saved.
Digging deep into the code, I have found a method in Inspectors::BaseInspector
def _select_only_spec_files(paths)
spec_files = _collect_files("*[_.]spec.rb")
which forces test files to be named '..._spec.rb'. According to the documentation of Guard/Dsl :
The watch method tells Guard which changed files the plugin should respond to.
In my opinion this hard-coding of '_spec.rb' is in contradiction with the freedom that watch gives to you.
Also I don't like the code in your Guardfile, which is generated by guard init rspec. The intention of the authors is certainly good, it allows newcomers to quickly start automating RSpec tests. But one don't master what's going on behind the scene, and it seems to be your case.
This is my Guardfile with a patch to redefine SimpleInspector#paths :
directories %w[ lib spec ]
guard :rspec, cmd: 'rspec' do
require 'guard/rspec'
require "guard/rspec/inspectors/simple_inspector.rb"
module ::Guard
class RSpec < Plugin
module Inspectors
class SimpleInspector < BaseInspector
def paths(paths)
# please don't clear modified files correctly detected
# by watch but whose name doesn't end with '_spec.rb'
paths # return input without modification
end
end
end
end
end
# test files
watch(/^spec\/.*_test\.rb$/)
# source files
# watch(%r|^lib/(?<path>.+)\.rb$|) { | m | "spec/#{m[:path]}_test.rb" }
# *** same as ***
watch(/^lib\/(.+)\.rb$/) { | m | "spec/#{m[1]}_test.rb" }
end
This is a temporary workaround I hope, at least it lets me define a watch statement the way I want, which corresponds to my existing test files.
The first watch detects changed RSpec '..._test.rb' files in the spec directory. The second watch detects a changed source file in the lib directory or one of its subdirectories, and transforms its name in the block so that RSpec will be presented a 'spec/..._test.rb' file.
This way you get rid of any constraint and can master your own regexp. You could even manipulate the path in the block, if the hierarchy of the tests doesn't match the one of the sources : why not
watch(/^abd\/def\/(.+)\.rb$/) { | m | "anywhere\/you\/like\/#{m[1]}_test.rb" }
And I can reassure you : guard-2.14.1 on my Mac perfectly detects changed files even deep inside the lib folder hierarchy.
HTH
PS : I don't have bundle, but you can replace cmd: 'rspec' by cmd: "bundle exec rspec" in the guard command.
Some console output to convince you it works (the test file is empty) :
21:08:29 - DEBUG - Start interactor
21:08:29 - DEBUG - Command execution: stty -g 2>/dev/null
[1] guard(main)> _[Guard] in guard.rb #async_queue_add ch={:modified=>["lib/antlr4/ruby_static/listeners/please_check_me.rb"], :added=>[], :removed=>[]}
21:08:36 - DEBUG - Interactor was stopped or killed
21:08:36 - DEBUG - Command execution: stty 2>/dev/null
_[Guard] //1 in Runner#run_on_changes mod=["lib/antlr4/ruby_static/listeners/please_check_me.rb"] add=[] rem=[]
...
_[Guard] //3 in Runner#run_on_changes ... plugin Guard::RSpec yielded, types={[:run_on_modifications, :run_on_changes, :run_on_change]=>["lib/antlr4/ruby_static/listeners/please_check_me.rb"], [:run_on_additions, :run_on_changes, :run_on_change]=>[], ...
_[Guard] //3+ plugin=#<Guard::RSpec #name=rspec #group=#<Guard::Group #name=default #options={}> #watchers=[#<Guard::Watcher:0x0..., #pattern=#<Guard::Watcher::Pattern::Matcher:0x007fbdca22d780 #matcher=/^spec\/.*_test\.rb$/>>, ..., #pattern=#<Guard::Watcher::Pattern::Matcher:0x007fbdca22d528 #matcher=/^lib\/(.+)\.rb$/>>]
...
_[Guard] //5 in Runner#run_on_changes ... match_result=["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"]
...
task=run_on_modifications
_[Guard] /+-+ in Runner#_supervise pl=Guard::RSpec, t=run_on_modifications, args=[["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"]]
...
21:08:36 - DEBUG - Hook :run_on_modifications_begin executed for Guard::RSpec
_[Guard] ยงยงยง in Plugin self.notify gp=Guard::RSpec, ev=run_on_modifications_begin, args=[["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"]]
_[Guard] /+-+ in Runner#_supervise about to plugin.send task=run_on_modifications, args=[["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"]]
_[RSpec] &&&& in RSpec#run_on_modifications paths=["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"]
_[RSpec] &&&& in RSpec#run_on_modifications about to runner.run
_[RSpec] ))) in RSpec::Runner#run paths=["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"] inspector=#<Guard::RSpec::Inspectors::SimpleInspector:0x007fbdca2351b0>
_[RSpec] ))) in RSpec::Runner#run after inspector ["spec/antlr4/ruby_static/listeners/please_check_me_test.rb"]
21:08:36 - INFO - Running: spec/antlr4/ruby_static/listeners/please_check_me_test.rb
_[RSpec] ))) in RSpec::Runner#_run
_[RSpec] ))) in RSpec::Runner#_run command=rspec
...
_[RSpec] ))) in RSpec::Runner#_really_run cmd=rspec -f documentation -r /Users/b/.rvm/gems/ruby-2.3.3#rspec2/gems/guard-rspec-4.7.3/lib/guard/rspec_formatter.rb ... spec/antlr4/ruby_static/listeners/please_check_me_test.rb
...
21:08:36 - DEBUG - Command execution: ...
Finished in 0.00042 seconds (files took 0.10208 seconds to load)
0 examples, 0 failures
...
21:08:36 - DEBUG - Guard::RSpec: RSpec command spec ... exited with: 0
...
21:08:36 - DEBUG - Start interactor
21:08:36 - DEBUG - Command execution: stty -g 2>/dev/null

Related

Running Rspec fails if variables can be passed to a class in Puppet

Problem
If variables can be passed to a Puppet class, e.g.:
class module_name (
$variable='hello_world'
) {
package { 'package_name': }
}
and rspec is run it fails, i.e.:
[user#host module_name]$ rspec
...............................FFFFFFFFFFFF..........................................
Failures:
1) opsview should contain Class[module_name]
Failure/Error: it { should contain_class('module_name') }
Puppet::Error:
Error from DataBinding 'hiera' while looking up 'module_name::variable':
FileSystem implementation expected Pathname, got: 'Hash' on node host
# /usr/share/ruby/vendor_ruby/puppet/resource.rb:393:
in `rescue in lookup_with_databinding'
# /usr/share/ruby/vendor_ruby/puppet/resource.rb:387:
in `lookup_with_databinding'
# /usr/share/ruby/vendor_ruby/puppet/resource.rb:381:
in `lookup_external_default_for'
Main issue
Error from DataBinding while looking up FileSystem implementation expected Pathname,
got: 'Hash' on node
Configuration
Versions
[vagrant#vm-one opsview]$ puppet --version
3.7.5
[vagrant#vm-one opsview]$ rspec --version
3.2.2
Spec_helper
[vagrant#vm-one opsview]$ cat spec/spec_helper.rb
require 'rspec-puppet'
require 'hiera-puppet-helper'
fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))
RSpec.configure do |c|
c.module_path = File.join(fixture_path, 'modules')
c.manifest_dir = File.join(fixture_path, 'manifests')
c.hiera_config = '/etc/puppet/hiera.yaml'
end
at_exit { RSpec::Puppet::Coverage.report! }
Attempt
According to this Q&A hiera-puppet-helper is causing the
issue. Rspec-puppet seems to support testing of hiera and
'hiera-puppet-helper' could be replaced. Ok perhaps this solves the issue, but what is causing the issue?
This post contains the same issue, but not a solution to solve
the issue
This post indicates that removing the class parameters solves the issue, but this class is used by multiple modules and therefore this is not a solution.
There's a problem with the hiera_config, it should be:
c.hiera_config = 'spec/fixtures/hiera/hiera.yaml'
assuming that you have directory structure like:
\spec
\fixtures
\hiera
hiera.yaml
default.yaml
and hiera.yaml:
---
:backends:
- yaml
:hierarchy:
- '%{::clientcert}'
- default
:yaml:
:datadir: './spec/fixtures/hiera'
The hiera-puppet-helper gem is indeed not required, in fact it shouldn't be there. I'd recommend generating module structure using Garethr's skeleton which already contains working setup for Hiera and can save you a lot of time.

How to get the error log from SASS when using the rails asset pipeline?

I've got 3 Rails 3.2 applications using the gem jquery-ui-themes. jquery-ui-themes uses scss for the image-path helper.
It works great on two of my applications, but the 3rd doesn't seem to compile the scss files in either development or production modes.
IOW, it sends this to the browser
background: #fcfdfd url(image-path("jquery-ui/redmond/ui-bg_inset-hard_100_fcfdfd_1x100.png")) 50% bottom repeat-x;
whereas the two working apps properly send
background: #fcfdfd url("/assets/jquery-ui/redmond/ui-bg_inset-hard_100_fcfdfd_1x100.png") 50% bottom repeat-x;
I've spent many hours trying to make the app that's broken as similar to possible to the two working apps as I can, but it's still failing.
My theory is that SASS is choking on something previous to redmond.css.scss. If so, there should be an error logged somewhere. Where do I find the error output from SASS?
Update:
I introduced a deliberate error into redmond.css.scss and I got a proper error dump. So I know that I'm correctly clearing the cache and actually running sass. Now to figure out why it's ignoring the image-path directives.
If you're looking for the answer to the question in the title, the answer is "the same way you get any other errors: they're in your log". To get a full backtrace, just point your browser at the asset: ie http://localhost:3000/assets/jquery-ui/redmond.css in my case.
Make sure you clear all your caches: rm -rf .sass-cache/ && rm -rf public/assets && rake tmp:cache:clear, as well as using ctrl-shift-r in your browser.
If you're looking for the answer for my real problem (image-path not working), make sure you have the proper Bundler.require line in your application.rb. The old Rails 3.0 doesn't work.
replace:
# If you have a Gemfile, require the gems listed there, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) if defined?(Bundler)
with:
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end

Rails 3.1 asset pipeline not seeing files

We're upgrading our app from Rails 2 to Rails 3.1, and I'm having trouble with the asset pipeline.
I've got the following in my config/application.rb:
if defined?(Bundler)
Bundler.require *Rails.groups(:assets => %w(development test))
# Bundler.require(:default, :assets, Rails.env)
end
# Enable the asset pipeline
config.assets.enabled = true
# config.assets.prefix = "/assets"
config.assets.paths << "#{Rails.root}/public/images"
config.assets.paths << "#{Rails.root}/public/stylesheets"
config.assets.paths << "#{Rails.root}/public/javascripts"
config.assets.version = '1.0'
And then this in development.rb
# Do not compress assets
config.assets.compress = false
config.assets.debug = true
I know this isn't the desired behavior for the pipeline, but we are doing it this way to make sure that when we merge the upgrade back into our master branch, all the old files are accounted for properly.
I then have the following file, "all.css," in my public/stylesheets directory:
/*
*= require ezform
*= require jquery-ui-1.8.9.custom
*= require thickbox
*= require yui-upload
*= require styles
*/
I am calling it from within my layouts/application.html.erb file like so:
<%= stylesheet_link_tag "all" %>
Loading things up in a browser, however, I get no styles (or javascript, for that matter). Firebug and Chrome tell me that the .css and .js files are being looked for in "/assets" - it's like the pipeline isn't searching through everything and bundling it like it should.
The error looks like this:
GET http://localhost:3000/assets/jquery-dependent.js 500 (Internal Server Error)
If I move "all.css" into /app/assets, it still won't find it. Moving it into /assets stops the error, but the stylesheet doesn't compile and I still don't get any styles in my browser.
There's also a slew of errors that look like this in my log:
Started GET "/assets/defaults.js?body=1" for 127.0.0.1 at 2011-12-22 14:35:36 -0600
[2011-12-22 14:35:36] ERROR NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
/Users/kevin/.rvm/gems/ruby-1.9.2-p0#media3/gems/rack-1.3.5/lib/rack/handler/webrick.rb:71:in `service'
/Users/kevin/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111:in `service'
/Users/kevin/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:70:in `run'
/Users/kevin/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
cache: [GET /assets/defaults.js?body=1] miss, store
Served asset /defaults.js - 200 OK (1ms)
What am I missing?
sigh It was memcached. I tured it on (memcached -d) and now all my assets are appearing. I'm not sure why, so I'd love some explanation. Otherwise, it's working.
There are a while bunch of settings that need to be added into the development and application config files for the pipeline to work correctly.
Check out the last section of the pipeline guide for details of these.
Once you've done that I suggest that you change the manifest names to application.css and application.js as these are the default names and you'll run into fewer problems starting with those. Edit your question if it still does not work and I'll see if I can help after that.

Set up RSpec to test a gem (not Rails)

It is pretty easy with the added generator of rspec-rails to set up RSpec for testing a Rails application. But how about adding RSpec for testing a gem in development?
I am not using jeweler or such tools. I just used Bundler (bundle gem my_gem) to setup the structure for the new gem and edit the *.gemspec manually.
I also added s.add_development_dependency "rspec", ">= 2.0.0" to gemspec and did a bundle install.
Is there some nice tutorial what to do next to get RSpec working?
I've updated this answer to match current best practices:
Bundler supports gem development perfectly. If you are creating a gem, the only thing you need to have in your Gemfile is the following:
source "https://rubygems.org"
gemspec
This tells Bundler to look inside your gemspec file for the dependencies when you run bundle install.
Next up, make sure that RSpec is a development dependency of your gem. Edit the gemspec so it reads:
spec.add_development_dependency "rspec"
Next, create spec/spec_helper.rb and add something like:
require 'bundler/setup'
Bundler.setup
require 'your_gem_name' # and any other gems you need
RSpec.configure do |config|
# some (optional) config here
end
The first two lines tell Bundler to load only the gems inside your gemspec. When you install your own gem on your own machine, this will force your specs to use your current code, not the version you have installed separately.
Create a spec, for example spec/foobar_spec.rb:
require 'spec_helper'
describe Foobar do
pending "write it"
end
Optional: add a .rspec file for default options and put it in your gem's root path:
--color
--format documentation
Finally: run the specs:
$ rspec spec/foobar_spec.rb
Iain's solution above works great!
If you also want a Rakefile, this is all you need:
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
# If you want to make this the default task
task default: :spec
Check the RDoc for RakeTask for various options that you can optionally pass into the task definition.
You can generate your new gem with rspec by running bundler gem --test=rspec my_gem. No additional Setup!
I always forget this. It's implemented here: https://github.com/bundler/bundler/blob/33d2f67d56fe8bf00b0189c26125d27527ef1516/lib/bundler/cli/gem.rb#L36
Here's a cheap and easy (though not officially recommended) way:
Make a dir in your gem's root called spec, put your specs in there. You probably already have rspec installed, but if you don't, just do a gem install rspec and forget Gemfiles and bundler.
Next, you'll make a spec, and you need to tell it where your app is, where your files are, and include the file you want to test (along with any dependencies it has):
# spec/awesome_gem/awesome.rb
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
$: << File.join(APP_ROOT, 'lib/awesome_gem') # so rspec knows where your file could be
require 'some_file_in_the_above_dir' # this loads the class you want to test
describe AwesomeGem::Awesome do
before do
#dog = AwesomeGem::Awesome.new(name: 'woofer!')
end
it 'should have a name' do
#dog.name.should eq 'woofer!'
end
context '#lick_things' do
it 'should return the dog\'s name in a string' do
#dog.lick_things.should include 'woofer!:'
end
end
end
Open up Terminal and run rspec:
~/awesome_gem $ rspec
..
Finished in 0.56 seconds
2 examples, 0 failures
If you want some .rspec options love, go make a .rspec file and put it in your gem's root path. Mine looks like this:
# .rspec
--format documentation --color --debug --fail-fast
Easy, fast, neat!
I like this because you don't have to add any dependencies to your project at all, and the whole thing remains very fast. bundle exec slows things down a little, which is what you'd have to do to make sure you're using the same version of rspec all the time. That 0.56 seconds it took to run two tests was 99% taken up by the time it took my computer to load up rspec. Running hundreds of specs should be extremely fast. The only issue you could run into that I'm aware of is if you change versions of rspec and the new version isn't backwards compatible with some function you used in your test, you might have to re-write some tests.
This is nice if you are doing one-off specs or have some good reason to NOT include rspec in your gemspec, however it's not very good for enabling sharing or enforcing compatibility.

Execute migration files dynamically

How can we execute a mignation file dynamically from the source code. Means we want to execute a migration file from an action of a controller. How can we do so?
The main issue was that we do not know the names of migration files. I do it with the following code
ActiveRecord::Migrator.migrate("vendor/plugins/#{self.id.to_s}/lib/db/migrate/", nil)
Package::Rake.call('db:schema:dump')
And the Rake class have the following method
def call(task, options={})
options[:rails_env] = Rails.env
args = options.map { |n,v| "#{n.to_s.upcase}='#{v}"}
system "rake #{task} #{args.join(' ')} --trace >> #{Rails.root}/log/rake.log &"
end
Hope this will help some body with similar problems.
This is assuming the migration is static and in your db/migrate directory when the app server starts:
You could add the migrations directory to your autoload path in config/application.rb, and then require the migration file to be run inside your controller (or in a config initializer):
application.rb
config.autoload_paths += %W(#{Rails.root}/db/migrate)
your_controller.rb
require '20101209102033_some_migration_file'
#....
SomeMigrationFile.up
I would be interested to know what the use case is here. Seems pretty wild!