jlarks32
jlarks32

Reputation: 1021

Ruby on Rails Coursera Class Bug in Tests

I'm currently taking Coursera's free Ruby on Rails Introduction class. I'm working on the third assignment which contains creating a People class where you have some functionality like a search function.

I'm getting a weird error when I run rspec with their designed unit tests. I'm 99% sure the error is lying in the unit tests. Specifically, before I've even touched any files, I'm getting the following error:

        raise <<-EOS
        #{description} accessed in #{article} #{hook_expression} hook at:
          #{CallerFilter.first_non_rspec_line}

        `let` and `subject` declarations are not intended to be called
        in #{article} #{hook_expression} hook, as they exist to define state that
        is reset between each example, while #{hook_expression} exists to
        #{hook_intention}.
        EOS

      RuntimeError:
        let declaration `class` accessed in an `after(:context)` hook at:
          /Users/<username>/.rvm/gems/ruby-2.4.0/gems/rspec-core-3.7.1/exe/rspec:4:in `<top (required)>'

        `let` and `subject` declarations are not intended to be called
        in an `after(:context)` hook, as they exist to define state that
        is reset between each example, while `after(:context)` exists to
        cleanup state that is shared across examples in an example group.

For starters, I don't totally understand the syntax they're using to describe talking about their tests. Secondly, here is the raw testing file that the author's of the Coursera class wrote:

require 'rspec'
require 'rspec/its'
require_relative '../module2_lesson3_formative.rb'

describe "lesson3" do

  context "check results" do
    p1 = Person.new("Ivana", "Trump")
    p2 = Person.new("Eric", "Trump")
    p3 = Person.new("Melania", "Trump")
    p4 = Person.new("Marla", "Maples")

    it "unexpected search result" do
      expect(Person.search("Trump").size).to be == 3
    end
  end

  context "check instance properties" do
    subject(:john) { Person.new("Chris", "Christie") }

    it "missing first_name" do
      is_expected.to respond_to(:first_name)
    end

    it "missing last_name" do
      is_expected.to respond_to(:last_name)
    end

  end

  context "check class properties" do
    subject(:class) { Person }

    it "missing search" do
      is_expected.to respond_to(:search)
    end
  end
end

I am hoping that someone can explain to me the debugging information when I run rspec. I'm using RSpec 3.7 which I'm guessing is the problem, as indicated that it might be a versioning upgrade thing here. That would also explain the fact that the class's authors didn't intentionally push up bad code. What is the best way for me to fix this and why are lines like this:

subject(:john) { Person.new("Chris", "Christie") }

in bad form? Thanks so much! Really appreciate your time :)

Upvotes: 1

Views: 109

Answers (2)

Sebasti&#225;n Palma
Sebasti&#225;n Palma

Reputation: 33420

In order to change the subject class for your specs, then you can "redefine" subject per each of your examples, or as it's needed.

When trying to change the class of the spec subject, with let or subject, then you get the detailed error (warning) message:

let and subject declarations are not intended to be called in an after(:context) hook, as they exist to define state that is reset between each example

So you can't set explicitly the class of your subject, because it'll be resetted with each running example.

You can set your subject to be a Person object within the "check class properties" context by using just subject, this way is_expected will check in this object that responds to the class method search, like:

context "check class properties" do
  subject { Person }

  it 'missing search' do
    is_expected.to respond_to(:search)
  end
end

Upvotes: 1

jlarks32
jlarks32

Reputation: 1021

This seems to have resolved the problem that rspec was complaining about:

describe "lesson3" do

  subject { person } # ADDED THIS LINE
  context "check results" do
    p1 = Person.new("Ivana", "Trump")
    p2 = Person.new("Eric", "Trump")
    p3 = Person.new("Melania", "Trump")
    p4 = Person.new("Marla", "Maples")

    it "unexpected search result" do
      expect(Person.search("Trump").size).to be == 3
    end 
  end

  context "check instance properties" do
    let(:person) { Person.new("Chris", "Christie") } # CHANGED THIS LINE

    it "missing first_name" do
      is_expected.to respond_to(:first_name) 
    end 

    it "missing last_name" do
      is_expected.to respond_to(:last_name) 
    end 

  end

  context "check class properties" do
    let(:person) { Person } # CHANGED THIS LINE

    it "missing search" do
      is_expected.to respond_to(:search) 
    end 
  end
end

I still am not sure why, or what the difference is implying. I would love someone to explain it a little bit more in depth.

Upvotes: 1

Related Questions