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

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

Related

Rails-How to use MiniTest's Teardown Method

I have been looking around the internet for a long, frustrating, while, and I'm still quite confused as to what the purpose of the teardown() method is in MiniTest and how it should be used.
The basic gist I have is that it is 1-run after each test, and 2-undoes things that were done during the test in order to allow future tests to run in a clean environment.
However, I am unclear on the nature of things it needs to undo: Does it need to empty the DB? Reset class variables? etc.
I am also unclear on whether the method is supposed to be explicitly filled out or not. I have found many examples where teardown() is completely left out of the example.
(My best guess is that there is a super-method teardown that runs automatically and takes care of certain things. That would explain why it is often left out, and would also explain why some things are reset in a given teardown() method and some aren't. But I still don't know which things are and which aren't.)
In short:
Does teardown need to be explicitly created? In what circumstances would it need to be overwritten and in which wouldn't it be?
The simplest answer is that you use #teardown in every test but you don't need to worry about it. Similar to the Rails lifecycle, there is a Minitest lifecycle. There are hooks to inject logic and behavior to be used by your tests. The main one in Rails tests is the database transaction. Each test that uses ActiveSupport::TestCase runs in a database transaction. The flow is like this:
Create the database transaction (Minitest::Test#setup)
Run your test method (MyTest#test_something)
Rollback the database transaction (Minitest::Test#teardown)
It is somewhat common for folks to use #setup to create objects for use in tests. After the test method completes the test object is garbage collected, so most folks don't use #teardown to clean up after the test. Because of this #teardown is typically a more advanced feature that you don't normally use when writing tests. I see it used much more often in testing libraries that enhance Minitest.
But there are times I do use #teardown in my tests. Here is an example of when I might use it.
require "minitest/autorun"
class Foo
def initialize namer
#namer = namer
end
def name
#namer.name
end
end
class FooTest < Minitest::Test
def setup
#namer_mock = Minitest::Mock.new
#namer_mock.expect :name, "foo"
#foo = Foo.new #namer_mock
end
def test_name
assert_equal "foo", #foo.name
end
def teardown
#namer_mock.verify
end
end

How to automatically skip callbacks in all unit tests but not in any integration tests

I use Rspec for testing under Rails 4.
I'd like to configure Rspec so that all my unit tests automatically run without callbacks, but all my integration tests run as Rails intended -- with all the same callbacks as you get in production and development.
Is this possible?
I can think of long-winded solution that involve writing conditional logic into my actual callbacks, but not elegant solutions that involve configuring Rspec.
You can replace your callback methods with test doubles when your unit tests run, as described in https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/message-expectations/allow-a-message-on-any-instance-of-a-class
For example, if you had the following class:
def Foo < ActiveRecord::Base
before_create :my_callback
...
end
you could stub the callback as follows:
allow_any_instance_of(Foo).to receive(:my_callback)

Helper functions in Rails unit tests

I'm using this sort of code in my code in my Unit tests.
test "should be awesome" do
assert true
end
I'm using FactoryGirl instead of fixtures.
I find that I'm repeating myself a lot and having helper functions would be quite useful. What's the best way to create and call a helper function in the unit test? Is there a before_filter available like it is in the controllers (I tried putting it in, but it's just an undefined method). Any help is appreciated!
You can add utility functions to your unit tests without a problem. As long as you don't call them name them like "test_something" they won't get run as unit tests. You can then call them from your actual unit test methods (the format you use boils down to having a method in the class anyway).
So:
test "should be awesome" do
assert_general_awesomeness
assert true
end
private
def assert_general_awesomeness
assert true
end
Utility methods that are going to be used all over the place can go in test_helper and they will be available to all your tests. You could alternatively have a module that you mix in to your tests to provide common utility methods.
If you are doing common calls to set up before a unit test you can put in in a setup method which will be called before each test in the class.

Rails testing with factories. Transactional uniqueness problem

I keep getting validation errors when running factories due to uniqueness constraints on fields. I am using shoulda with factory_girl. I have a both a unit test and a functional test creating 2 products in the database. I can run 'rake test:units' and 'rake test:functionals' over and over in any order and everything is will be green but when I run 'rake test' which runs the units followed by the functionals I get errors due to uniqueness.
I also tried creating models to break uniqueness in 2 different unit tests and I get the error then as well.
I have been playing with these settings in test_helper.rb but can't get anything to work
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
end
Does the transactional_fixtures setting take any effect of factories. Whats the best way to handle cleaning the database between tests?
(sigh..)
So the problem was that I was copying code from the shoulda docs and ended up declaring my test classes like so:
class UserTest < Test::Unit::TestCase
However for the transactional fixtures setting to have any effect you need to inherit from ActiveSupport::TestCase by declaring your classes
class UserTest < ActiveSupport::TestCase
Hopefully this can help save someone else some time.

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