Michael Anhari
TDD in Rails 5 - Model Testing
- rails
- testing
This post is part of a series about test-driven development in Rails
- System testing
- Integration testing
- Model testing
Today we're going to tackle the center of our outside-in testing approach with
Rails 5 by adding some validations to our Article
model.
Model testing is a form of unit testing, which is used to test a single unit of our application. It's a good place to test your validations, scopes, and any instance methods you add to your model.
In more complex applications, model tests can reveal coupling in your application when you start having to instantiate or mocking objects just to test the model in consideration.
Our model test
I think requiring a title
and body
for each article is a reasonable
requirement.
Let's start with a test that ensures an article without a title
isn't
considered valid by Rails.
Our model test should already exist when we used our rails generator:
# test/models/article_test.rb
require 'test_helper'
class ArticleTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
Let's replace the commented out example with our test for the title
field:
# test/models/article_test.rb
require 'test_helper'
class ArticleTest < ActiveSupport::TestCase
test "the title field is required" do
article = Article.new(title: nil, body: "I love pajamas")
refute article.valid?
end
end
This is the first time we've seen refute
instead of assert
. This is
checking to make sure the valid is false
(or nil
). You can also use the
assert_not
assertion if that reads better to you.
Let's run our test:
$ bin/rails test test/models/article_test.rb
Failure:
ArticleTest#test_the_title_field_is_required: Expected true to not be truthy.
This failure is telling us what we want. It's telling us to implement a
validation for the title
field. Let's implement that on our Article
model:
# app/models/article.rb
class Article < ApplicationRecord
validates :title, presence: true
end
$ bin/rails test test/models/article_test.rb
Finished in 0.044457s, 22.4936 runs/s, 22.4936 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
Perfect! We can duplicate the test / validation for the body
field as well.
Our new test:
# test/models/article_test.rb
require 'test_helper'
class ArticleTest < ActiveSupport::TestCase
test "the title field is required" do
article = Article.new(title: nil, body: "I love pajamas")
refute article.valid?
end
test "the body field is required" do
article = Article.new(title: "Pajamas: How I Feel About Them", body: "")
refute article.valid?
end
end
$ bin/rails test test/models/article_test.rb
Failure:
ArticleTest#test_the_body_field_is_required: Expected true to not be truthy.
Adding our validation:
# app/models/article.rb
class Article < ApplicationRecord
validates :title, presence: true
validates :body, presence: true
end
$ bin/rails test test/models/article_test.rb
..
Finished in 0.027840s, 71.8391 runs/s, 71.8391 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
Wrap up
That pretty much does it for this series for now! I hope you enjoyed this series. A lot of what I covered is also covered in the Rails guides testing page, but I wanted to go step by step through the failures and build the application in this series. I do encourage you to read that page as well because I could not cover everything in this series.
If there's anything else you'd like to see covered on this blog, feel free to tweet me @michaelanhari.
Cheers friend.