Rails Tutorial: Odłączanie testu RSpec

Próbuję to zrobićĆwiczenie 2 rozdziału 8.5 u Michaela HartlaSamouczek Ruby on Rails. Ćwiczenie jest następujące:

Podążając za przykładem w Sekcji 8.3.3, przejrzyj specyfikacje użytkownika i żądania uwierzytelnienia (tj. Pliki znajdujące się obecnie w katalogu spec / requests) i zdefiniuj funkcje użytkowe w spec / support / utilities.rb, aby oddzielić testy od implementacji. Dodatkowy kredyt: Uporządkuj kod wsparcia w osobnych plikach i modułach, i zdobądź wszystko, aby poprawnie włączyć moduły do ​​pliku pomocnika specyfikacji.

Przykład 8.3.3: utilities.rb

include ApplicationHelper

def valid_signin(user)
  fill_in "Email",    with: user.email
  fill_in "Password", with: user.password
  click_button "Sign in"
end

RSpec::Matchers.define :have_error_message do |message|
  match do |page|
    page.should have_selector('div.alert.alert-error', text: message)
  end
end

Zdefiniowanevalid_signin(user) funkcja jest używana w następnym blokuauthentication_pages_spec.rb i działa dobrze.

describe "with valid information" do
    let(:user){FactoryGirl.create(:user)}
    before { valid_signin(user) }

    it { should have_selector('title', text: user.name) }
    it { should have_link('Profile', href: user_path(user)) }
    it { should have_link('Sign out', href: signout_path) }
    it { should_not have_link('Sign in', href: signin_path) }

    describe "followed by signout" do
        before { click_link "Sign out" }
        it { should have_link('Sign in') }
    end
end

W tym przykładzie przystąpiłem do tworzenia własnej nazwyvalid_signup(user):

def valid_signup(user)
    fill_in "Name",         with: user.name
    fill_in "Email",        with: user.email
    fill_in "Password",     with: user.password
    fill_in "Confirmation",         with: user.password_confirmation
end

Używam tego bloku wuser_pages_spec.rb lubię to:

describe "with valid information" do
  let(:user){FactoryGirl.create(:user)}
  before { valid_signup(user) }

  it "should create a user" do
    expect { click_button submit }.to change(User, :count).by(1)
  end

  describe "after saving the user" do
    before { click_button submit }
    let(:user) { User.find_by_email(user.email) }

    it { should have_selector('title', text: user.name) }
    it { should have_selector('div.alert.alert-success', text: 'Welcome') }
    it { should have_link('Sign out') }
  end
end

To nie działa. Spork / Guard zgłasza te błędy:

Failures:

  1) UserPages signup with valid information should create a user
     Failure/Error: expect { click_button submit }.to change(User, :count).by(1)
       count should have been changed by 1, but was changed by 0
     # ./spec/requests/user_pages_spec.rb:46:in `block (4 levels) in '

  2) UserPages signup with valid information after saving the user 
     Failure/Error: before { valid_signup(user) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./spec/support/utilities.rb:10:in `valid_signup'
     # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '

  3) UserPages signup with valid information after saving the user 
     Failure/Error: before { valid_signup(user) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./spec/support/utilities.rb:10:in `valid_signup'
     # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '

  4) UserPages signup with valid information after saving the user 
     Failure/Error: before { valid_signup(user) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./spec/support/utilities.rb:10:in `valid_signup'
     # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '

Błędy wydają się sugerować nazwę user.name w moimvalid_signup(user) funkcja wutilities.rb nie jest zdefiniowany, ale nie widzę powodu, dla którego. Ponownie uruchomiłem Guarda kilka razy i zrobiłemrake db:test:prepare aby upewnić się, że db (test postgresql) był w porządku.

Oto mojafactories.rb dla pełności:

FactoryGirl.define do
    factory :user do
        name    "Example User"
        email   "[email protected]"
        password    "foobar"
        password_confirmation   "foobar"
    end
end

Zanim spróbuję rozdzielić więcej pakietów testowych, bardzo chciałbym rozwiązać ten błąd i, co ważniejsze, zrozumieć jego przyczynę.

EDYTOWAĆ

Próbowałem swoich wskazówek i edytowałem funkcję wuser_pages_spec.rb następująco:

describe "with valid information" do
      before { valid_signup(user) }

      it "should create a user" do
        expect { click_button submit }.to change(User, :count).by(1)
      end

      describe "after saving the user" do
        before { click_button submit }
        let(:user) { User.find_by_email('[email protected]') }

        it { should have_selector('title', text: user.name) }
        it { should have_selector('div.alert.alert-success', text: 'Welcome') }
        it { should have_link('Sign out') }
      end
    end

Odkąd usunąłemlet(:user){FactoryGirl.create(:user)} z funkcji, którą zgadłem, nie było już użytkownika utworzonego w funkcji, więc musiałem zdefiniowaćvalid_signup(user) jako takie jakuser zmienna dlavalid_signup nie było już wypełniane przez FactoryGirl:

def valid_signup(user)
    fill_in "Name",     with: "Example User"
    fill_in "Email",    with: "[email protected]"
    fill_in "Password", with: "foobar"
    fill_in "Confirmation", with: "foobar"
end

To nie zadziałało i dało mi następujące błędy:

Failures:<p></p>

<p>1) UserPages signup with valid information should create a user
     Failure/Error: before { valid_signup(user) }
     NameError:
       undefined local variable or method <code>user' for #<RSpec::Core::ExampleGroup::Nested_5::Nested_3::Nested_2:0x007fdafc5088c0>
     # ./spec/requests/user_pages_spec.rb:42:in</code>block (4 levels) in '</p>

2) UserPages signup with valid information after saving the user Failure/Error: it { should have_selector('title', text: user.name) } NoMethodError: undefined method <code>name' for nil:NilClass # ./spec/requests/user_pages_spec.rb:52:in</code>block (5 levels) in '

I also tried running the test with valid_signup(user) the way I used to have it before (with user.name, user.email, user.password, user.password_confirmation, which didn't work either, with errors:

Failures:

  1) UserPages signup with valid information should create a user
     Failure/Error: before { valid_signup(user) }
     NameError:
       undefined local variable or method `user' for #
     # ./spec/requests/user_pages_spec.rb:42:in `block (4 levels) in '

  2) UserPages signup with valid information after saving the user 
     Failure/Error: it { should have_selector('title', text: user.name) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./spec/requests/user_pages_spec.rb:52:in `block (5 levels) in '

Next I tried running it without passing variables in user_pages_spec.rb: before { valid_signup() } and without a variable in the function in utilities.rb:

def valid_signup()
    fill_in "Name",     with: "Example User"
    fill_in "Email",    with: "[email protected]"
    fill_in "Password", with: "foobar"
    fill_in "Confirmation", with: "foobar"
end

This returned:

Failures:

  1) UserPages signup with valid information should create a user
     Failure/Error: before { valid_signup(user) }
     NameError:
       undefined local variable or method `user' for #
     # ./spec/requests/user_pages_spec.rb:42:in `block (4 levels) in '

  2) UserPages signup with valid information after saving the user 
     Failure/Error: it { should have_selector('title', text: user.name) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./spec/requests/user_pages_spec.rb:52:in `block (5 levels) in '

Still no closer to the answer. I might be overlooking something simple. No clue what though. I got what I first did wrong though: I just thought FactoryGirl was a way to create variables, and I didn't know it actually did something to my test database.

questionAnswers(4)

yourAnswerToTheQuestion