Parallelize Rails Minitest - ruby-on-rails

I am experimenting with using minitests parallelize_me! function to run my tests in parallel. I am trying to get just two empty tests to pass:
class Example < ActiveSupport::TestCase
parallelize_me!
test 'create' do
p 'create'
end
test 'invalid' do
p 'invalid'
end
end
I've commented out all my fixtures and I'm only trying to run these two tests in parallel. It keeps throwing errors like this:
Error:
Example#test_invalid:
RuntimeError: Circular dependency detected while autoloading constant <ClassName>
The class name changes each time to a different class. I guess it's trying to load the app each time in parallel and getting confused or something. How can I use this feature? Are there some good resources available on the subject?
App is on ruby-2.4.0, Rails 5.0.1

Related

When I run a rails test can I make it display only the error message?

I am following along with the Ruby on Rails Tutorial by Michael Hartl and am up to the point of running tests. The test is a simple "supposed to fail" test shown here:
test "should get about" do
get static_pages_about_url
assert_response :success
end
with the error being simply that the about page, controller method, and route do not yet exist. However when I run the test I get a massive block of code which fills up my terminal. This is just a small sampling as an example of what i'm seeing.
E
Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x00007fe6682cc760 #_routes=nil, #NAME="test_should_get_about", #failures=[#<Minitest::UnexpectedError: Unexpected exception>], #assertions=0, #integration_session=#<#<Class:0x00007fe6685342c8>:0x00007fe66859fc58 #_routes=nil, #app=#<SampleApp::Application:0x000055d7735cea68 #_all_autoload_paths=["/home/clay/Programs/sample_app/app/channels", "/home/clay/Programs/sample_app/app/controllers", "/home/clay/Programs/sample_app/app/controllers/concerns", "/home/clay/Programs/sample_app/app/helpers", "/home/clay/Programs/sample_app/app/jobs", "/home/clay/Programs/sample_app/app/mailers", "/home/clay/Programs/sample_app/app/models", "/home/clay/Programs/sample_app/app/models/concerns"], #_all_load_paths=["/home/clay/Programs/sample_app/lib", "/home/clay/Programs/sample_app/vendor", "/home/clay/Programs/sample_app/app/channels", "/home/clay/Programs/sample_app/app/controllers", "/home/clay/Programs/sample_app/app/controllers/concerns", "/home/clay/Programs/sample_app/app/helpers", "/home/clay/Programs/sample_app/app/jobs", "/home/clay/Programs/sample_app/app/mailers", "/home/clay/Programs/sample_app/app/models", "/home/clay/Programs/sample_app/app/models/concerns"], #app=#<ActionDispatch::HostAuthorization:0x000055d774009820 #app=#<Rack::Sendfile:0x000055d774009988 #app=#<ActionDispatch::Static:0x000055d773fe4f98 #app=#<ActionDispatch::Executor:0x000055d773fe5088 #app=#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000055d77382f4d8 #name="ActiveSupport::Cache::Strategy::LocalCache", #local_cache_key=:active_support_cache_null_store_local_cache_4420, #app=#<Rack::Runtime:0x000055d773fe51f0 #app=#<Rack::MethodOverride:0x000055d773fe5290 #app=#<ActionDispatch::RequestId:0x000055d773fe5330 #app=#<ActionDispatch::RemoteIp:0x000055d773fe5420 #app=#<Rails::Rack::Logger:0x000055d773fe54e8 #app=#<ActionDispatch::ShowExceptions:0x000055d773fe5588 #app=#<ActionDispatch::DebugExceptions:0x000055d773fe56c8 #app=#<ActionDispatch::ActionableExceptions:0x000055d773fe5790 #app=#<ActionDispatch::Reloader:0x000055d773fe58f8 #app=#<ActionDispatch::Callbacks:0x000055d773fe5998 #app=#<ActionDispatch::Cookies:0x000055d773fe5a38 #app=#<ActionDispatch::Session::CookieStore:0x000055d773fe5c68 #app=#<ActionDispatch::ContentSecurityPolicy::Middleware:0x000055d773fe5d58 #app=#<ActionDispatch::PermissionsPolicy::Middleware:0x000055d773fe5e20 #app=#<Rack::Head:0x000055d773fe5ec0 #app=#<Rack::ConditionalGet:0x000055d773fe5f60 #app=#<Rack::ETag:0x000055d773fe6050 #app=#<Rack::TempfileReaper:0x000055d773fe60f0
All I really need is the NameError: undefined local variable or method 'static_pages_about_url' and the location of the failing test right? Is this standard for failing tests in Ruby on Rails or is there a way to change how error messages are displayed from showing all of this less useful information?
In test driven development (TDD), you write the tests first. When you run them, all of them will be failing because you have not written the implementation yet (this is your "Red"). After that, you write the implementation that makes the tests pass (this is your "Green"). Once all tests are passsing, it comes the stage where you refactor the implementation (if required, this is your "Refactor"). Red, Green, Refactor.
In your particular example, you have written the test that checks if you can "GET" the about page but because you have not yet implemented the solution, your tests are failing.
In order to make the test pass, you'll need to add this to your route.rb file.
get 'static_pages/about'

Websockets flaky tests after upgrading to Rails 6

While upgrading a middle size app from Rails 5.1 to 6.0.2.2 (+ Ruby 2.6.1 -> 2.6.3) I start to get flaky tests in all kind of tests. 90% coverage, 500 hundreds tests, and between 0 to 8 tests failings, totally random. After a long bug hunt, I noticed that I got everything working with 100% confidence if I skip all Websocket related tests.
This is typically what I have to test and how I'm doing it (Minitest/Spec syntaxe):
class Api::PlayersControllerTest < ActionController::TestCase
before do
#user = users(:admin)
sign_in #user
end
it "broadcasts stop to user's player" do
put :update, format: :json, params: {id: #user.id}
assert_broadcast_on("PlayersChannel_#{#user.id}", action: "stop")
end
end
Notice that it's not an "integration test" because we're using a raw API call. What I have to check is: if some request is coming to some controller, ActionCable is broadcasting a Websocket message. That's why I have to use Devise sign_in helper in a controller Test.
ActionCable is backed by Redis, in all environments.
I do not use Parallel testing.
Dataset is using Fixtures, not factories.
use_transactional_tests is set to true
I have 23 tests like this one, and they all used to pass without any problem using Rails 5.1. Started one by one using a focus, they also all pass 100% both in Rails 5 or 6. The problem is when executing the whole test suite, I start to get flakiness in all sections (Unit/Models tests included), mostly related to dataset consistency. Actually, it looks like fixtures are not (or poorly) reloaded.
Any ideas? Is it something wrong with what I'm doing, or do you think it's a Rails 6 issue?
Ok, solved by adding Database Cleaner Gem. Pretty curious that it works using the same ":transaction" strategy that's in use with the Rails barebone fixture management... but anyway, it works!

RSpec Stubbing Java Static Method ArgumentError

I am attempting to stub a Java static method in my specs for my JRuby class which imports some Java libraries. I get the following error for the method call:
Failure/Error: JCoDestinationManager.getDestination('properties')
ArgumentError:
Wrong number of arguments. Expected 0, got 1.
That's the JCo Java static method. I created a small spec file to try and isolate the issue:
require 'rails_helper'
describe SapClient do
let(:destination) { double(Java::ComSapConnJcoRt::RfcDestination) }
before do
allow(JCoDestinationManager).to receive(:getDestination).and_return destination
end
it 'can be created' do
c = SapClient.new
expect(c).to_not be_nil
end
end
If I add the with clause like so, I still get the same result.
allow(JCoDestinationManager).to receive(:getDestination).with('properties').and_return destination
The strange part to me is that I only encounter this project in rails. If I copy the code over to a Sinatra project and run these specs there, all is well. I created a new Rails project and a new Sinatra project and installed the same versions of RSpec, verified RSpec mocks were the same version, etc. and still saw the discrepancy in behavior.
When I throw in a pry and observe what happens when I just call
JCoDestinationManager.getDestination
With no arguments, I get the mock destination that I define. If I comment out the allow statement, I see a real RfcDestination get created.
While searching, only thing I saw that seemed close to what I'm observing here is from https://github.com/rspec/rspec-mocks/issues/919 but apparently the solution to this problem was a jruby issue that has since been fixed.
Rails Gemfile
Rails Gemfile.lock
Sinatra Gemfile
Sinatra Gemfile.lock

main_app Namespace unknown in Rspec, only in unit suite tests (batch)

I have a helper class, ApplicationHelper, that has a method, build_links(). I have another class, AppleClass, that refers to that method.
AppleClass
def foo
....
build_links
end
end
ApplicationHelperClass
def build_links
main_app.blah_path(1)
end
end
The complication here is that there's an Engine, so I usually explicitly reference "main_app.blah_path" not just "blah_path".
The test against foo passes by itself, in its file, and when I run all helpers. It fails, though, when I include it in all the unit tests - "rake spec:suite:unit", and with our entire suite. All Apple tests pass, all ApplicationHelper tests pass. The only failing ones are when one method is referring to the other method, in routes, outside of the engine, in the full suite.
`undefined local variable or method `main_app' for #
<RSpec::Core::ExampleGroup::Nested_45::Nested_1:0x007fc134b30130>`
My suspicion is that the test helper, or some config, is not loading the engine's routes early enough, and thus links to "main_app" don't make sense. If I remove main_app, the test fails until it's run in the main suite.
Does anyone have tips on troubleshooting what's really going on? Also, could I kickstart the routing somehow in test_helper?
ruby-1.9.3-p385, rails 3.2.13, rspec 2.13.0
I had the same issue and found that if I added this method to the top of my Controller RSpec test case, then it resolved the issue entirely.
def main_app
Rails.application.class.routes.url_helpers
end
I think this issue is related to this question

Testing module without Rails

I've got some Rspec tests that I'm using to test a module. The module is used by a number of models in my Rails app. In order to keep testing time down to a minimum, I want to avoid loading Rails when testing my module.
The problem is that there are a few methods that contain rescues and those rescues mention the Rails debugger. When Rspec sees the capital 'r' in Rails, it has a bad time because it considers it an uninitialized constant.
I was hoping that if I wrapped up the logging info into its own method, I could avoid the problem. Here's what I came up with. But if I go down this road, I would need to stub either the rescue code or or the log_info method. Is that right? How would I do that? And which one should I stub?
def download_robots_file(page)
file = Net::HTTP.get(URI("#{page}robots.txt"))
rescue StandardError => ex
log_info('robot_file', ex)
end
....
private
def log_info(problem, exception_issue)
Rails.logger.debug("Couldn't download #{problem}: " + exception_issue.inspect)
end
You can add to stub chain method that you want to stub.
Rails.stub_chain(:logger).and_return(mocked_logger_instance)
Un-stub in the end with:
Rails.unstub(:logger)
All credits go to mister on following link How to rspec mock ruby rails logger class

Resources