Testing Rails model validations - ruby-on-rails

There's many examples of testing RoR model validations. Even keeping the test being DRY across multiple models. But isn't it testing Rails which is already tested?
#user = User.make
#user.name = nil
#user.should_not be_valid
Isn't it testing if Rails validations work?

Isn't it testing if Rails validations work?
The point is that it tests that your model validates the presence of name. The fact that it also in effect tests that the Rails validation works, that Rspec works, that Ruby works, that your OS works, and that the rules of physics haven't suddenly changed, is beside the point.

The point is that you test that your model is using the validation. I agree with you, though, that your example tests the validation itself, and the test is also somewhat ambiguous.
If you are using the shoulda gem, you can simply use should validate_presence_of(:name).

Think of a method in your program where you have called update_attribute (update_attribute skips validation). Calling that method leaves the object in an invalid state, however the database still gets updated. Using valid?/invalid? can help you catch such cases.

Related

Stubbing with FactoryGirl, MiniTest, and Rails 4

I am a big fan of FactoryGirl, but have never understood the ".build_stubbed" method and would like to incorporate stubbing/mocking into my TDD. Can someone help me with the basics of what kind of stubbing I can do with FactoryGirl? Should I start using Mocha or another similar GEM to handle the mocking/stubbing or is any of this included in the Rails 4 default MiniTest?
The factory girl command build_stubbed means that the object is created (and also all its associated objects) but no objects are inserted into the database. You should use this if you want faster tests and do not need to have the objects in the database.
This means that the command does not have to do much with stubbing or mocking.
I myself have only experience with Mocha and can say that it very easy to use it for stubbing and mocking.
For stubbing out a command (e.g. of the object Person)
person = Person.new
person.stubs(:name).returns('Robert')
The obove example creates an instance of the person and stubbes out the method name to always return 'Robert'.
For mocking out the same command
person = Person.new
person.expects(:name).returns('Robert')
The above does the same as stubbing out the method. With the only difference that now the test fails if the method name is not called exactly once.

Factory Girl & Rails: can we turn off the database transactions that wrap each test?

I've got this issue with database locking when I'm testing some threading features I've got in my application--the database locks on one thread and then all the other threads deadlock on that. As there's no explicit transaction in my code I can't just guard and release manually.
I read somewhere that fixtures in TestCase leverage implicit (implicit to MY code) transactions to clean out the database between tests, but I can't find anywhere if this is true for Factory Girl as well.
Does anyone know if it is true and if so, is there a way to turn it off for specific tests, but not all of the tests?
thanks in advance!
FactoryGirl just takes your model, sets the attributes, and calls #save on that model. I think you just need to change a setting. With RSpec, you should have a line in your spec_helper.rb file:
config.use_transactional_fixtures = true
This config is sent to the Rails testing config. This is then used in the #setup_fixtures method.
The documentation on Rails transactional fixtures
HTH

Where to put common Unit Test code in ruby on rails environment?

Using Rails 3.0, I have a small bit of code that I seem to be calling in all my Unit tests.
Is there a common place to put shared unit test code that won't be incorporated into both unit and functional tests? I'd rather ONLY incorporate it into the needed files, just the unit tests.
I'm new to testing practices in general. Is it common in Rails to test validations (for example, test: validates_presence_of :name)? Most of my functions that test validations on a model are all basically the same (just swap in and out correct fixture and attribute name). Doesn't seem very DRY. Looking for a way to refactor.
Thanks.
You can place the code in the test/test_helper.rb file.
You should already find a code fragment that looks like this
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
end
If the code should be used in all your tests, you can add your methods in the ActiveSupport::TestCase class. Otherwise, wrap them into a Module and mix the module where required.
It's a good practice to test validations not to test the validation itself (the validates_presence_of macro is already tested in the Rails codebase), but to make sure chances in your code don't affect your class business.
For instance, there might be validation which needs to be triggered only in specific events. Or you might want to make sure no one removed your super-secret validation on that specific model.
If you want to test your model validations, I encourage you to check out shoulda. Shoulda provides several handy methods to test your validations.
class PostTest < ActiveSupport::TestCase
should belong_to(:user)
should validates_presence_of(:id)
end

factory_girl + rspec doesn't seem to roll back changes after each example

Similar to the problem described here:
http://rpheath.com/posts/411-how-to-use-factory-girl-with-rspec
in Short (shorten'd code):
spec_helper:
config.use_transactional_fixtures = true
config.use_instantiated_fixtures = false
factories.rb:
Factory.define :state do
f.name "NY"
end
in my spec
before(:each) do
#static_model = Factory(:state) # with validate uniqueness of state name
end
error:
duplicate entry name "NY" etc.
Question:
Shouldn't rspec clear database before each spec example and hence not throwing duplicate entry errors?
Things i think off:
do you use rake spec to run your testsuite: that builds up the database from scratch (to make sure nothing is sticking)
do you use, anywhere, a before (:all) ? Because whatever you create inside a before :all should be deleted again in a after :all or it keeps on existing.
Question: Shouldn't rspec clear database before each spec example and hence not throwing duplicate entry errors?
RSpec with DatabaseCleaner or RSpec Rails with use_transactional_fixtures will clear the DB as long as your created the data in the example itself. before :all do ... end is considered outside of the example, because the data remains untouched across multiple examples. Whatever you create in before :all you have to delete in after :all.
In order to delete whatever you create automatically use before :each do ... end. Be aware the same data will be created and removed 10 times if you have 10 examples. The difference between before :all and before :each is better explained here: rails rspec before all vs before each
Some more possible causes:
There's still a states.yml fixture sitting around
Someone played around on script/console test and forgot to clean up afterwards.
You might also find it's because you haven't wrapped the statement in:
describe "what it should do" do
#static_model = Factory(:state) # with validate uniqueness of state name
end
I discovered that was the change that solved this problem:
Why isn't factory_girl operating transactionally for me? - rows remain in database after tests
I have had similar questions about what sort of starting state one can expect when using FG and RSpec.
While I too wait for clarity, Database Cleaner could be a good fix: http://rubydoc.info/gems/database_cleaner/0.6.7/frames
hth -
Perry
When you use Factory(:state) wich is a shortcut to Factory.create(:state), factory_girl returns you a saved object.
Use Factory.build(:state) instead.
Dude maybe your yaml fixtures from regular unit tests get mixed into your rspec?

Should I write rails tests with the def or test keyword?

This seems like a simple question but I can't find the answer anywhere. I've noticed that in general, tests in a Ruby on Rails app can be written as:
test "the truth" do
assert true
end
or
def the_truth
assert true
end
It seems newer material writes tests the first way, but I can't seem to find a reason for this. Is one favored over the other? Is one more correct? Thanks.
There has been a shift in recent years from short, abbreviated test names to longer, sentence-like test names. This is partly due to the popularity of RSpec and the concept that tests are specs and should be descriptive.
If you prefer descriptive test names, I highly recommend going with the test method. I find it to be more readable.
test "should not be able to login with invalid password" do
#...
end
def_should_not_be_able_to_login_with_invalid_password
#...
end
Also, because the description is a string it can contain any characters. With def you are limited in which characters you can use.
I believe the first method was implemented starting with Rails 2.2.
As far as I am aware, it simply improves readability of your code (as def can be any function while test is used only in test cases).
Good luck!
As Mike Trpcic suggests you should check out RSpec and Cucumber. I'd like to add that you should also take a look at:
Shoulda (http://github.com/thoughtbot/shoulda/tree/master)
Factory Girl (http://github.com/thoughtbot/factory_girl/tree/master)
Shoulda is a macro framework for writing concise unit tests for your models/controllers, while the second is a replacement for fixtures.
I would suggest doing your testing with either RSpec or Cucumber. I use both to test all my applications. RSpec is used to test the models and controllers, and Cucumber tests the Views (via the included Webrat functionality).

Resources