Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Why are my spec tests failing when they should be passing?

I started building my app using guard/minitest and then decided to switch over to rspec. I added rspec to my gemfile for test and development (below)

group :development, :test do 
    gem 'byebug'
    gem 'web-console'
    gem 'spring'
    gem 'annotate'
    gem 'rspec-rails'
end

group :test do
    gem 'minitest-reporters'
    gem 'mini_backtrace'
    gem 'guard-minitest'
end

I bundle installed and saw the new spec directory. But for some reason that I have not been able to figure out some tests are failing that should be passing.

Here's my user_spec.rb in spec/models/user_spec.rb

require 'rails_helper'

#RSpec.describe User, :type => :model do
#  pending "add some examples to (or delete) #{__FILE__}"
describe User do
  let(:valid_attributes) {
    {
      first_name: "Jacqueline",
      last_name: "Boltik",
      email: "jboltik@oolaabox.com",
      password: "password",
      password_confirmation: "password"
    }
  }
  context "validations" do
    let(:user) { User.new(valid_attributes) }

    before do
      User.create(valid_attributes)
    end

    it "requires an email" do 
      expect(user).to validate_presence_of(:email)
    end

    it "requires a unique email" do
      expect(user).to validate_uniqueness_of(:email)
    end

    it "requires a unique email (case insensitive)" do
      user.email = "JBOLTIK@OOLAABOX.COM"
      expect(user).to validate_uniqueness_of(:email)
    end

    it "requires the email address to look like an email" do
      user.email = "jboltik"
      expect(user).to_not be_valid
    end

  end

  describe "#downcase_email" do
    it "makes the email attribute lower case" do
      user = User.new(valid_attributes.merge(email: "JBOLTIK@OOLAABOX.COM"))
      expect{ user.downcase_email }.to change{ user.email }.
        from("JBOLTIK@OOLAABOX.COM").
        to("jboltik@oolaabox.com")
    end

    it "downcases an email before saving" do
      user = User.new(valid_attributes)
      user.email = "MIKE@TEAMTREEHOUSE.COM"
      expect(user.save).to be_true
      expect(user.email).to eq("mike@teamtreehouse.com")
    end
  end
end

And here's the model user.rb in app/models/user.rb

class User < ActiveRecord::Base
    has_secure_password
    validates :email, presence: true,
                    uniqueness: true,
                    format: {
                      with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/
                    }

    before_save :downcase_email

    def downcase_email
        self.email = email.downcase
    end
end

When I run the test $ rspec spec/models/user_spec.rb

it returns two passing tests and 4 failures. I copied the code directly from the exercise and I can't figure out why it's failing. I'm using Rails 4.1 Ruby 2.1 and Rspec 3.1

Thank you in advance for any help!

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Please copy the whole failing output from the console. It will tell us which lines in the tests are not passing and why.

5 Answers

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

It's only my preliminary theory but you might need the shoulda-matchers gem which gives you those validate_uniqueness_of tests.

The final test passed by changing

it "downcases an email before saving" do
      user = User.new(valid_attributes)
      user.email = "JBOLTIK@OOLAABOX.COM"
      expect(user.save).to be_true
      expect(user.email).to eq("jboltik@oolaabox.com")
    end

to

it "downcases an email before saving" do
      user = User.new(valid_attributes)
      user.email = "JBOLTIK@OOLAABOX.COM"
      expect(user.save).to be true
      expect(user.email).to eq("jboltik@oolaabox.com")
    end

Now everything passes :) Seems like a change in syntax with Rspec 3 was causing the issue.

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Glad this worked :). Yeah, RSpec 3 introduced some changes in the syntax. I used be_truthy in case of similar test.

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Although truthy will accept ANY value that is not nil or false, so it's not always preferable.

Janis Celms
Janis Celms
44,170 Points

Rspec 3 new syntax was failing me as well

Here's the entire console output. Thanks for your help!

$ rspec spec/models/user_spec.rb

WARNING: Nokogiri was built against LibXML version 2.9.2, but has dynamically loaded 2.9.0
FFF..F

Failures:

  1) User validations requires an email
     Failure/Error: expect(user).to validate_presence_of(:email)
     NoMethodError:
       undefined method `validate_presence_of' for #<RSpec::ExampleGroups::User::Validations:0x007fe14bd9d468>
     # ./spec/models/user_spec.rb:23:in `block (3 levels) in <top (required)>'

  2) User validations requires a unique email
     Failure/Error: expect(user).to validate_uniqueness_of(:email)
     NoMethodError:
       undefined method `validate_uniqueness_of' for #<RSpec::ExampleGroups::User::Validations:0x007fe150467c90>
     # ./spec/models/user_spec.rb:27:in `block (3 levels) in <top (required)>'

  3) User validations requires a unique email (case insensitive)
     Failure/Error: expect(user).to validate_uniqueness_of(:email)
     NoMethodError:
       undefined method `validate_uniqueness_of' for #<RSpec::ExampleGroups::User::Validations:0x007fe14a589d68>
     # ./spec/models/user_spec.rb:32:in `block (3 levels) in <top (required)>'

  4) User#downcase_email downcases an email before saving
     Failure/Error: expect(user.save).to be_true
       expected true to respond to `true?`
     # ./spec/models/user_spec.rb:53:in `block (3 levels) in <top (required)>'

Finished in 0.11439 seconds (files took 2.38 seconds to load)
6 examples, 4 failures

Failed examples:

rspec ./spec/models/user_spec.rb:22 # User validations requires an email
rspec ./spec/models/user_spec.rb:26 # User validations requires a unique email
rspec ./spec/models/user_spec.rb:30 # User validations requires a unique email (case insensitive)
rspec ./spec/models/user_spec.rb:50 # User#downcase_email downcases an email before saving

Great advice - I just installed the shoulda_matchers gem and now the tests pass all except 1. I followed the instructions to install shoulda_matchers here - in case anyone else is facing this same issue the instructions are very clear: https://github.com/thoughtbot/shoulda-matchers#rspec

After installing shoulda_matchers I retested and only got 1 failure.

$ rspec spec/models/user_spec.rb
WARNING: Nokogiri was built against LibXML version 2.9.2, but has dynamically loaded 2.9.0
.....F

Failures:

  1) User#downcase_email downcases an email before saving
     Failure/Error: expect(user.save).to be_true
       expected true to respond to `true?`
     # ./spec/models/user_spec.rb:53:in `block (3 levels) in <top (required)>'

Finished in 0.20742 seconds (files took 3.7 seconds to load)
6 examples, 1 failure

Failed examples:

rspec ./spec/models/user_spec.rb:50 # User#downcase_email downcases an email before saving

Thanks for posting your solution, Jacqueline! You helped me solve the same problem.