Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numerical matchers #244

Closed

Conversation

HoneyryderChuck
Copy link

Correction to the previous pull request ( #236 ) which was breaking the ruby 1.8 tests

@drapergeek
Copy link
Contributor

@TiagoCardoso1983 Maybe I'm misunderstanding something here. In order for me to use this matcher do I have to actually set the attribute by hand?

@HoneyryderChuck
Copy link
Author

Well, yes, according to the AR, you say something like

validates :num, :numericality => {:greater_than => 5 }

and the spec should work accordingly

 should validate_numericality_of(:num).is_greater_than(5)  

@bryanrite
Copy link

👍

@mxie
Copy link
Contributor

mxie commented Apr 10, 2013

@TiagoCardoso1983 Yes, you are correct about that in a sense. However, I believe @drapergeek (and correct me if I'm wrong) is referring to the before blocks in the spec where you did:

before { subject.attr = 2 }

and the like. Our specs typically don't set attributes like that and test the matcher against those values. The specs should just verify that your matcher actually does the validate the way it's supposed to, e.g. that

validate_numericality_of(:attr).is_less_than_or_equal_to(4)

actually does exactly

validates_numericality_of :attr, :less_than_or_equal_to => 4

Check out spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb for reference.

@conradwt
Copy link

Has this issue been resolved? I ask the question because I'm still seeing the following message:

     Failure/Error: it { should validate_numericality_of(:attr).is_less_than_or_equal_to(4) }
     NoMethodError:
       undefined method `is_less_than_or_equal_to' for #<Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher:0x007fa896c72c70>

@mxie
Copy link
Contributor

mxie commented Apr 17, 2013

@conradwt We're still waiting for @TiagoCardoso1983 to fix the PR. This will be resolved when they do.

@HoneyryderChuck
Copy link
Author

Sorry for the lateness, was out of the internets for a while. I don't understand exactly the spec issue, but I tried to rewrite it in a more similar way to the other specs. If this doesn't solve the issue, please be more explicit in what it is wrong.

@drapergeek
Copy link
Contributor

@TiagoCardoso1983 I think you're still misunderstanding us. Having to set the attribute to a specific value in your test doesn't operate the way all our other tests work. The code should actually set this attribute without it having to happen in the test. The user shouldn't be responsible for that.

@HoneyryderChuck
Copy link
Author

Sorry, I'm really misunderstanding because I still don't see it. How should the spec look like then? I'm testing the matcher against all possible options already.

@conradwt
Copy link

Can someone send @TiagoCardoso1983 an example of one of the numeric matchers and the way it should be written as a spec? Another option would be for someone to pair with him to knock this out being that @TiagoCardoso1983 started this task.

@drapergeek
Copy link
Contributor

@TiagoCardoso1983
The fact that you have to set subject.attr = 1 in your tests is what concerns me. Given that case, if you were using the full method then your tests could not pass using this implementation:

 it { should validate_numericality_of(:age).greater_than(18) }

because you would have to set your subject to equal 18.

Does this make more sense? If you could write a spec that uses the full matcher I think you would understand why this is an issue.

…. hope this is more in sync with the other specs
@HoneyryderChuck
Copy link
Author

Again, sorry for the lateness. I perceived you had a problem with me explicitly assigning the attribute before the match, so I assumed you wanted a more idempotent way of instantiating objects. Please report back to me if this is still not in sync with what you want.

@fny
Copy link
Contributor

fny commented May 19, 2013

@TiagoCardoso1983

You're shouldn't define explicit numerical cases, but rather check that the correct validation is being implemented irrespective of the values involved.

Consider the shoulda's current test case for a validation requiring an odd number. It doesn't use any digits. Instead it creates a dummy model instance with the validation on the fly...

 def validating_numericality(options = {})
    define_model :example, :attr => :string do
      validates_numericality_of :attr, options
    end.new
  end

...and tests to check that the matcher exists:

    it 'allows odd number values for that attribute' do
      validating_numericality(:odd => true).should matcher.odd
    end

    it 'rejects when the model does not enforce odd number values' do
      validating_numericality.should_not matcher.odd
    end

@HoneyryderChuck
Copy link
Author

Just noticed I can't really call a should_not matcher on top of a numerical validation. This:

it { should_not validate_numericality_of(:attr)

breaks because some negative_failure_message is not defined. Doesn't have anything to do with the matchers I inserted. Should I open an issue on this?

@fny
Copy link
Contributor

fny commented May 19, 2013

I think you need a failure_message_for_should and a failure_message_for_should_not. Check out the only_integer_matcher as an example.

@HoneyryderChuck
Copy link
Author

Not on the version of the gem I'm working on, these methods do not exist.

@mxie
Copy link
Contributor

mxie commented May 20, 2013

@fny Thanks for your explanation! You're exactly right about what we're looking for in the specs.

@TiagoCardoso1983 The failure_message_for_should and failure_message_for_should_not methods were originally missing from the validate_numericality_ofmatcher, as well as from its submatchers. However, they should now be in place as of version 2.1.0. Try rebasing your branch and see if they appear now.

Tiago Cardoso added 3 commits May 20, 2013 13:56
Conflicts:
	lib/shoulda/matchers/active_model.rb
…here, also submatchers, returning usually the same result as the main matcher
@HoneyryderChuck
Copy link
Author

Is it now good to go?

module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind tightening up this whitespace a bit? Just remove the empty lines before and after the class comment and right before def initialize.

@mcmire
Copy link
Collaborator

mcmire commented May 21, 2013

@TiagoCardoso1983 I left a couple of comments.

You don't seem to have any opposite tests for the validation -- that is, what if you have a model that doesn't validate_numericality_of(:attr) and you attempt to validate_numericality_of(:attr).is_greater_than(2)?

What if you do this... have contexts for the different qualifiers (is_greater_than, is_less_than, etc.), and then inside of those contexts, test that instance_with_validation(:whatever => 2).should matcher.whatever(2) and instance_without_validations.should_not matcher.whatever(2).

Additionally, can you fold the subject into the test itself, and give a description to each test?

For instance you might have something like:

context 'is_greater_than' do
  it "accepts an instance with a validation" do
    instance_with_validation(:greater_than => 2).should matcher.is_greater_than(2)
  end

  it "rejects an instance without a validation" do
    instance_without_validations.should_not matcher.is_greater_than(2)
  end
end

I think if you do that we should be good to go.


def initialize(value, operator)
@value = value
@options = { :operator => operator }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to store this in @options? Can you not store this in simply @operator instead?

@HoneyryderChuck
Copy link
Author

@mcmire , I don't see the use case there. less_than and greater_than are options of the numericality validation, they should be preceded by a numericality validation, I guess.

@mcmire
Copy link
Collaborator

mcmire commented May 21, 2013

@TiagoCardoso1983 Right, I don't expect people to try to use is_greater_than, etc. when the model doesn't have a validation on it, but if you're writing test-first you expect such a test to fail and then you add the validation and then it should pass. That's the use case.

@mcmire
Copy link
Collaborator

mcmire commented May 21, 2013

@TiagoCardoso1983 Okay so I think we're almost ready to merge this. Do you mind squashing your commits as it makes sense and/or rebasing if necessary before I do so?

@HoneyryderChuck
Copy link
Author

Everything's up-to-date, no need to rebase. I didn't understand what you meant by "squashing commits", but I'd say it is good to go.

@drapergeek
Copy link
Contributor

@TiagoCardoso1983, as a rule when we're pulling in a feature, we 'squash' all the commits down into a singlle commit; @mcmire should be able to do this for you before he merges it in so its not a big deal. Thanks for putting this together!

@mcmire
Copy link
Collaborator

mcmire commented May 24, 2013

Merged!

@mcmire mcmire closed this May 24, 2013
mcmire added a commit that referenced this pull request May 24, 2013
@bdwain
Copy link

bdwain commented May 31, 2013

Is this in the current build (2.1.0) of the gem yet? Or not until 2.2.0? I installed 2.1.0 and get errors saying is_greater_than is not defined (and all of the other new matchers)

@fny
Copy link
Contributor

fny commented May 31, 2013

The current v2.1.0 release on Rubygems does not contain the comparison matchers. You'll have to install the gem directly from the repo for now.

# in your Gemfile
gem 'shoulda-matchers', github: 'thoughtbot/shoulda-matchers'

@bdwain
Copy link

bdwain commented May 31, 2013

That's what I figured. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants