2
\$\begingroup\$

In my journey of learning Rails, I'm wondering if I should test model validations. If so, is this a correct way to do it?

require 'test_helper'

class ShippingAddressTest < ActiveSupport::TestCase

  test "shipping addresses validations" do
    s = ShippingAddress.create
    assert_not s.valid?, "Address was valid without any data"
    assert s.errors.include? :name
    assert s.errors.include? :phone
    assert s.errors.include? :address
    assert s.errors.include? :user
    assert s.errors.include? :city

    s.name = "Some"
    s.phone = "8296964737"
    s.address = "Calle #1"
    s.user_id = 1

    # Test Inclusion of city
    s.city = "Santo"
    assert_not s.valid?, "Address was valid with incorrect city"

    s.city = "Santo Domingo"
    assert s.valid?, "Address not valid with everything filled"
  end

end

I just found out while reading Testing Rails guide about this:

3.3 What to Include in Your Unit Tests

Ideally, you would like to include a test for everything which could possibly break. It's a good practice to have at least one test for each of your validations and at least one test for every method in your model.

In this case, what would be the correct way to add a test for a single validation?

\$\endgroup\$
1
\$\begingroup\$

Unit tests

Unit tests should test the smallest behavior possible in each method of tests. Why ? Because when you make changes it helps determine what has break just by looking at failing tests.

3.3 What to Include in Your Unit Tests

Ideally, you would like to include a test for everything which could possibly break. It's a good practice to have at least one test for each of your validations and at least one test for every method in your model.

I added emphasis on something I find very important, you should test each validation on it's own. That way it's easier to see every rules your code have. By looking at your tests, I should easily see what your code is about and what I should expect to see.

When you want to comment, refactor

Most of time when you add a comment it's a sign that you should refactor (this is not an absolute rule, but it's apply in a lot of case).

# Test Inclusion of city
s.city = "Santo"
assert_not s.valid?, "Address was valid with incorrect city"

Do you see what you did there ? It's a test case inside your test. If you need to reuse some constant or variable in a test, there are ways to do this without being in the same method. You can setup data in a method and call it in your test methods to keep your code clean.

You should have :

  test "shipping addresses validations" do
    s = ShippingAddress.create
    assert_not s.valid?, "Address was valid without any data"
    assert s.errors.include? :name
    assert s.errors.include? :phone
    assert s.errors.include? :address
    assert s.errors.include? :user
    assert s.errors.include? :city   
  end

  test "inclusion of city" do
    s = ShippingAddress.create
    s.name = "Some"
    s.phone = "8296964737"
    s.address = "Calle #1"
    s.user_id = 1
    s.city = "Santo"
    assert_not s.valid?, "Address was valid with incorrect city"

  end

You should have a test for each validation of the fields of your class where only the one field is missing. That way if your validation on the name per example changed, then that tests failed. If you only do one tests with everything you may not be able to trap that one validation has been remove.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.