Code Monkey home page Code Monkey logo

rails-4-1-rspec-3-0's People

Contributors

ruralocity avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rails-4-1-rspec-3-0's Issues

Ch 3 Testing for Failures

You're saying “We’re testing not just for ideal results–the user selects a letter with results–but also for letters with no results.”, but this test is the really the same as the first test. There are results if you pass in 'J'.

I think you should change the letter being passed in to something like 'M' so there are no matching results. Maybe even change the expectation to something like:

expect(Contact.by_letter('K')).to be_empty

Ch.9 Specify bin/xxx or bundle exec xxx

Naked command might execute unexpected version, so I think you should specify bin/xxx or bundle exec xxx .

For example:

  • guard init rspec => bundle exec guard init rspec
  • Run guard => Run bundle exec guard
  • spring binstub rspec = > bundle exec spring binstub rspec
  • spring stop => bin/spring stop
  • rspec --tag focus => bin/rspec --tag focus

But I am not fully confident about which to use. Probably I am misunderstaindig. Please review and investigate by yourself.

Ch 3. rspec and bin/rspec are not always interchangeable

In chapter 3, you wrote "We'll fill in the details in a moment, but if we ran the specs right now from the command line (by typing bin/rspec or just rspec on the command line) the output would be similar to the following:" However bin/rspec and rspec are not always interchangeable. (bin/rspec and bundle exec rspec are usually interchangeable, I think.)

rbenv executes the latest version of RSpec in specific Ruby version. If it differs the one in Gemfile.lock, you may not be able to run tests.

The following scenario shows such case (3.1.7 vs 3.0.0):

➜  cb git:(master) rspec -v
3.0.0
➜  cb git:(master) gem update rspec
Updating installed gems
Updating rspec-core
Fetching: rspec-support-3.1.2.gem (100%)
Successfully installed rspec-support-3.1.2
Fetching: rspec-core-3.1.7.gem (100%)
Successfully installed rspec-core-3.1.7
Updating rspec-expectations
Fetching: rspec-expectations-3.1.2.gem (100%)
Successfully installed rspec-expectations-3.1.2
Updating rspec-mocks
Fetching: rspec-mocks-3.1.3.gem (100%)
Successfully installed rspec-mocks-3.1.3
Updating rspec-rails
Fetching: rspec-rails-3.1.0.gem (100%)
Successfully installed rspec-rails-3.1.0
Updating spring-commands-rspec
Fetching: spring-commands-rspec-1.0.4.gem (100%)
Successfully installed spring-commands-rspec-1.0.4
Gems updated: rspec-core rspec-support rspec-expectations rspec-mocks rspec-rails spring-commands-rspec
➜  cb git:(master) rspec -v
3.1.7
➜  cb git:(master) bin/rspec -v
3.0.0
➜  cb git:(master) bundle exec rspec -v
3.0.0
➜  cb git:(master) rspec
/Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/bundler-1.7.6/lib/bundler/runtime.rb:34:in `block in setup': You have already activated rspec-support 3.1.2, but your Gemfile requires rspec-support 3.0.0. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/bundler-1.7.6/lib/bundler/runtime.rb:19:in `setup'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/bundler-1.7.6/lib/bundler.rb:121:in `setup'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/bundler-1.7.6/lib/bundler/setup.rb:7:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:135:in `require'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:135:in `rescue in require'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:144:in `require'
    from /Users/jit/dev/private/cb/config/boot.rb:4:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/dev/private/cb/config/application.rb:1:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/dev/private/cb/config/environment.rb:2:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/dev/private/cb/spec/spec_helper.rb:3:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/jit/dev/private/cb/spec/features/admin_spec.rb:2:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/configuration.rb:1105:in `load'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/configuration.rb:1105:in `block in load_spec_files'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/configuration.rb:1105:in `each'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/configuration.rb:1105:in `load_spec_files'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/runner.rb:96:in `setup'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/runner.rb:84:in `run'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/runner.rb:69:in `run'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/lib/rspec/core/runner.rb:37:in `invoke'
    from /Users/jit/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/rspec-core-3.1.7/exe/rspec:4:in `<top (required)>'
    from /Users/jit/.rbenv/versions/2.1.4/bin/rspec:23:in `load'
    from /Users/jit/.rbenv/versions/2.1.4/bin/rspec:23:in `<main>'
➜  cb git:(master) bin/rspec
......

Finished in 0.62278 seconds (files took 0.39209 seconds to load)
6 examples, 0 failures

Randomized with seed 63723

➜  cb git:(master) bin/rspec -v
3.0.0
➜  cb git:(master) be rspec
......

Finished in 0.62967 seconds (files took 2.6 seconds to load)
6 examples, 0 failures

Randomized with seed 49959

Problems with using Capybara

Hello.

First I want to say "Thank you!!!" for creating this book!!! I will recommend this book for the Thinkful.com training site. I'm having problems with the Capybara testing. Rspec doesn't like when I type 'visit root_path'. When I create the Module, it still doesn't like the login aspect.

my github is https://github.com/vdogamer/rpsec1
(forgive my misspelling)

Ch.3 eq != eql

You wrote "RSpec requires eq or eql, not ==, to indicate an expectation of equality.". However, eq and eql are not interchangeable. This expression might lead misunderstanding. I think you don't have to mention eql here.

https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers

  it "is equal to a float of the same value" do
    expect(5).to eq(5.0)
  end

  it "is not equal to a float of the same value" do
    expect(5).not_to eql(5.0)
  end

Ch 11: Don't use binstub?

    $ rails g scaffold news_release title released_on:date body:text
    $ rake db:migrate

In chapter 11, the commands above could use binstub, like bin/rails or bin/rake. Don't you replace with them?

Ch 3: Spec code written as normal text

I found an example spec which is written in normal text, the code doesn't even contain line breaks so it's very hard to read
I found the issue existing in the PDF and mobi versions, so I assume it also exists in the epub version.
It's under the Testing Validations in chapter 3, highlighted in gray in the screenshot

screenshot

Ch 3: "RSpec prefers `eq` over `==`" is amiguous

You wrote "RSpec prefers eq over == to indicate an expectation of equality". I feel it is allowed to write as expect(x).to == y, but it isn't. I think you should explicitly explain "==" is not allowed.

Ch 2: Where do you test a specific view in chapter 12?

In chapter 2, you wrote "That said, there are times when it makes sense to test a specific view. See chapter 12 for more details.", but I could not understand what you mean. In chapter 12, I am not sure which one is written about view test.

Ch 10: Pass attributes to controller instead of model

In the code below, user: create(:user_with_avatar) should be user: attributes_for(:user_with_avatar), correct?

    it "uploads an avatar" do
      post :create, user: create(:user_with_avatar)
      expect(assigns(:user).avatar_file_name).to eq 'avatar.png'
    end

Ch.9 No "specify" code in the "it{} and specify{}" section

In the section titled "it{} and specify{}", there is no sample code using specify. (I requested to do so, though...)

It may be hard to understand "Read your specs aloud as you write them, and use the term that makes the most sense--there are not hard rules about when to use one or the other." too.

Ch.2 Use bin/rake db:create:all

In exercises in chapter 2, you wrote "if you haven’t already, with bundle exec rake db:create:all.", but it bin/rake would be better for this use case.

Ch 9: "specify { should ..." is not readable

In chapter 9, you wrote specify { should be_named 'John Doe' } but it is not readable. It would be better to write as it { is_expected.to be_named 'John Doe' }. Other sample codes like it { should ... } should be changed to it { is_expected.to ...} too, because you can write without "should" with RSpec 3.

Ch 3, spec_helper still exists

As you may be able to spot, we’re creating an outline of examples here to help us sort similar examples together. This makes for a more readable spec. Now let’s finish cleaning up our reorganized spec with the help of a before hook:

Sample code after the sentence above still require spec_helper. And I found some 'spec_helper's in other chapters. Please grep and fix them.

curly brackets not needed for FactoryGirl + Faker

When you introduce Faker on page 54 there is this code example:

FactoryGirl.define do 
  factory :contact do
    firstname { Faker::Name.first_name }
    lastname { Faker::Name.last_name }
    email { Faker::Internet.email }
  end 
end

but I think the curly brackets aren't needed.

Few questions regarding your approach

Hi Aaron, I've just finished to read your book and it was very useful to clarify some doubts I had on rails testing.

I have few remaining questions for you:

  • I see in the controller specs that you test that the values in the assigned variable are the correct ones. How do you proceed when the find method is more complex? For example User.search(various_params), you surely have it well tested in the model specs, so what do you check in the controller? That the search method is called and is passed the params? This in my opinion breaks the behaviour testing as it checks that a specific method is called with that exact params (-> fragile tests). But if you call the method and check the results you actually test it 2 times (in the controller and in the model)
  • You duplicated (using shared specs) the same specs for different roles (guest, user, admin), in theory it is a good thing to do (because you want to make sure that it works as expected for everyone), in your experience how much does it affect the time to run all specs? If many actions are shared I guess the times is 2 or 3 times what it'd have been without them
  • How much time do your tests take to run all specs (models, controllers, features)? And what do you consider "acceptable" and what too much?
  • I see you suggest shoulda, isn't a big duplication mirroring the real code? I mean, you have a spec that says that it { should validate_presence_of(:arms) }, and then in the model you have validates :arms, presence: true... I'm not 100% convinced about that test
  • I see below that Eric asked about background jobs, and you suggested to test them like you suggest testing rake tasks. What about testing that a job is actually scheduled during another action (in a model or controller)? Would you do something like expect(SomeJob).to receive(:perform_later) or is there a better approach?

Thank you!

Remove --warning option

In this repository .rspec file has --warnings option, but this is very noisy. When I git-cloned and ran RSpec, I was surprised at too many warnings. I guess beginners would be surprised too.

Spring is not used in binstubs.

In chapater 9, you introduced Guard + Spring, but in branches for chapter 9, 11 and master, bin/rspec does not use Spring. It is very confusing.

In addition, I think bin/rails and bin/rake should use Spring from the start, because this is Rails 4.1 application.

Phone class should have attribute other than phone.

Phone class has phone attribute. I think it could lead confusing.

E.g.

contact = Contact.find params[:id]
phones = contact.phones # Phone instances
phones = phones.map{|phone| phone.phone } # Phone attributes

It would be better if it has different attribute name. For example:

contact = Contact.find params[:id]
phones = contact.phones
phone_numbers = phones.map{|phone| phone.phone_number }

Ch 11: Generator config can be used to skip creating JS, SCSS and helper

You might know, but generator config can be used to skip creating JS, SCSS and helper:

    config.generators do |g|
      # ...     
      g.assets false
      g.helper false
      g.javascripts false
      g.stylesheets false
    end

However, this is technique about Rails, not RSpec, so I am not sure if it is worth mentioning.

Ch 9: skip is preferable to pending

As you know, pending behavior has been changed since RSpec 3. So the code below should use skip rather than pending in this context:

    it "loads a lot of data" do
      pending "no longer necessary"
      # your spec's code; it will not be run
    end

And I think it is worth mentioning about the difference between skip and pending.

Ch 3, 'bin/rspec' is better than 'rspec'

Now, if we run RSpec from the command line again (via rspec or bundle exec rspec, depending on whether you installed the rspec binstub in the previous chapter) we see one passing example!

In the sentence above, you wrote "via rspec or bundle exec rspec" but I think "via bin/rspec or bundle exec rspec" would be better because readers can easily understand they are using the installed binstub.

Ch 8. Selenium Error

I was getting the following error after adding js: true to features/user_spec.rb

Selenium::WebDriver::Error::JavascriptError: arguments[0] is undefined

I was running Firefox 35. The solution was to uninstall Firefox 35 and install Firefox 34 instead.
After that the specs were passing again. I'm not sure why it doesn't work with 35.

I found the solution on StackOverflow, which also suggests disabling automatic updates of Firefox, otherwise it will update to 35 and the spec may fail again.

http://stackoverflow.com/questions/28159499/seleniumwebdrivererrorjavascripterror-arguments0-is-undefined

Ch 4: Unnecessary block exists

Unnecessary block is used in phone attribute:

    FactoryGirl.define do
      factory :phone do
        association :contact
        phone { '123-555-1234' }

        factory :home_phone do
          phone_type 'home'
        end

        factory :work_phone do
          phone_type 'work'
        end

        factory :mobile_phone do
          phone_type 'mobile'
        end
      end
    end

How about using Poltergeist?

You are using selenium-webdriver, but I don't use Selenium-webdriver day-to-day development. Recently I use Poltergeist.

Selenium-webdriver takes active window, so I don't like it so much. I think using headless browsers like Poltergeist is more practical approach. Do you have any plans to switch JS driver?

Ch 3, worth mentioning about 'not_to' and 'to_not'

I found you use not_to instead of to_not from RSpec 3 edition and I am wondering why.

But anyway I think it is worth mentioning about not_to and to_not. Readers should know they can use both. If there is any rule to determine which to use, I would like to know it.

Ch 9 spec fails

spec/controllers/contacts_controller_spec.rb:199 fails with

Failures:

  1) ContactsController administrator access behaves like full access to contacts PATCH #update invalid attributes does not change the contact's attributes
     Failure/Error: expect(assigns(:contact).reload.attributes).to eq contact.attributes

       expected: {"id"=>2, "firstname"=>"Lawrence", "lastname"=>"Smith", "email"=>"[email protected]", "created_at"=>Thu, 08 Jan 2015 06:18:40 UTC +00:00, "updated_at"=>Thu, 08 Jan 2015 06:18:40 UTC +00:00, "hidden"=>false}
            got: {"id"=>2, "firstname"=>"Lawrence", "lastname"=>"Smith", "email"=>"[email protected]", "created_at"=>Thu, 08 Jan 2015 06:18:40 UTC +00:00, "updated_at"=>Thu, 08 Jan 2015 06:18:40 UTC +00:00, "hidden"=>false}

       (compared using ==)

       Diff:

     Shared Example Group: "full access to contacts" called from ./spec/controllers/contacts_controller_spec.rb:233
     # ./spec/controllers/contacts_controller_spec.rb:199:in `block (5 levels) in <top (required)>'
     # ./spec/rails_helper.rb:38:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:37:in `block (2 levels) in <top (required)>'

  2) ContactsController user access behaves like full access to contacts PATCH #update invalid attributes does not change the contact's attributes
     Failure/Error: expect(assigns(:contact).reload.attributes).to eq contact.attributes

       expected: {"id"=>2, "firstname"=>"Lawrence", "lastname"=>"Smith", "email"=>"[email protected]", "created_at"=>Thu, 08 Jan 2015 06:18:41 UTC +00:00, "updated_at"=>Thu, 08 Jan 2015 06:18:41 UTC +00:00, "hidden"=>false}
            got: {"id"=>2, "firstname"=>"Lawrence", "lastname"=>"Smith", "email"=>"[email protected]", "created_at"=>Thu, 08 Jan 2015 06:18:41 UTC +00:00, "updated_at"=>Thu, 08 Jan 2015 06:18:41 UTC +00:00, "hidden"=>false}

       (compared using ==)

       Diff:

     Shared Example Group: "full access to contacts" called from ./spec/controllers/contacts_controller_spec.rb:242
     # ./spec/controllers/contacts_controller_spec.rb:199:in `block (5 levels) in <top (required)>'
     # ./spec/rails_helper.rb:38:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:37:in `block (2 levels) in <top (required)>'

in branch https://github.com/everydayrails/rails-4-1-rspec-3-0/tree/09_speedup

Ch 11: title_with_date should be helper method

The implementation of title_with_date is view-specific, so it should be implemented as helper method rather than model instance method. And I18n.l is preferable to strftime for internationalization purpose. For example:

    module NewsReleasesHelper
      def title_with_date(news_release)
        "#{l news_release.released_on}: #{news_release.title}"
      end
    end

Other solution is using decorator gem like Draper. (It would be overkill here, though.)

Ch.7 shared_examples_for appears once

In chapter 7, you write shared_examples_for 'public access to contacts' do. I wonder why you use shared_examples_for instead of shared_examples. I think it should be shared_examples for consistency.

Ch 10: Test url rather than path

Your mailer spec has expect(mail.body.encoded).to match edit_friendship_path(user, friend) but mail message usually has url rather than path. So I feel expect(mail.body.encoded).to match edit_friendship_url(user, friend) is better. (edit_friendship_url includes edit_friendship_path, though.)

In addition, such a test case usually requires default_url_options in test.rb. Beginners might get in trouble (like I used to).

Automatically require rails_helper in all specs

Notice the require 'rails_helper' at the top, and get used to typing it–all of your specs will include this line moving forward.

I actually like to add --require rails_helper to a .rspec file in my project root. This has the effect that all my specs are automatically run with rails_helper pre-required. You can do this with other parameters you'd like to use when running rspec as well. My full .rspec file reads:

--color
--format documentation
--require rails_helper

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.