Commits on Jan 7, 2016
  1. @bdmac @mcmire

    Numericality validation of virtual attributes

    Commit #18b2859d2522a4866c398b9a32ebc3de4ec79389 broke numericality
    validation of virtual attributes in ActiveRecord models. This commit
    added a `column_type` method that assumes if `columns_hash` is a thing
    then our attribute would be present within it. This is not true for
    virtual attributes and leads to:
    ```
         NoMethodError:
               undefined method `type' for nil:NilClass
             # /Users/bdmac/.gem/ruby/2.2.2/gems/shoulda-matchers-3.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb:442:in
             # `column_type'
    ```
    bdmac committed with mcmire Oct 28, 2015
  2. @mcmire

    Always use doc formatter for RSpec by default

    Prior to this commit we only told RSpec to use the doc formatter if we
    were running one test file. When a test file is being run using Zeus,
    `unit_spec_helper` (and thus `spec_helper`) are loaded ahead of time.
    This means that from RSpec's perspective, no files are being run, and so
    the documentation formatter is not chosen, which means that the default
    progress reporter is used.
    
    This guard was added primarily to ensure that when tests are run on CI,
    the progress reporter is used instead of the documentation formatter.
    This happens anyway, though, because we pass that manually to RSpec
    within the Rakefile. So we don't need this guard.
    mcmire committed Jan 7, 2016
Commits on Jan 6, 2016
  1. @mdeering @mcmire

    Do not apply .railsrc

    mdeering committed with mcmire Oct 25, 2015
  2. @mcmire

    Remove IneffectiveTestError

    Prior to this commit, the numericality matcher raised an
    IneffectiveTestError if used against a numeric column (unless other
    qualifiers were added). I had a misunderstanding of how the numericality
    validation works -- it turns out it doesn't work against the output of
    the attribute in question, it works against the input. So raising this
    exception is pointless and doesn't actually protect against anything.
    mcmire committed Jan 5, 2016
Commits on Jan 5, 2016
  1. @mcmire

    Enable ignoring_interference_by_writer by default

    Forcing people to add ignoring_interference_by_writer for each and every
    case in which an attribute changes incoming values is pretty obnoxious
    on our part (for instance, when using the numericality matcher against
    an integer column + `only_integer`). So now, it's enabled by default.
    This effectively means that people should never get
    AtttributeChangedValueErrors again.
    mcmire committed Jan 4, 2016
  2. @mcmire

    Add ignoring_interference_by_writer to all matchers

    `allow_value` matcher is, of course, concerned with setting values on a
    particular attribute on a particular record, and then checking that the
    record is valid after doing so. That comes with a caveat: if the
    attribute is overridden in such a way so that the same value going into
    the attribute isn't the same value coming out of it, then `allow_value`
    will balk -- it'll say, "I can't do that because that changes how I
    work."
    
    That's all well and good, but what the attribute intentionally changes
    incoming values? ActiveRecord's typecasting behavior, for instance,
    would trigger such an exception. What if the developer needs a way to
    get around this? This is where `ignoring_interference_by_writer` comes
    into play. You can tack it on to the end of the matcher, and you're free
    to go on your way.
    
    So, prior to this commit you could already apply it to `allow_value`,
    but now in this commit it also works on any other matcher.
    
    But, one little thing: sometimes using this qualifier isn't going to
    work. Perhaps you or something else actually *is* overriding the
    attribute to change incoming values in a specific way, and perhaps the
    value that comes out makes the record fail validation, and there's
    nothing you can do about it. So in this case, even if you're using
    `ignoring_interference_by_writer`, we want to inform you about what the
    attribute is doing -- what the input and output was. And so we do.
    mcmire committed Dec 30, 2015
  3. @mcmire

    allow_value: Fix compatibility with enum columns

    When used against an attribute that's an enum, `allow_value` will raise
    an AttributeValueChangedError. This commit prevents that from happening.
    mcmire committed Dec 30, 2015
  4. @mcmire

    Add ValidationMatcherScenario for use in tests

    Also add a helper method, `build_scenario_for_validation_matcher`, to
    all unit tests.
    
    Our plan is to slowly transition all of the tests to use this helper
    method, and that we we can get rid of the umpteen different ways we are
    building records across all of the tests.
    mcmire committed Dec 27, 2015
  5. @mcmire

    Extract classes for defining models in tests

    The main driver behind this commit is to provide a programmatic way to
    define models in tests. We already have ways of doing this, of course,
    with `define_model` and `define_active_model_class`, but these methods
    are very low-level, and in writing tests we have historically made our
    own methods inside of test files to define full and complete models. So
    we have this common pattern of defining a model with a validation, and
    that's repeated across many different files.
    
    What we would like to do, right now, is extract some commonly used
    assertions to a shared example group. These assertions need to define
    models inside of the tests, but the issue is that sometimes the models
    are ActiveRecord models, and sometimes they are ActiveModel models, and
    when the shared example group is used within a test file, we need a way
    to choose the strategy we'd like to use at runtime. Since the way we
    currently define models is via methods, we can't really provide a
    strategy very easily. Also, if we need to customize how those models are
    defined (say, the attribute needs to be a has-many association instead
    of a normal attribute) then the methods only go so far in providing us
    that level of customization before things get really complicated.
    
    So, to help us with this, this commit takes the pattern of
    model-plus-validation previously mentioned and places it in multiple
    classes.
    
    Note that this is also a precursor to a later commit in which we
    introduce `ignoring_interference_by_writer` across the board. The way we
    will do this is by adding a shared example group that then uses these
    model creation classes internally to build objects instead of relying
    upon methods that the outer example group -- to which the shared example
    group is being mixed into -- provides.
    mcmire committed Dec 23, 2015
  6. @mcmire

    uniqueness: Extract code to gen dummy values

    We need to use this in another part of the codebase: later, when we add
    ignoring_interference_by_writer to all matchers, we will need a way of
    overriding an attribute such that it produces another value that
    invalidates the test. Some tests require us to generate dummy values.
    mcmire committed Dec 27, 2015
Commits on Jan 4, 2016
  1. @mcmire

    Dispel confusion around rails_helper in README

    [ci skip]
    mcmire committed Jan 4, 2016
Commits on Dec 31, 2015
  1. @mcmire
  2. @mcmire
  3. @mcmire

    Update NEWS with latest changes

    [ci skip]
    mcmire committed Dec 31, 2015
  4. @mcmire

    numericality: lazily assign submatchers/qualifiers

    The numericality matcher has two kinds of qualifiers: those that add new
    tests directly to the matcher, and those that change the behavior of
    those tests. For instance, consider `odd` and `strict`. Using `odd`
    instructs the matcher to verify not only that the attribute can only be
    set to a number, but that it must be set to an *odd* number. `strict`
    then instructs the `odd` matcher to make this verification with the
    assumption that a validation exception will be raised instead of the
    record producing a validation error.
    
    It follows, then, that these qualifiers are order-dependent. This test:
    
        should validate_numericality_of(:attr).strict.odd
    
    is actually a different test than:
    
        should validate_numericality_of(:attr).odd.strict
    
    Why? Because if `strict` is written before `odd`, then it doesn't have
    any submatchers to affect. But if it is written after, then it can see
    that `odd` is present and can apply itself to it.
    
    The fact that users have to remember to specify submatchers in a certain
    order is inconvenient, and we don't like it. So to fix this, this commit
    records whenever `strict` or other like qualifiers are used, but then
    waits to apply them to the other submatchers until #matches? is called
    (that is, when the matcher is run).
    mcmire committed Dec 26, 2015
  5. @mcmire

    numericality: Do not run all submatchers

    This commit changes the numericality matcher so that when running
    submatchers, the matcher will stop on the first one that fails instead
    of running them all. Since all of the submatchers modify the same
    record, running all of them is actually bad since it could possibly make
    the failure message confusing (since the record will be in a mixed
    state).
    mcmire committed Dec 26, 2015
  6. @mcmire

    numericality: Show msg from only 1st failing submatcher, not all

    If multiple submatchers that the numericality matcher creates fail, then
    all of their messages will be contained within the message for the
    numericality matcher itself. This ends up being too much information,
    especially since later, we're going to tack a note on the end of
    allow_value's message if we detect that an attribute has changed an
    incoming value. If we didn't just show the message for the first failing
    submatcher, then that note would be present for all of the submatchers,
    and that gets obnoxious fast.
    mcmire committed Dec 25, 2015
  7. @mcmire

    Adjust message for AttributeDoesNotExistError

    Make it a little more clear that the attribute mentioned is on the
    model.
    mcmire committed Dec 30, 2015
  8. @mcmire
  9. @mcmire

    Remove tests for numericality submatchers

    All of these are tested indirectly through the tests for the
    numericality matcher itself. There are already plenty of tests to
    maintain, and so there's really no need to unit test these (not that
    they were truly "unit tested" to begin with).
    mcmire committed Dec 25, 2015
  10. @mcmire

    Add 'it supports' as an alias for 'it behaves like'

    Oftentimes our shared example groups represent tests for qualifiers.
    It's more natural to say "it supports ignoring_interference_by_writer"
    instead of "it behaves like it supports
    ignoring_interference_by_writer".
    mcmire committed Dec 24, 2015
  11. @mcmire
  12. @mcmire

    Define attrs in a module when building AM models in tests

    When a developer builds an ActiveModel model and wants to override an
    attribute, she may do so using `super` to call the original method. For
    instance:
    
        def foo=(value)
          super(value.next)
        end
    
    as opposed to:
    
        def foo=(value)
          @foo = value.next
        end
    mcmire committed Dec 22, 2015
  13. @mcmire

    Small tweaks to scripts that update gems

    The `update_gem_in_all_appraisals` script can do two things:
    
    * Update the given gem located in the Gemfile
    * Update the given gem located in Appraisals
    
    Currently, if the first step fails, then the second step does not run.
    With this commit, both will run regardless of their status.
    mcmire committed Dec 23, 2015
  14. @mcmire

    Upgrade RSpec to v3.4

    v3.3 introduced a new feature: the ability to re-run failed specs. v3.4
    contains some other nifty features, such as code highlighting and
    compound failure messages.
    mcmire committed Dec 23, 2015
  15. @mcmire

    allow_value: Inspect values more clearly

    Modify descriptions and failure messages for all matchers by way of
    allow_value and put small angle brackets around inspected values. This
    is to visually distinguish an inspected value from the rest of the text,
    and is especially noticeable for complex values such as an array that
    contains an object, particularly if the inspected version of the value
    wraps onto another line. It's a little easier to see:
    
        When attempting to set :attr on Example to ‹[#<Child id:
        nil>]›...
    
    rather than:
    
        When attempting to set :attr on Example to [#<Child id:
        nil>]...
    mcmire committed Dec 22, 2015
  16. @mcmire

    confirmation: Refactor to use AttributeSetter

    When the confirmation matcher is setting the confirmation attribute, we
    want it to raise an exception if the model does not have that attribute,
    same as if it would raise an exception if the attribute under test did
    not exist.
    mcmire committed Dec 21, 2015
  17. @mcmire

    Keep test Rails app directory clean

    All tests are run against a Rails app. The app is generated before each
    test, and one would think it gets removed after each test. For unit
    tests, this *does* happen before each test, but for acceptance tests, it
    does not get removed at all. This commit ensures that this happens, so
    that it is possible to run acceptance tests immediately after running
    unit tests.
    mcmire committed Dec 23, 2015
  18. @mcmire

    allow_value: pre-set attributes before validation

    While attempting to add support for `ignoring_interference_by_writer` to
    the confirmation matcher, I was noticing that there are two attributes
    we are concerned with: the attribute under test, and the confirmation
    attribute -- for instance, `password` and `password_confirmation`. The
    way that the matcher works, `password_confirmation` is set first on the
    record before `password` is set, and then the whole record is validated.
    This is fine, but I also noticed that `allow_value` has a specific way
    of setting attributes -- not only does it check whether the attribute
    being set exists and fail properly if it is does not, but it also
    raises a CouldNotSetAttribute error if the attribute changes incoming
    values. This logic needs to be performed on both `password_confirmation`
    as well as `password`.
    
    With that in mind, `allow_value` now supports a `values_to_preset=`
    writer method which allows one to assign additional attributes unrelated
    to the one being tested prior to validation. This will be used by the
    confirmation matcher in a future commit.
    
    This means that `allow_value` now operates in two steps:
    
    1. Set attributes unrelated to the test, raising an error if any of the
       attributes do not exist on the model.
    2. Set the attribute under test to one or more values, raising an error
       if the attribute does not exist, then running validations on the
       record, failing with an appropriate error message if the validations
       fail.
    
    Note that the second step is similar to the first, although there are
    more things involved. To that end, `allow_value` has been completely
    refactored so that the logic for setting and validating attributes
    happens in other places. Specifically, the core logic to set an
    attribute (and capture the results) is located in a new AttributeSetter
    class.
    
    Also, the CouldNotSetAttributeError class has been moved to a namespace
    and renamed to AttributeChangedValueError.
    
    Finally, this commit fixes DisallowValueMatcher so that it is the true
    opposite of AllowValueMatcher: DVM#matches? calls AVM#does_not_match?
    and DVM#does_not_match? calls AVM#matches?.
    mcmire committed Dec 19, 2015
  19. @mcmire
Commits on Dec 14, 2015
  1. @mcmire

    Run all rake tasks with --trace

    mcmire committed Dec 13, 2015
  2. @mcmire

    Update NEWS wrt recent changes to failure messages

    [ci skip]
    mcmire committed Dec 13, 2015
  3. @mcmire

    Fix acceptance tests to match recent changes

    Descriptions and failure messages of all matchers have been updated, so
    fix acceptance tests that reference either of these things.
    mcmire committed Dec 13, 2015
  4. @mcmire

    Refactor uniqueness matcher

    This is part of a collection of commits that aim to improve failure
    messages across the board, in order to make matchers easier to debug
    when something goes wrong.
    
    * Have the failure message describe what the matcher was trying to do
      when it failed.
    * Make the description of the matcher more readable.
    * Refactor the matcher so that it no longer unnecessarily creates
      records, but re-uses the existing record if it can instead. This
      makes the logic that the matcher performs slightly easier to follow.
    * Fix or fill in tests involving failure messages and descriptions to
      match these changes and recent changes to ValidationMatcher.
    mcmire committed Dec 13, 2015
  5. @mcmire

    Refactor presence matcher

    This is part of a collection of commits that aim to improve failure
    messages across the board, in order to make matchers easier to debug
    when something goes wrong.
    
    * Make the description of the matcher more readable.
    * Fix or fill in tests involving failure messages and descriptions to
      match these changes and recent changes to ValidationMatcher and
      allow_value.
    mcmire committed Dec 13, 2015