MiniTest suite only running two out of 4 testcase files - ruby-on-rails

I have a TDD solution written in Ruby 1.9.3 (latest stable Windows RubyInstaller).
The application is in the app directory and in the sibling test directory I have 4 files containing tests.
I have a Rakefile executing a MiniTest test suite that merely includes the test case files.
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList['test/ts_*.rb']
t.verbose = true
end
ts_test_suite.rb:
gem 'minitest'
require_relative 'tc_requirement_tests.rb'
require_relative 'tc_command_tests.rb'
require_relative 'tc_movement_tests.rb'
require_relative 'tc_placement_tests.rb'
When I execute rake test from the commandline 2 of the 4 files execute successfully and (for some strange reason) the other two are not being executed. tc_requirement_tests.rb is one of those two files:
require 'test_base.rb'
require './app/turn_to.rb'
require './app/direction.rb'
class RequirementTests < TestBase
def requirement_test_1
#bad_robot.place(0, 0, Direction::NORTH)
#bad_robot.move
assert_equal "Output: 0,1,NORTH", #bad_robot.report_posture
end
def requirement_test_2
#bad_robot.place(0, 0, Direction::NORTH)
#bad_robot.turn(TurnTo::LEFT)
assert_equal "Output: 0,0,WEST", #bad_robot.report_posture
end
def requirement_test_3
#bad_robot.place(1, 2, Direction::EAST)
#bad_robot.move
#bad_robot.move
#bad_robot.turn(TurnTo::LEFT)
#bad_robot.move
assert_equal "Output: 3,3,NORTH", #bad_robot.report_posture
end
end
If I deliberately put a syntax error in one of the two test case files that are not executing, Rake complains with the expected error message, so I know that it is "seeing" the file.
Any ideas why 2 of the 4 test case files are not being executed?

It sounds like your test framework needs the test function names to begin test_. Try renaming your test functions so that they're in the format test_requirement_1, test_requirement_2, etc.

Related

Is there a way to cleanup database tests in Rails 6.0.3.1 System Tests. I thought Rails does the cleanup?

Using
Ruby "2.7.1"
Rails "6.0.3.1"
Mac OS Catalina 10.15.5
Using the default Rails Minitest and FactoryBot for test data.
Issue: I have test data being shared between system test files and hence failing tests. When I run the system test files individually the tests pass but this is inconvenient.
I use the the system test config out of the box as in the application_system_test_case.rb
This is my system test scenario.
I have 3 Customers in customers_system_test.rb file and 1 Customer (so far) in job_description_system_test.rb Customer 1 appears in the customers_system_test.rb failing test screenshots that Rails conveniently provide.
Note: The 3 failing tests all concern record counts such as assert_equal Customer.count, 3
The 3 failing tests
test "visit create customer and navigate back" do
...
assert_equal Customer.count, 3
end
test "cancel destroying a customer" do
assert_equal Customer.count, 3
...
end
test "destroy a customer" do
assert_equal Customer.count, 3
...
end
Interestingly I had the same issue with test data not being cleaned up when running rails test for controller, integration tests etc: The way I get around that is adding the following snippet to the test_helper.rb :
(ActiveRecord::Base.connection.tables - %w{schema_migrations}).each do |table_name|
ActiveRecord::Base.connection.execute "TRUNCATE TABLE #{table_name} CASCADE;"
end Doesn't work for system tests
I feel like I am missing the obvious?
test_helper.rb
require "simplecov"
SimpleCov.start "rails"
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
require "rails/test_help"
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
include Warden::Test::Helpers
# Run tests in parallel with specified workers
# parallelize(workers: :number_of_processors)
parallelize(workers: 1)
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
# fixtures :all
# Add more helper methods to be used by all tests here...
include Devise::Test::IntegrationHelpers
end
(ActiveRecord::Base.connection.tables - %w{schema_migrations}).each do |table_name|
ActiveRecord::Base.connection.execute "TRUNCATE TABLE #{table_name} CASCADE;"
end
Ok I got all tests running and passing including system tests by doing the following (wasn't aware this was necessary in Rails 6)
...
setup do
sign_in user
#customer_1 = FactoryBot.create(:customer_with_job_descriptions)
#job_description_2 = FactoryBot.create(:job_description, customer_id: #customer_1.id)
end
teardown do
#customer_1.destroy!
#job_description_2.destroy!
end
...
Ref: 8 Setup and Teardown
https://guides.rubyonrails.org/v3.2/testing.html#setup-and-teardown
........................................................................................
Finished in 22.971069s, 4.3968 runs/s, 21.4182 assertions/s.
101 runs, 492 assertions, 0 failures, 0 errors, 0 skips

How to prevent RSpec from running specs twice in Rails plugin with dummy app?

I'm writing a Rails extension. To test it, I use RSpec. In order to make models to test the plugin on, I use a pregenerated dummy app:
rails plugin new yaffle --dummy-path=spec/dummy --skip-test --full
I have a few tests. When I call them, they run twice.
> # I have 4 tests in app total
> rspec
> 8 examples, 0 failures
> rspec spec/yaffle/active_record/acts_as_yaffle_spec.rb
> 4 examples, 0 failures
> rspec spec/yaffle/active_record/acts_as_yaffle_spec.rb:4
> 2 examples, 0 failures
This is how my files look like:
# lib/yaffle.rb
Gem.find_files('yaffle/**/*.rb').each { |path| require path }
module Yaffle
# Your code goes here...
end
# spec/spec_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../dummy/config/environment", __FILE__)
RSpec.configure do |config|
config.example_status_persistence_file_path = '.rspec_status'
config.disable_monkey_patching!
end
# spec/dummy/config/environment.rb
# Load the Rails application.
require_relative 'application'
# Initialize the Rails application.
Rails.application.initialize!
# spec/yaffle/active_record/acts_as_yaffle_spec.rb
require "spec_helper"
RSpec.describe "Acts as yaffle" do
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
end
def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
assert_equal "last_tweet", Wickwall.yaffle_text_field
end
end
# spec/dummy/config/application.rb
require_relative 'boot'
require "rails/all"
Bundler.require(*Rails.groups)
require "yaffle"
module Dummy
class Application < Rails::Application
config.load_defaults 6.0
end
end
Also, I noticed that only files with require "spec_helper" are duplicated
So, what am I doing wrong? And, if it's a bug, how to work around it?
The cause
It was caused by this line:
Gem.find_files('yaffle/**/*.rb').each { |path| require path }
Apparently, Gem.find_files gets all files in gem directory that match that pattern - not only the files relative to gem root. So, yaffle/**/*.rb means both files in <GEM_ROOT>/lib/yaffle/... and <GEM_ROOT>/spec/lib/yaffle/....
https://apidock.com/ruby/v1_9_3_392/Gem/find_files/class
Fix
I fixed it by requiring all files explicitly:
require 'lib/yaffle/active_record/acts_as_yaffle'
require 'lib/yaffle/active_record/has_fleas'
It's also possible to just require all files from that directory:
Dir["lib/yaffle/active_record/**/*.rb"].each {|file| require file }

Run tests in custom test folder in Rails 5

When I want to run all model tests we do
rails test:models
If I similarly would like to run tests that sits in a folder called service_objects (in the test folder) - what would be the required steps?
With inspiration from multiple, sources I have tried the following in lib/tasks:
namespace :test do
Rails::TestTask.new(classes: 'test:prepare') do |t|
t.pattern = 'test/service_objects/**/*_test.rb'
end
end
But running rails test:service_objects returns this error message:
NameError: uninitialized constant Rails::TestTask
Replace Rails::TestTask with Rails::TestUnit::Runner as shown in the file below, with the require path indicated at the top.
Then to run ONLY the tests in test/focused directory, you can call
rails test:focused
and to run ALL tests in the test directory EXCEPT those in test/long_running, you can call
rails test:without_long_running
Tested with Rails 5.1.6
The new Rails 5 test runner does have some really helpful features, but sometimes you still need a little more control.
# lib/tasks/test_tasks.rake
require "rails/test_unit/runner"
namespace :test do
task :focused => "test:prepare" do
$: << "test"
test_files = FileList['test/focused/*_test.rb']
Rails::TestUnit::Runner.run(test_files)
end
task :without_long_running_tests => "test:prepare" do
$: << "test"
test_files = FileList['test/**/*_test.rb'].exclude('test/long_running/**/*_test.rb')
Rails::TestUnit::Runner.run(test_files)
end
end
Credit should go to jonatack may 2015 post here: https://github.com/rails/rails/issues/19997

using the --format documentation option with Rspec and Rake

I am in the process of learning Ruby and I recently set up a small project in which i am writing an API.
currently i have 2 classes, one called API which inherits from Grape
class API < Grape::API
(first quick question, within this class can i have normal methods, like def say_hello ? or is it just web methods?)
and one which i have called APIHelpers
i have set up 2 x spec files
api_spec.rb
APIHelpers_spec.rb
this is the contents of my Rakefile:
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new do |t|
t.rspec_opts = '--format documentation'
t.pattern = ['spec/libs/*.rb']
end
task :default => :spec
When i run the rake (i am using Rubymine 6.0 as my IDE) i am not getting any output from the Rspec except that the 2 tests i have added have passed.
2 examples, 0 failures, 2 passed
Finished in 0.05642 seconds
using the --format documentation i would have expected to see the whole structure from the describe and it statements.
Does anyone have any idea on how i can go about making these tests show correctly using RubyMine?
thanks
in case anyone else comes across this question, here is what i did to get around this issue,
instead of using Rake to run my tests i just used a Rspec configuration, added in an spec_helper
and added in this bit of code
RSpec.configure do |config|
config.color_enabled = true
config.tty = true
config.formatter = :documentation
config.expect_with :rspec do |c|
c.syntax = :expect
end
end
this fixed my issues

How to Test Factories First with Minitest but without the spec framework?

I found a blog post about Testing Factories First (by BigBinary - which happens to be a Minitest/spec version of Thoughtbot's RSpec original).
Could you please show me the equivalent without the spec framework - just with Minitest (Rails)?
The Thoughtbot approach (RSpec)
spec/factories_spec.rb
FactoryGirl.factories.map(&:name).each do |factory_name|
describe "The #{factory_name} factory" do
it 'is valid' do
build(factory_name).should be_valid
end
end
end
Rakefile
if defined?(RSpec)
desc 'Run factory specs.'
RSpec::Core::RakeTask.new(:factory_specs) do |t|
t.pattern = './spec/factories_spec.rb'
end
end
task spec: :factory_specs
The BigBinary approach (Minitest, spec)
spec/factories_spec.rb
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe FactoryGirl do
EXCEPTIONS = %w(base_address base_batch bad_shipping_address)
FactoryGirl.factories.each do |factory|
next if EXCEPTIONS.include?(factory.name.to_s)
describe "The #{factory.name} factory" do
it 'is valid' do
instance = build(factory.name)
instance.must_be :valid?
end
end
end
end
lib/tasks/factory.rake
desc 'Run factory specs.'
Rake::TestTask.new(:factory_specs) do |t|
t.pattern = './spec/factories_spec.rb'
end
task test: :factory_specs
What is the Minitest equivalent (without spec)?
The approach I am presenting below is slightly different than the two original solutions - in the sense that my approach creates only one test, within which I cycle through the factories and run an assertion against each. I was not able to create a solution that mimics the original solutions any closer - which is (I believe) a separate test method for each factory. If someone could show such an implementation, that would be cool.
test/aaa_factories_tests/factories_test.rb
require File.expand_path(File.dirname(__FILE__) + '/../test_helper.rb')
class FactoriesTest < Minitest::Unit::TestCase
puts "\n*** Factories Test ***\n\n"
EXCEPTIONS = %w(name_of_a_factory_to_skip another_one_to_skip)
def test_factories
FactoryGirl.factories.each do |factory|
next if EXCEPTIONS.include?(factory.name.to_s)
instance = FactoryGirl.build(factory.name)
assert instance.valid?, "invalid factory: #{factory.name}, error messages: #{instance.errors.messages.inspect}"
instance = factory = nil
end
end
end
Thanks to the way Minitest works out of the box -- add any directories under test/ and minitest-rails will automatically create the associated rake task for it. So let's say you add a test/api/ directory, rake minitest:api will automagically be available. -- I see the task when I run bundle exec rake -T with no other configurations:
rake minitest:aaa_factories_tests # Runs tests under test/aaa_factories_tests
And I am able to run this task successfully:
-bash> bundle exec rake minitest:aaa_factories_tests
*** Factories Test ***
Run options: --seed 19208
# Running tests:
.
Finished tests in 0.312244s, 3.2026 tests/s, 9.6079 assertions/s.
1 tests, 3 assertions, 0 failures, 0 errors, 0 skips
Despite the ugliness of prepending the directory with aaa, I am able to have the factories tested first with:
bundle exec rake minitest:all
The reason for the aaa prepend solution is MiniTest does a Dir glob and on Mac OS X (and other Unix variants) the results are sorted alphabetically (though the results differ across different platforms).
As well, I prepended the default_tasks array with aaa_factories_tests to have the factories tested first in the default Minitest task (i.e. when running bundle exec rake minitest).
lib/tasks/factories_first.rake
MiniTest::Rails::Testing.default_tasks.unshift('aaa_factories_tests') if Rails.env =~ /^(development|test)\z/
Note that the above condition avoids erroneously referencing Minitest in environments where it is unavailable (I have confined minitest-rails to :test and :development groups in Gemfile). Without this if-condition, pushing to Heroku (for example to staging or production) will result in uninitialized constant MiniTest.
Of course I am also able to run the factories test directly:
bundle exec ruby -I test test/aaa_factories_tests/factories_test.rb
Here is a solution for MiniTest without the spec framework:
test/factories_test.rb
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
class FactoriesTest < ActiveSupport::TestCase
EXCEPTIONS = %w(griddler_email)
FactoryBot.factories.map(&:name).each do |factory_name|
next if factory_name.to_s.in?(EXCEPTIONS)
context "The #{factory_name} factory" do
should 'be valid' do
factory = build(factory_name)
assert_equal true, factory.valid?, factory.errors.full_messages
end
end
end
end
lib/tasks/factory.rake
namespace :test do
desc 'Test factories'
Rake::TestTask.new(:factories) do |t|
t.pattern = './test/factories_test.rb'
end
end
task minitest: 'test:factories'
The most important thing is to use taks minitest instead of task test if you want the factories tests to be run before other tests.

Resources