rspec3 validations test

59 views
Skip to first unread message

Roelof Wobben

unread,
Aug 10, 2014, 1:09:49 PM8/10/14
to rs...@googlegroups.com
Hello,

I read everywhere that I is not wise to use before

Now I wonder what is a good rspec3 way to test validations and later on test a inout of a form by using capybara/

I did google a lot but I could not find a good example.

Roelof

Aaron Kromer

unread,
Aug 10, 2014, 5:31:26 PM8/10/14
to rs...@googlegroups.com

That’s a few questions. Let me see if I can provide a little perspective on them. Note these are just my opinions and do not reflect any RSpec standard / best practice / recommendation / etc.

…is not wise to use before

This is largely a matter of opinion. Now, you may have come across something stating that before(:all) or it’s new more intent revealing alias before(:context) is not wise to use. In general, I agree with this view. This is only run once before the entire example group (context) it is defined in. There are rare cases where this is what you need, but generally, it’s not what you need. It usually leaks mutable state across specs, which can have very surprising and difficult to debug consequences. It also has many caveats regarding DB state, transactions, and other system level dependencies.

On the other hand, before(:each) or the new before(:example), which is the default if you just write before, it more acceptable to use. It is also normally what you want. It keeps state clean across specs, it hooks into transactions, rspec-mocks, etc. Unless you have a provable, with valid data showing it, case where this is detrimental to performance, it’s the proper choice.

Personally, I feel before and let should be used sparingly. They should be reserved for cases when you mean to state: “All of the following specs in this group really must have this setup action done before each of them.”

Note I wrote “setup action”. This does not apply to any action regarding the object under test. I personally believe those should not be put in any before block, but explicitly listed in the spec so that it is clear what you are testing, versus what is setting up the testing environment. Let me share a code sample explaining this view:

RSpec.describe Array, "list of elements" do
  describe "popping the array" do
    let(:element_list) do
      [:first, :second, :last]
    end

    # This is the same as before(:each) or before(:example)
    before do
      element_list.pop
    end

    # Note we are **cannot** use the same setup state since we need to capture
    # the value
    it "returns the last value of the array" do
      expect([:first, :second, :last].pop).to eq(:last)
    end

    # Note it's very unclear what the test is doing just by looking at it.  We
    # are describing an action on an Array instance. Yet, that isn't clear from
    # this spec at all, since all we see is that we check the array elements
    it "mutates the array removing the last element" do
      expect(element_list).to eq([:first, :second])
    end
  end
end

I’ve seen the above code “cleaned up” to be more expressive by converting it into something like:


RSpec.describe Array, "list of elements" do
  describe "popping the array" do
    let(:array_with_elements) do
      [:first, :second, :last]
    end

    # This is idiom is often viewed as an implicit `before`.
    #
    # Except, it's not. It's only run once you send the `element_list` message.
    # If you do this in the wrong spot then it may lead to surprising tests.
    #
    # This often leads people to use bang form `subject!`, which is
    # functionally the same as:
    #
    #   subject(:element_list) { ... }
    #   before { element_list }
    #
    # But this is often not the right tool and can have some surprising issues:
    # http://aaronkromer.com/blog/2013-05-19-the-bang-is-for-surprise.html
    #
    # Additionally, using `subject` here, IMO, is just wrong. The subject is
    # not the element returned from `#pop`. It's a specific instance of
    # `Array`. We are testing the behavior of `#pop`.
    subject(:popped_element) do
      array_with_elements.pop
    end

    # Looks clean, but is misleading as to what is actually the subject of the
    # spec. Here it's the popped element, but in reality, it's the return value
    # of calling the action `pop`.
    it "returns the last value of the array" do
      expect(popped_element).to eq(:last)
    end

    # This turns out to appear trickier to test. Often the initial pass looks
    # something like this:
    #
    #   expect(array_with_elements).to eq([:first, :second])
    #
    # That will fail though. Why? Because if we are not using the bang form of
    # `subject!`, a `before`, or something like `preload` (see blog link
    # above) then nothing is actually popped before this spec is run. Thus the
    # array is never mutated. Leaving `array_with_elements` unmodified.
    it "mutates the array removing the last element" do
      popped_element
      expect(array_with_elements).to eq([:first, :second])
    end
  end
end

I’ve also seen people go the following route, as well, it looks a bit cleaner:

# Looks cleaner using ivars. In general, I am not a fan of ivars and instead
# prefer to use local variables and message passing. This allows for clean
# extractions of ideas / concepts without modifying lots of code.
#
# For more details see this SO answer: http://stackoverflow.com/a/5359979/47438
RSpec.describe Array, "list of elements" do
  describe "popping the array" do
    before do
      @element_list = [:first, :second, :last]
      @popped_element = @element_list.pop
    end

    # Looks clean, but is misleading as to what is actually the subject of the
    # spec. Here it's the popped element, but in reality, it's the return value
    # of calling the action `pop`.
    it "returns the last value of the array" do
      expect(@popped_element).to eq(:last)
    end

    # Again, looks clean, but is misleading. Here we are actually looking at
    # the real object under test (the proper subject). But, it's already
    # mutated. We still have to hunt down that mutation.
    it "mutates the array removing the last element" do
      expect(@element_list).to eq([:first, :second])
    end
  end
end

Another large issue I have with the last form above is it completely hides the mutation and behavior being tested in the before block. Just looking at the before block, it’s not obvious what is setup and what is being tested. It isn’t until I’ve read all of the specs, or a large number of them, that things become clear to me.

This is why, I prefer a form more along the lines of:

RSpec.describe Array, "list of elements" do
  describe "popping the array" do
    subject(:element_list) do
      [:first, :second, :last]
    end

    it "returns the last value of the array" do
      expect(element_list.pop).to eq(:last)
    end

    it "mutates the array removing the last element" do
      expect{ element_list.pop }.to change{ element_list }
        .from([:first, :second, :last])
        .to([:first, :second])
    end
  end
end

To me this is cleaner, more explicit, and more obvious what is happening. But I’m just one person.

way to test validations

I would test them just as I would any side-effect based protocol:

RSpec.describe Admin, type: :model do
  describe "requires a name" do
    subject(:nameless_admin) do
      Admin.new(name: nil)
    end

    it "is not valid" do
      expect(nameless_admin.valid?).to be false
    end

    it "sets an error on the name attribute" do
      expect{ nameless_admin.valid? }
        .to change{ nameless_admin.errors[:name] }
        .from([])
        .to(include "can't be blank")
    end
  end
end

inout of a form by using capybara

This is a bit broader. In general, I simply go to the web page, fill in the form, then check the response. These are usually feature type acceptance specs. When I write these, I sometimes don’t adhere to the “one expectation per spec” guideline. This is because I am often testing a workflow, and I need to validate my expected assumptions along the path.

RSpec.describe "Signing up for the site", type: :feature do
  it "requires a name to be specified" do
    visit sign_up_url
    click_button "Sign Up"
    expect(current_url).to eq sign_up_url
    expect(page).to have_contenxt "Name can't be blank"
  end
end

Checkout the capybara readme (https://github.com/jnicklas/capybara) for more examples.


Happy testing!


Aaron



--
You received this message because you are subscribed to the Google Groups "rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rspec+un...@googlegroups.com.
To post to this group, send email to rs...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/5a32ddf8-f0fc-4bcd-80cd-555118b50ef1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Roelof Wobben

unread,
Aug 11, 2014, 2:45:30 AM8/11/14
to rs...@googlegroups.com
Thanks,

I asked this because I did the Hartl tutorial and he uses this :

describe User do

  before { @user = User.new(name: "Example User", email: "us...@example.com") }



and this :

before_save { self.email = email.downcase }

And from  googling I get the impression that this is not the right way so that is why I asked here. 

Roelof



Op zondag 10 augustus 2014 23:31:26 UTC+2 schreef Aaron Kromer:
<div title="MDH:VGhhdCdzIGEgZmV3IHF1ZXN0aW9ucy4gTGV0IG1lIHNlZSBpZiBJIGNhbiBwcm92aWRlIGEgbGl0 dGxlIHBlcnNwZWN0aXZlIG9uIHRoZW0uIF9Ob3RlIHRoZXNlIGFyZSBqdXN0IG15IG9waW5pb25z IGFuZCBkbyBub3QgcmVmbGVjdCBhbnkgUlNwZWMgc3RhbmRhcmQgLyBiZXN0IHByYWN0aWNlIC8g cmVjb21tZW5kYXRpb24gLyBldGMuXzxkaXY+PGJyPjwvZGl2PjxkaXY+Jmd0OyAuLi48c3BhbiBz dHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzcHg7Ij5p cyBub3Qgd2lzZSB0byB1c2UgYGJlZm9yZWA8L3NwYW4+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0i Zm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzcHg7Ij48YnI+PC9z cGFuPjwvZGl2PjxkaXY+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJp ZjsgZm9udC1zaXplOiAxM3B4OyI+VGhpcyBpcyBsYXJnZWx5IGEgbWF0dGVyIG9mIG9waW5pb24u Jm5ic3A7PC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7 IGZvbnQtc2l6ZTogMTNweDsiPk5vdywgeW91IG1heSBoYXZlIGNvbWUgYWNyb3NzIHNvbWV0aGlu ZyBzdGF0aW5nIHRoYXQgYGJlZm9yZSg6YWxsKWAgb3IgaXQncyBuZXcgbW9yZSBpbnRlbnQgcmV2 ZWFsaW5nIGFsaWFzIGBiZWZvcmUoOmNvbnRleHQpYCBpcyBub3Qgd2lzZSB0byB1c2UuIEluIGdl bmVyYWwsIEkgYWdyZWUgd2l0aCB0aGlzIHZpZXcuIFRoaXMgaXMgb25seSBydW4gb25jZSBiZWZv cmUgdGhlIGVudGlyZSBleGFtcGxlIGdyb3VwIChjb250ZXh0KSBpdCBpcyBkZWZpbmVkIGluLiBU aGVyZSBhcmUgcmFyZSBjYXNlcyB3aGVyZSB0aGlzIGlzIHdoYXQgeW91IG5lZWQsIGJ1dCBnZW5l cmFsbHksIGl0J3Mgbm90IHdoYXQgeW91IG5lZWQuIEl0IHVzdWFsbHkgbGVha3MgbXV0YWJsZSBz dGF0ZSBhY3Jvc3Mgc3BlY3MsIHdoaWNoIGNhbiBoYXZlIHZlcnkgc3VycHJpc2luZyBhbmQgZGlm ZmljdWx0IHRvIGRlYnVnIGNvbnNlcXVlbmNlcy4gSXQgYWxzbyBoYXMgbWFueSBjYXZlYXRzIHJl Z2FyZGluZyBEQiBzdGF0ZSwgdHJhbnNhY3Rpb25zLCBhbmQgb3RoZXIgc3lzdGVtIGxldmVsIGRl cGVuZGVuY2llcy48L3NwYW4+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFy aWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzcHg7Ij48YnI+PC9zcGFuPjwvZGl2PjxkaXY+ PGZvbnQgZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYiPk9uIHRoZSBvdGhlciBoYW5kLCBgYmVmb3Jl KDplYWNoKWAgb3IgdGhlIG5ldyBgYmVmb3JlKDpleGFtcGxlKWAsIHdoaWNoIGlzIHRoZSBkZWZh dWx0IGlmIHlvdSBqdXN0IHdyaXRlIGBiZWZvcmVgLCBpdCBtb3JlIGFjY2VwdGFibGUgdG8gdXNl LiBJdCBpcyBhbHNvIG5vcm1hbGx5IHdoYXQgeW91IHdhbnQuIEl0IGtlZXBzIHN0YXRlIGNsZWFu IGFjcm9zcyBzcGVjcywgaXQgaG9va3MgaW50byB0cmFuc2FjdGlvbnMsIHJzcGVjLW1vY2tzLCBl dGMuIFVubGVzcyB5b3UgaGF2ZSBhIHByb3ZhYmxlLCB3aXRoIHZhbGlkIGRhdGEgc2hvd2luZyBp dCwgY2FzZSB3aGVyZSB0aGlzIGlzJm5ic3A7ZGV0cmltZW50YWwmbmJzcDt0byBwZXJmb3JtYW5j ZSwgaXQncyB0aGUgcHJvcGVyIGNob2ljZS48L2ZvbnQ+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0i Zm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzcHg7Ij48YnI+PC9z cGFuPjwvZGl2PjxkaXY+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJp ZjsgZm9udC1zaXplOiAxM3B4OyI+UGVyc29uYWxseSwgSSBmZWVsIGBiZWZvcmVgIGFuZCBgbGV0 YCBzaG91bGQgYmUgdXNlZCBzcGFyaW5nbHkuIFRoZXkgc2hvdWxkIGJlIHJlc2VydmVkIGZvciBj YXNlcyB3aGVuIHlvdSBtZWFuIHRvIHN0YXRlOiBfIkFsbCBvZiB0aGUgZm9sbG93aW5nIHNwZWNz IGluIHRoaXMgZ3JvdXAgcmVhbGx5ICoqbXVzdCoqIGhhdmUgdGhpcyAqKnNldHVwIGFjdGlvbioq IGRvbmUgYmVmb3JlIGVhY2ggb2YgdGhlbS4iXzwvc3Bhbj48L2Rpdj48ZGl2PjxzcGFuIHN0eWxl PSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7IGZvbnQtc2l6ZTogMTNweDsiPjxicj48 L3NwYW4+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5zLXNl cmlmOyBmb250LXNpemU6IDEzcHg7Ij5Ob3RlIEkgd3JvdGUgInNldHVwIGFjdGlvbiIuIFRoaXMg ZG9lcyBub3QgYXBwbHkgdG8gYW55IGFjdGlvbiByZWdhcmRpbmcgdGhlIG9iamVjdCB1bmRlciB0 ZXN0LiBJIHBlcnNvbmFsbHkgYmVsaWV2ZSB0aG9zZSBzaG91bGQgbm90IGJlIHB1dCBpbiBhbnkg YGJlZm9yZWAgYmxvY2ssIGJ1dCBleHBsaWNpdGx5IGxpc3RlZCBpbiB0aGUgc3BlYyBzbyB0aGF0 IGl0IGlzIGNsZWFyIHdoYXQgeW91IGFyZSB0ZXN0aW5nLCB2ZXJzdXMgd2hhdCBpcyBzZXR0aW5n IHVwIHRoZSB0ZXN0aW5nIGVudmlyb25tZW50LiBMZXQgbWUgc2hhcmUgYSBjb2RlIHNhbXBsZSBl eHBsYWluaW5nIHRoaXMgdmlldzo8L3NwYW4+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0iZm9udC1m YW1pbHk6IGFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzcHg7Ij48YnI+PC9zcGFuPjwv ZGl2PjxkaXY+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsgZm9u dC1zaXplOiAxM3B4OyI+YGBgcnVieTwvc3Bhbj48L2Rpdj48ZGl2PjxkaXYgc3R5bGU9IiI+PGZv bnQgZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYiPlJTcGVjLmRlc2NyaWJlIEFycmF5LCAibGlzdCBv ZiBlbGVtZW50cyIgZG88L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlh bCwgc2Fucy1zZXJpZiI+Jm5ic3A7IGRlc2NyaWJlICJwb3BwaW5nIHRoZSBhcnJheSIgZG88L2Zv bnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5i c3A7ICZuYnNwOyBsZXQoOmVsZW1lbnRfbGlzdCkgZG88L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0i Ij48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5ic3A7ICZuYnNwOyAmbmJzcDsgWzpm aXJzdCwgOnNlY29uZCwgOmxhc3RdPC9mb250PjwvZGl2PjxkaXYgc3R5bGU9IiI+PGZvbnQgZmFj ZT0iYXJpYWwsIHNhbnMtc2VyaWYiPiZuYnNwOyAmbmJzcDsgZW5kPC9mb250PjwvZGl2PjxkaXYg c3R5bGU9IiI+PGZvbnQgZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYiPjxicj48L2ZvbnQ+PC9kaXY+ PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5ic3A7ICZuYnNw OyAjIFRoaXMgaXMgdGhlIHNhbWUgYXMgYmVmb3JlKDplYWNoKSBvciBiZWZvcmUoOmV4YW1wbGUp PC9mb250PjwvZGl2PjxkaXYgc3R5bGU9IiI+PGZvbnQgZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYi PiZuYnNwOyAmbmJzcDsgYmVmb3JlIGRvPC9mb250PjwvZGl2PjxkaXYgc3R5bGU9IiI+PGZvbnQg ZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYiPiZuYnNwOyAmbmJzcDsgJm5ic3A7IGVsZW1lbnRfbGlz dC5wb3A8L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1z ZXJpZiI+Jm5ic3A7ICZuYnNwOyBlbmQ8L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBm YWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+PGJyPjwvZm9udD48L2Rpdj48ZGl2IHN0eWxlPSIiPjxm b250IGZhY2U9ImFyaWFsLCBzYW5zLXNlcmlmIj4mbmJzcDsgJm5ic3A7ICMgTm90ZSB3ZSBhcmUg KipjYW5ub3QqKiB1c2UgdGhlIHNhbWUgc2V0dXAgc3RhdGUgc2luY2Ugd2UgbmVlZCB0byBjYXB0 dXJlPC9mb250PjwvZGl2PjxkaXYgc3R5bGU9IiI+PGZvbnQgZmFjZT0iYXJpYWwsIHNhbnMtc2Vy aWYiPiZuYnNwOyAmbmJzcDsgIyB0aGUgdmFsdWU8L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48 Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5ic3A7ICZuYnNwOyBpdCAicmV0dXJucyB0 aGUgbGFzdCB2YWx1ZSBvZiB0aGUgYXJyYXkiIGRvPC9mb250PjwvZGl2PjxkaXYgc3R5bGU9IiI+ PGZvbnQgZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYiPiZuYnNwOyAmbmJzcDsgJm5ic3A7IGV4cGVj dChbOmZpcnN0LCA6c2Vjb25kLCA6bGFzdF0ucG9wKS50byBlcSg6bGFzdCk8L2ZvbnQ+PC9kaXY+ PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5ic3A7ICZuYnNw OyBlbmQ8L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1z ZXJpZiI+PGJyPjwvZm9udD48L2Rpdj48ZGl2IHN0eWxlPSIiPjxmb250IGZhY2U9ImFyaWFsLCBz YW5zLXNlcmlmIj4mbmJzcDsgJm5ic3A7ICMgTm90ZSBpdCdzIHZlcnkgdW5jbGVhciB3aGF0IHRo ZSB0ZXN0IGlzIGRvaW5nIGp1c3QgYnkgbG9va2luZyBhdCBpdC4gJm5ic3A7V2U8L2ZvbnQ+PC9k aXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5ic3A7ICZu YnNwOyAjIGFyZSBkZXNjcmliaW5nIGFuIGFjdGlvbiBvbiBhbiBBcnJheSBpbnN0YW5jZS4gWWV0 LCB0aGF0IGlzbid0IGNsZWFyIGZyb208L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBm YWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5ic3A7ICZuYnNwOyAjIHRoaXMgc3BlYyBhdCBhbGws IHNpbmNlIGFsbCB3ZSBzZWUgaXMgdGhhdCB3ZSBjaGVjayB0aGUgYXJyYXkgZWxlbWVudHM8L2Zv bnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+Jm5i c3A7ICZuYnNwOyBpdCAibXV0YXRlcyB0aGUgYXJyYXkgcmVtb3ZpbmcgdGhlIGxhc3QgZWxlbWVu dCIgZG88L2ZvbnQ+PC9kaXY+PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1z ZXJpZiI+Jm5ic3A7ICZuYnNwOyAmbmJzcDsgZXhwZWN0KGVsZW1lbnRfbGlzdCkudG8gZXEoWzpm aXJzdCwgOnNlY29uZF0pPC9mb250PjwvZGl2PjxkaXYgc3R5bGU9IiI+PGZvbnQgZmFjZT0iYXJp YWwsIHNhbnMtc2VyaWYiPiZuYnNwOyAmbmJzcDsgZW5kPC9mb250PjwvZGl2PjxkaXYgc3R5bGU9 IiI+PGZvbnQgZmFjZT0iYXJpYWwsIHNhbnMtc2VyaWYiPiZuYnNwOyBlbmQ8L2ZvbnQ+PC9kaXY+ PGRpdiBzdHlsZT0iIj48Zm9udCBmYWNlPSJhcmlhbCwgc2Fucy1zZXJpZiI+ZW5kPC9mb250Pjwv ZGl2PjwvZGl2PjxkaXY+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJp ZjsgZm9udC1zaXplOiAxM3B4OyI+YGBgPC9zcGFuPjwvZGl2PjxkaXY+PHNwYW4gc3R5bGU9ImZv bnQtZmFtaWx5OiBhcmlhbCwgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAxM3B4OyI+PGJyPjwvc3Bh bj48L2Rpdj48ZGl2PjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7 IGZvbnQtc2l6ZTogMTNweDsiPkkndmUgc2VlbiB0aGUgYWJvdmUgY29kZSAiY2xlYW5lZCB1cCIg dG8gYmUgbW9yZSBleHByZXNzaXZlIGJ5IGNvbnZlcnRpbmcgaXQgaW50byBzb21ldGhpbmcgbGlr ZTo8L3NwYW4+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6IGFyaWFsLCBzYW5z LXNlcmlmOyBmb250LXNpemU6IDEzcHg7Ij48YnI+PC9zcGFuPjwvZGl2PjxkaXY+PGZvbnQgZmFj ZT0iYXJpYWwsIHNhbnMtc2VyaWYiPmBgYHJ1Ynk8L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNl PSJhcmlhbCwgc2Fucy1zZXJpZiI+PGRpdj5SU3BlYy5kZXNjcmliZSBBcnJheSwgImxpc3Qgb2Yg ZWxlbWVudHMiIGRvPC9kaXY+PGRpdj4mbmJzcDsgZGVzY3JpYmUgInBvcHBpbmcgdGhlIGFycmF5 IiBkbzwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyBsZXQoOmFycmF5X3dpdGhfZWxlbWVudHMpIGRv PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICZuYnNwOyBbOmZpcnN0LCA6c2Vjb25kLCA6bGFzdF08 L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgZW5kPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4mbmJz cDsgJm5ic3A7ICMgVGhpcyBpcyBpZGlvbSBpcyBvZnRlbiB2aWV3ZWQgYXMgYW4gaW1wbGljaXQg YGJlZm9yZWAuPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICM8L2Rpdj48ZGl2PiZuYnNwOyAmbmJz cDsgIyBFeGNlcHQsIGl0J3Mgbm90LiBJdCdzIG9ubHkgcnVuIG9uY2UgeW91IHNlbmQgdGhlIGBl bGVtZW50X2xpc3RgIG1lc3NhZ2UuPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICMgSWYgeW91IGRv IHRoaXMgaW4gdGhlIHdyb25nIHNwb3QgdGhlbiBpdCBtYXkgbGVhZCB0byBzdXJwcmlzaW5nIHRl c3RzLjwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyAjPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICMg VGhpcyBvZnRlbiBsZWFkcyBwZW9wbGUgdG8gdXNlIGJhbmcgZm9ybSBgc3ViamVjdCFgLCB3aGlj aCBpczwvZGl2Pjxka
...

Roelof Wobben

unread,
Aug 11, 2014, 7:35:24 AM8/11/14
to rs...@googlegroups.com
Hello Aaron,

I  see something strange in my test.

I have made this test-user.

subject(:short_admin) do
      Admin.new(name: "aaa")
end

which should fail because of this validation :

 validates :name , presence:true,
                    inclusion: { in: 5..10 }

it fails but I was expected another error message.
 Now I see this one: "Name is not included in the list"
where I expected to see something like this : too short. Name must exist between 5 and 10 characters.

Roelof


 




Op maandag 11 augustus 2014 08:45:30 UTC+2 schreef Roelof Wobben:

Jon Rowe

unread,
Aug 11, 2014, 7:54:28 AM8/11/14
to rs...@googlegroups.com
Hey Roelof

The Rails validation helper you’re using doesn’t work like that,
`inclusion:` specifies a list of values the field can be, so that error
message is actually correct.

You’re looking for the `length: { in: 5..10 }`

Cheers
Jon
--
You received this message because you are subscribed to the Google Groups "rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rspec+un...@googlegroups.com.
To post to this group, send email to rs...@googlegroups.com.

Roelof Wobben

unread,
Aug 11, 2014, 8:24:32 AM8/11/14
to rs...@googlegroups.com
Thanks,

I have my first test ready.
What do you experts think of it :

require 'rails_helper'
RSpec.describe Admin, type: :model do
 
  it { is_expected.to respond_to(:name) }
  it { is_expected.to respond_to(:password) }
  it { is_expected.not_to respond_to(:model) }
  it { is_expected.not_to respond_to(:compact, :flatten) }

 
  describe "requires a name" do
    subject(:nameless_admin) do
      Admin.new(name: nil)
    end
   
    it "is not valid" do
      expect(nameless_admin.valid?).to be false
    end
   
    it "sets an error on the name attribute" do
      expect{ nameless_admin.valid? }
        .to change{ nameless_admin.errors[:name] }
        .from([])
        .to(include "can't be blank")
    end
  end
   
  describe "admin has a too short name " do
    subject(:short_admin) do
      Admin.new(name: "aaa")
    end
   
    it "sets a error on to short names of the name attribute" do
       expect{ short_admin.valid? }
        .to change{ short_admin.errors[:name] }
        .from([])
        .to(include "is too short (minimum is 5 characters)")
    end
  end
  
  describe "admin has a too long name " do
    subject(:long_admin) do
      Admin.new(name: "aaaaaaaaaaaaaaa")
    end
    it "sets a error on to long names of the name attribute" do
       expect{ long_admin.valid? }
        .to change{ long_admin.errors[:name] }
        .from([])
        .to(include "is too long (maximum is 10 characters)")
    end
  end
   
end

Roelof


Op maandag 11 augustus 2014 13:54:28 UTC+2 schreef Jon Rowe:
...
Reply all
Reply to author
Forward
0 new messages