NoMethodError <fixture name> in Rails and minitest/spec - ruby-on-rails-4

Without minitest/spec, the test looks like this, and the my_engine_customers fixtures are loaded (all is well):
my_engine/test/models/my_engine/customer_test.rb is
require 'test_helper'
module MyEngine
class CustomerTest < ActiveSupport::TestCase
test "alex is id 5" do
assert my_engine_customers(:alex).id, 5
end
end
end
After adding require 'minitest/autorun' to test/test_helper.rb, and then
converting the above test :
require 'test_helper'
describe MyEngine::Customer do
let(:alex) { my_engine_customers(:alex) } # error here (error shown below)
it "alex is id 5" do
assert alex.id, 5
end
end
I get this error:
NoMethodError: undefined method `my_engine_customers' for
#<#<Class:0x007fb63e8f09e8>:0x007fb63e81b068>
How do I access fixtures when using minitest/spec ?

When you use the spec DSL you get a Minitest::Spec object to run your tests. But the Rails fixtures and database transaction are only available in ActiveSupport::TestCase, or test classes that inherit from it like ActionController::TestCase. So what you need is some way for the spec DSL to use ActionSupport::TestCase for you tests.
There are two steps to this, first ActiveSupport::TestCase needs to support the spec DSL. You can do this by adding the following code to you test_helper.rb file:
class ActiveSupport::TestCase
# Add spec DSL
extend Minitest::Spec::DSL
end
(Did you know ActiveSupport::TestCase.describe exists? You probably want to remove that method before you add the spec DSL if you plan on doing nested describes.)
Second, you need to tell the spec DSL to use ActiveSupport::TestCase. The spec DSL adds register_spec_type for just this purpose. So also add the following to your test_helper.rb file:
class ActiveSupport::TestCase
# Use AS::TestCase for the base class when describing a model
register_spec_type(self) do |desc|
desc < ActiveRecord::Base if desc.is_a?(Class)
end
end
This will look at the subject of the describe and if it is an ActiveRecord model it will use ActiveSupport::TestCase instead of Minitest::Spec to run the tests.
As you might expect, there are lots of other gotchas involved when you try to use the spec DSL for controllers and other types of tests. The easiest way IMO is to add a dependency on minitest-rails and then require "minitest/rails" in your test_helper.rb file. minitest-rails does all this configuration and more and makes the process much smoother. (Again, IMO.)
For more info see my blaurgh post Adding Minitest Spec in Rails 4. </shameless-self-promotion>

Related

Rails minitest with namespaced fixtures

I have a namespaced model, namely Billing::Plan. So I put its fixture under test/fixtures/test/billing/plan.yml. (Actually, it was the rails generator to put it there, so I assumed it was a convention over configuration pleasantness :-))
Now, when I run a single test it works, but when I try to run all my test suite with rake test or guard the fixture loading fails with this error
ActiveRecord::StatementInvalid: ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "plans" does not exist
The important part is
ERROR: relation "plans" does not exist
It seems like the fixtures :all command in my test_helper.rb file fails to understand that the relation name is billing_plans instead of plans.
Why is that?
I figured it out looking at what fixtures :all does.
It needs a call to set_fixture_class in order to correctly assign the table name to a namespaced fixture.
So I solved my problem adding...
# test/test_helper.rb
module ActiveSupport
class TestCase
fixtures :all
set_fixture_class 'billing/plan' => Billing::Plan # <= ...this line!
end
end

How do I use a multi-word model name when using ember-cli?

I'm having trouble using multi-word model names in conjunction with ember-cli.
I'm getting the following warning:
WARNING: Encountered "phrase_token" in payload, but no model was found
for model name "phraseToken" (resolved model name using
DS.ActiveModelSerializer.typeForRoot("phrase_token"))
I'm doing my find as follows:
store.find('phrase-token', 123).then(function(m) { ... })
The JSON returned by my server uses the root phrase_token as I am using the ActiveModelAdapter.
One theory I have is that Ember-data is trying to use camelCase model names, but this isn't found by the ember-cli resolver that uses dasherized names.
I also tried the following:
store.find('phraseToken', 123).then(function(m) { ... })
but that fails saying there's no such model.
Update:
I noticed that this only happens in unit tests. I realize in my question I failed to mention that I ran into this problem when testing. In my full application, I don't actually have the problem at all.
I declare my test module as follows:
moduleForModel 'phrase-token', 'PhraseToken', {
# Specify the other units that are required for this test.
needs: ['adapter:application', 'serializer:application']
}
I think it comes down to the difference that in my full application (with a fully populated container, etc.) I can do the following:
!!store.modelFactoryFor('phrase-token') # true
!!store.modelFactoryFor('phraseToken') # true
but in my unit test:
!!store.modelFactoryFor('phrase-token') # true
!!store.modelFactoryFor('phraseToken') # false
Update 2:
I have found that performing the following in my setup code for my unit tests solves the problem:
container.normalizeFullName = function(fullName) {
fullName.dasherize()
});
But it feels like this shouldn't necessary, so I'm holding out for a different answer.
Update 3:
I posted an issue about this and the 0.2.0 release of ember-qunit has fixed the problem.
You should simply always use the dasherized name when you reference the model in your code - just like you name your files, everything else is deprecated to my knowledge. That doesn't affect your JSON payload though.

Ruby on Rails Rake throwing "Incorrect table name" error after updating rails project from 4.1.9 to 4.2.0

I have been working on a project for the last couple months, which was originally developed in 4.1.6 and I am now trying to update it to 4.2.0 (I have incrementally tested all version between 4.1.6 and 4.2.0, and all of the 4.1.x version work without error, and it is only when I go to 4.2.0 that I see the issue I describe here).
In this application, there is a lot of shared functionality that is common to ALL models, so I have created an abstract class, and all of my models inherit from that this class.
class TrackableModel < ActiveRecord::Base
self.abstract_class = true
...
end
class User < TrackableModel
...
end
The only change in the Gemfile was changing gem 'rails', '4.1.6' to gem 'rails', '4.2.0'
The update process was following the instructions HERE using rake rails:update and followed it up with the upgrade steps found in section 2 of the same document.
I overwrote all of the conflicting files with the defaults for this rake task, but reviewed each afterwards and worked in my modifications.
Before the update, all tests pass, but after updating
130 runs, 0 assertions, 0 failures, 130 errors, 0 skips
with the error
ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect table name '': SHOW FULL FIELDS FROM ``
Error:
xxxTest#test_yyy:
NoMethodError: undefined method `each' for nil:NilClass
The application seems to work without any changes to the user experience. Everything looks good until I try to execute the tests.
I just can't get my tests to run.
Update:
I forgot to mention that I am running
ruby 2.1.5p273 (2014-11-13 revision 48405) [i386-mingw32].
Additionally, I have been working to follow the execution path. It seems to be failing while it is trying to setup the fixtures. It is going through a loop where it is building the schema_cache of tables. It queries the schema_migrations and my first custom table "customers" (during this call it iterates over each of the columns on this table which appears to be successful).
On the next call to
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.columns(table_name#String)
table_name's value is nil
Unfortunately I am still new enough to ruby/rails that I am having difficulties finding where the table_name values (schema_migrations, customers, nil, ...) is actually being set.
Can someone help point in in the direction of where the list of tables is coming from that is building the schema_cache?
I encountered the same issue and was able to resolve it. In my case, the base class that inherited from ActiveRecord included a belongs_to :foo statement. I moved that out to the sub-classes of the base class and the fixtures loaded.
So, here is an example:
class BaseAwesomeModel < ActiveRecord::Base
self.abstract_class = true
# This is what was causing the issue, moved to subclasses
# belongs_to :something
end
class AnotherModel < BaseAwesomeModel
belongs_to :something
end
class YetAnotherModel < BaseAwesomeModel
belongs_to :something
end
I'm not sure if this is what is causing your fixtures to fail to load, but it was the source of my issue.
Good luck!
Just a note for anyone else who comes across this issue and DOESN'T have a relationship defined in the base (abstract) class:
Scopes can also cause this issue with abstract classes (in the same way that belongs_to did for a previous answerer), but apparently if you move them to a class method it works:
Change:
scope :scope_name, -> { #code }
To:
def self.scope_name
#code
end
My problem was actually caused by something entirely different though. I was previously using the foreigner gem and it has definitions that can look like this in the migrations:
change_table :table_name do |t|
t.remove_foreign_key :column_name
end
If you move these to the new internalized rails syntax for foreign keys it works:
remove_foreign_key :table_name, :column_name

Calling spec_helper file

I'm new in rspec test. My spec directory contain various subfolders: controllers, models, views, requests, helpers(all helper file located here) etc. So if I want to call(require) /helpers/crud_helper_spec.rb from /controllers/crud_contrller_spec.rb. What should I do?
Any helpers you write you can put in spec/support, like your CRUD helper in spec/support/crud_helper.rb:
module CrudHelper
# Fancy helpers here
end
Your spec/spec_helper is probably already configured to require these files. To use the helpers in a controller spec, do the following
describe PostsController do
include CrudHelper
it { fancy_helper(:index) }
end

Custom test suite for django app

I have a pretty complex django app which has following structure.
/myapp
/myapp/obj1/..
/myapp/obj1/views.py
/myapp/obj1/forms.py
/myapp/obj2/..
/myapp/obj2/views.py
/myapp/obj2/forms.py
/myapp/tests/..
/myapp/tests/__init__.py
/myapp/tests/test_obj1.py
/myapp/tests/test_obj2.py
I have a lot more objects. In /myapp/tests/__init__.py I import TestCase instances from test_obj1.py and test_obj2.py and it is enough to run all available test.
What I'm trying to do is to create a custom test suite. According to the documentation:
There is a second way to define the test suite for a module: if you
define a function called suite() in either models.py or tests.py, the
Django test runner will use that function to construct the test suite
for that module. This follows the suggested organization for unit
tests. See the Python documentation for more details on how to
construct a complex test suite.
So, i've created this function like this:
def suite():
suite = unittest.TestSuite()
suite.addTest(TestObj1Form())
suite.addTest(TestObj2Form())
return suite
However, when I run tests I get this error: ValueError: no such test method in <class 'myproject.myapp.tests.test_obj1.TestObj1Form'>: runTest. Of course I can define this method, but then if I run test it will invoke only this method and ignore all of the test* methods.
Any suggestions how to create a custom test suite for django app properly? I've googled and I found nothing about that.
You should add all your tests with a special function:
suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestObj1Form))