Minitest plugins (ie. minitest/pride) not working after installing rails - ruby-on-rails

I have two Ruby projects (1 Rails, 1 vanilla). Both using Ruby 3.0.3. In my Ruby project (before bundling my Rails one), Minitest::Pride is loaded and works when running rake test. But, after bundling the Rails project, I'm back to old red/green colors for rake test in the Ruby project.
Here's the file structure (for simplicity's sake, I'm stripping the Rails project down to just a Gemfile, which I can reproduce this error with on a clean Ruby Rbenv install):
ruby-project/
-- test/
-- example_test.rb
-- test_helper.rb
Gemfile
Rakefile
rails-project/
-- Gemfile
ruby-project/test/example_test.rb:
require "test_helper"
class ExampleTest < Minitest::Test
25.times do |i|
define_method "test_success#{i}" do
assert true
end
end
end
ruby-project/test/test_helper:
require "minitest/autorun"
require "minitest/pride"
ruby-project/Gemfile:
source "https://rubygems.org"
gem "rake"
gem "minitest"
ruby-project/Rakefile:
require "rake/testtask"
Rake::TestTask.new(:test) do |t|
t.libs = %w(lib test)
t.pattern = "test/**/*_test.rb"
end
task :default => :test
rails-project/Gemfile:
source "https://rubygems.org"
ruby "3.0.3"
gem "rails", "~> 7.0.3"
Steps to Reproduce (with rbenv already installed):
Build two projects like the ones above
rbenv install 3.0.3
From ruby-project dir: bundle
From ruby-project dir: rake test (Minitest::Pride plugin loaded)
From rails-project dir: bundle
From ruby-project dir: rake test (Minitest::Pride plugin NOT loaded)
Things I have tried:
locking Minitest to the exact same version for both projects (5.16.3 and 5.17.0)
locking Rails to 7.0.3.1 and 7.0.4.2
Bundling the Rails project first
I'm running on a M1 Mac, but I'm not sure this matters. Interestingly, rails test in a real Rails project WILL load Minitest::Pride.
Any ideas on what's going on and how to fix?

Related

How to test a gem that depends on Rails and uses Rails commands

I'm making a gem that executes Rails commands (rails g model Item for example). When I use it in a Rails project, everything works. The problem is testing it in development outside of a Rails project.
I'm using cucumber with aruba to test if CLI commands execute the proper rails commands and generate the expected files. Unfortunately, when I try to test the behaviour it fails because there are no rails files and the commands require to be run inside of a Rails project in order to work.
I have added a rails dependency to the gemspec:
Gem::Specification.new do |spec|
spec.add_development_dependency 'rails', '~> 5.2.4'
end
I've thought about creating a new rails project on test start and then deleting it after the tests run, but that seems highly inconvenient. Is there a better way to do this?
A technique we use for WickedPDF is in the default rake task, before we run the tests, is to delete & generate a full Rails application in a gitignored subdirectory of the gem.
As a high-level simplified example of this Rakefile, it looks something like this:
Rakefile
require 'rake'
require 'rake/testtask'
# This gets run when you run `bin/rake` or `bundle exec rake` without specifying a task.
task :default => [:generate_dummy_rails_app, :test]
desc 'generate a rails app inside the test directory to get access to it'
task :generate_dummy_rails_app do
if File.exist?('test/dummy/config/environment.rb')
FileUtils.rm_r Dir.glob('test/dummy/')
end
system('rails new test/dummy --database=sqlite3')
system('touch test/dummy/db/schema.rb')
FileUtils.cp 'test/fixtures/database.yml', 'test/dummy/config/'
FileUtils.rm_r Dir.glob('test/dummy/test/*') # clobber existing tests
end
desc 'run tests in the test directory, which includes the generated rails app'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
Then, in test/test_helper.rb, we require the generated Rails app, which loads Rails itself and it's environment:
test/test_helper.rb
ENV['RAILS_ENV'] = 'test'
require File.expand_path('../dummy/config/environment.rb', __FILE__)
require 'test/unit' # or possibly rspec/minispec
# Tests can go here, or other test files can require this file to have the Rails environment available to them.
# Some tests may need to copy assets/fixtures/controllers into the dummy app before being run. That can happen here, or in your test setup.
You could skip parts of Rails that aren't needed by customizing the command that generates the app. For example, your gem may not need a database at all or a lot of things by default, so you command could be customized for a simpler app. Something like this maybe:
system("rails new test/dummy --skip-active-record \
--skip-active-storage --skip-action-cable --skip-webpack-install \
--skip-git --skip-sprockets --skip-javascript --skip-turbolinks")
In the WickedPDF project, we wanted to test across a wide range of "default" Rails installs, so we don't customize the command much, but that may generate much more than what you need to test some generator tasks.
WickedPDF also tests against multiple versions of Rails with TravisCI and multiple Gemfiles, but this could also be accomplished with the Appraisal gem that Luke suggested in this thread.
Check out Thoughbot's Appraisal gem:
Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."
Here is a guide on how to set it up, including setting up a micro Rails app within your tests dir.

Getting started with rspec

I'm trying to do the labs on TestFirst.org with rspec. I've installed rspec and initilized it in the project directory. But when i "rake" i get this error message:
Could not find 'rspec' <~> 2) - did find: [rspec-3.0.0]
C:/Sites/RubyTest/RubyTesting/learn_ruby/rakefile:2:in `<top (required)>ยด
My versions:
ruby 1.9.3p545
rails 4.1.1
rspec 3.0.2
Seems like I've got the wrong version of rspec or something. My OS is windows 7 btw.
This is the content of rakefile:
gem 'rspec', '~>2'
require 'rspec/core/rake_task'
task :default => :spec
desc "run tests for this lab"
RSpec::Core::RakeTask.new do |task|
lab = Rake.application.original_dir
task.pattern = "#{lab}/*_spec.rb"
task.rspec_opts = [ "-I#{lab}", "-I#{lab}/solution", '-f documentation', '-r ./rspec_config']
task.verbose = false
end
This is because rspec ~3.0.0 is already activated and your rake file requires 'rspec', '~>2'. Change rspec version in Rakefile to fix this.
gem 'rspec', '~>3'
Looks like you have a installed version of rspec (3.0.2) that is more recent than the one expected by the project (~ 2.x).
One simple way to solve it would be to force bundle to use the project version:
bundle exec rake
(instead of just using rake)

Why does Ruby run only some tests and not others?

I'm using this command to run some tests...
bundle exec ruby -Itest test/functional/*.rb
In my test/functional dir I have two files...
file_sets_controller_test.rb
user_sessions_controller_test.rb
With the above command, the tests in file_sets_controller_test.rb all run but the ones in user_sessions_controller_test.rb don't run at all -- no errors or other output is reported.
However, I can run that file directly no problem, with this...
bundle exec ruby -Itest test/functional/user_sessions_controller_test.rb
That works fine.
I know that another option is to use rake test functionals, but that is extremely slow compared to running them directly.
ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-darwin11.4.2]
Rails 3.2.12
Here's a part of my Gemfile...
group :development, :test do
gem 'ansi'
gem 'turn'
gem 'minitest'
gem 'minitest-matchers'
end
And here's my test_helper.rb...
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'turn/autorun'
Turn.config.ansi = true
require 'minitest/autorun'
class ActiveSupport::TestCase
fixtures :all
end
Removing the Turn and Minitest gems doesn't change anything as far as I can tell.
The ruby command takes a ruby file to run as its first argument and makes additional arguments available to the ruby program. The shell is expanding your glob expression into 2 arguments and passing them to ruby, so ruby is running the first file name in the expansion.
Additional:
I think you can do what you want with something like...
bundle exec ruby -Itest -e "Dir.glob('test/functional/*_test.rb').each{|f| require File.expand_path(f)}"

Nested Project For Testing Ruby Gem

When creating a gem for a specific application framework, I nest a project within the gem in a test directory. For example, with a Rails specific gem I'd setup a directory structure like:
Rakefile
Gemfile
attached.gemspec
lib/attached.rb
lib/...
test/Gemfile
test/app/...
test/...
To test, I setup the nested project Gemfile using gem 'attached', path: '...' and run rake test inside the test directory. Is it possible to add a task to my main Rakefile that will allow me to run the tests in my sub project without changing into the directory first?
I always use the gem enginex to help me setup my gems with an integrated rails application.
In the root Rakefile they write:
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end
task :default => :test
They do not use a nested Gemfile, instead they load the Rails project inside the test_helper.rb and rails is a development/test dependency of the gem.
To check out the gem:
gem install enginex
Or check the source. This gem is included in rails 3.1 as the new plugin generator.
The simplest way (and I think the least bug prone), would be to have a task like:
task :test do
system('cd test; bundle exec rake test')
end
The other, more complicated way would be to include all "subtasks" in the root Rakefile add a prerequisite to each one of them, that will change the current directory, like so:
task :change_dir do
puts 'changing dir'
Dir.chdir('test')
end
namespace :sub do
load 'test/Rakefile'
end
Rake::Task.tasks.select{|t| t.name.start_with?('sub:')}.each do |task|
task.prerequisites.insert(0, 'change_dir')
end
I'm not sure how this will work with bundler though.
One last thing that I would recommend to you is to take a look at a project structure that bundle gem command creates. I use it for all my gems now, and I believe that taking advantage of it would make your problem go away entirely:)

Rails shoulda and factory_girl setup

I have installed both shoulda and factory_girl, I can run shoulda just fine, but when I add this:
require 'factory_girl'
Factory.define :user do |u|
u.mail 'test#example.com'
u.pass 'secret'
end
to my test/test_helper.rb I'm getting this error:
/test/test_helper.rb:1:in `require': no such file to load -- factory_girl (LoadError)
when I execute rake test:units
I have installed both gems using:
sudo gem install thoughtbot-shoulda --source=http://gems.github.com
sudo gem install thoughtbot-factory_girl --source=http://gems.github.com
and can see both of them being installed fine.
And by the way, this works fine as well:
script/console
Loading development environment (Rails 2.3.8)
require 'factory_girl'
=> []
so requiring the gems seems to be working
Couple things to check:
Don't use --source=http://gems.github.com anymore. This has been deprecated in favor for gemcutter.org
Don't use "thoughtbot-gem_name" - again this was deprecated by gemcutter.org. Just do sudo gem install factory_girl shoulda
Make sure you have config.gem 'factory_girl' in your config/environments/test.rb file.
if you are using spork, make sure to restart it. Took me a few moments to realize that.

Resources