1

I found that SimpleCov always flags all standard (i.e. nothing fancy like custom method validations) validations in the model(s) to be "fully hit / tested". This confuses me as I would've thought that one should be writing tests to hit every (single) validation (if one was so minded) in the models - but no, with no (sensible) tests written, simplecov shows all model validations as tested.

I'm new to rails and testing so apologies if it's something very fundamental and obvious. I've spent like a day running around this issue, found a few interesting issues that have been resolved but still struggle to understand it.

Setup: default Rails 7.0.3, Ruby 3.0.3, program using rspec for testing & simplecov for coverage tracking. I've replicated this using a simple rails new project with the default devise user model where I've added title, first_nama, and last_name fields to the user model, and required the title field via a simple validation in the model.

# 20221102142351_add_name_to_users.rb
class AddNameToUsers < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :title, :string
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end

# user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :title, presence: true
end

Problem encountered: without writing a single line in the user_spec.rb file (i.e. with no tests), simplecov tells me that validates :title, presence: true has been hit. I know this is kinda of trivial here, but it's less trivial if one has several models and a lot of (standard) validations.

If you want to replicate this:

  1. Add rspec gem in testing & development and generate the user model spec file as per documentation
  2. Add the simplecov gem in testing as per documentation starting simplecov in the spec_helper.rb file - and don't forget the next point
  3. Hash out the capybara gem in testing (it causes an error as per below when running rspec spec)
An error occurred while loading ./spec/models/user_spec.rb. - Did you mean?
                    rspec ./spec/spec_helper.rb

Failure/Error: require_relative '../config/environment'

LoadError:
  cannot load such file -- addressable/uri

You can play around with the user model spec file, but irrespective of what you do, the validates :title, presence: true always lights as as "hit".

How does one / simplecov "know" when the (model) validations have "truly" been tested?

# user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  # pending "add some examples to (or delete) #{__FILE__}"

  describe "User validations" do
    it "should be valid for a user with all fields filled out" do
      @valid_user = User.new(email: "test@test.com", password: "testtest", title: "Mr", first_name: "Jack", last_name: "Sparrow")
      @valid_user.save
      expect(@valid_user.valid?).to be true
    end

    it "should be invalid for a user without a title" do
      @invalid_user = User.new(email: "test@test.com", password: "testtest", first_name: "Jack", last_name: "Sparrow")
      @invalid_user.save
      expect(@invalid_user.valid?).to be false
    end
  end
end

pandancode
  • 53
  • 5
  • 1
    *How does one / simplecov "know" when the (model) validations have "truly" been tested?* `simplecov` knows that this line has been executed as part of one or more of your tests, therefor it is theoretically "covered" as part of your testing suit. `simplecov` does not care if the test passes or fails because the result of the test has no impact on whether or not something was tested (called as part of the test suite). – engineersmnky Nov 02 '22 at 16:37
  • 1
    Technically speaking "coverage" is not bound to testing at all, it is simply the number of times a line or branch was executed. See [`Coverage`](https://ruby-doc.org/stdlib-3.1.2/libdoc/coverage/rdoc/Coverage.html) – engineersmnky Nov 02 '22 at 16:41
  • Oh, I appreciate that "coverage" being hit / not "tested" point. Alternatively, in the controllers, the test behave in a way that I can logically follow. We hit the methods, then it runs through all lines (apart from maybe those in if conditions - which you will have to hit multiple times). However, does this means that "testing" models is using rspec / simplecov...kind of pointless? – pandancode Nov 03 '22 at 11:48
  • No testing and code coverage are in no way pointless, on the contrary it is extremely important in my opinion to test, specifically testing the models (unit testing). This ensures that the code works the way it supposed to and when you make a change it still works (or the tests fail). It is still up to you to make sure that the tests are comprehensive enough and when you find an untested case that has negative impacts write a test and fix the problem so the test runs green. Code coverage helps ensure that when testing you are not missing lines that could have unexpected consequences. – engineersmnky Nov 03 '22 at 13:01

0 Answers0