Commit Graph

14 Commits

Author SHA1 Message Date
Elliot Winkler 217a0b04ea Presence: check before assigning empty string
A previous commit updated the presence matcher so that when it is
testing invalid values for the attribute in question, it now considers
an empty string as one of those values. However, a string is not always
a valid value for an attribute. For instance, an attribute that is
decorated with `serialize` where the serialization class is Array cannot
be set to a string at all, and doing so will raise an error immediately.

With that in mind, this commit adds checks to ensure that it is safe to
try an empty string.
2019-06-13 00:39:00 -06:00
Joey Cheng 8553f697a2 Changes to ModelBuilder
* create_table and define_model_class accepts optional `connection' parameter for custom db connections
* clear_column_caches and drop_created_tables for ProductionRecord
2019-05-23 21:57:21 -06:00
Elliot Winkler da4e6ddd06 Add failing tests for issue 1146 2019-01-29 23:33:06 -07:00
Elliot Winkler 85a3b03c30 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.
2016-01-05 00:58:16 -07:00
Elliot Winkler 1b0a36a3ab 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
2015-12-30 21:58:51 -05:00
Anthony Navarre + Elliot Winkler eaaa2d83e5 allow_value: Raise error if attr sets value differently
`allow_value` will now raise a CouldNotSetAttribute error if the
attribute in question cannot be changed from a non-nil value to a nil
value, or vice versa. In other words, these are the exact cases in which
the error will occur:

* If you're testing whether the attribute allows `nil`, but the
  attribute detects and ignores nil. (For instance, you have a model
  that `has_secure_password`. This will add a #password= method to your
  model that is defined in a such a way that you cannot clear the
  password by setting it to nil -- nothing happens.)
* If you're testing whether the attribute allows a non-nil value, but
  the attribute fails to set that value. (For instance, you have an
  ActiveRecord model. If ActiveRecord cannot typecast the value in the
  context of the column, then it will do nothing, and the attribute will be
  effectively set to nil.)

What's the reasoning behind this change? Simply put, if you are assuming
that the attribute is changing but in fact it is not, then the test
you're writing isn't the test that actually gets run. We feel that this
is dishonest and produces an invalid test.
2015-02-17 23:09:56 -07:00
Elliot Winkler 74fa081ef5 Stop testing against columns unsupported by SQLite 2015-02-12 16:05:46 -07:00
Elliot Winkler 72f60fae94 Add support for Postgres
When running tests, you can now switch between running them against a
SQLite or PostgreSQL database. This is accomplished by modifying the
unit and acceptance tests so that when they generate and load the test
Rails application, database.yml is replaced with content that will
configure the database appropriately.
2015-02-12 16:01:00 -07:00
Elliot Winkler a43b8e44dd Rewrite tests for validate_uniqueness_of
* The main problem I had with the old tests is that information that
  the reader didn't need to care about was not properly abstracted away.
  For instance, a helper method used by almost all tests will always
  create a model called Example, and will always use an attribute called
  "attr" (on which the validation is present). However, in some tests
  the class or attribute is referred to directly. The reader shouldn't
  have to care about either of these things, since they are constant --
  the tests should be readable enough so that this information is not
  necessary to understand the case being tested against.

* Speaking of this helper method, some of the tests used it and some
  didn't. Some defined their own helper methods to represent a
  particular case (`case_sensitive: true`, `allow_nil`, etc.). This is
  now fixed so that all but two tests use the same helper method to
  define a model. This model is completely customizable -- one can
  specify the type of the attribute being validated, the names and types
  of scoped attributes, etc.

* The tests around scoped attributes and different types are all
  basically the same, so they are now compressed into a shared context.

* Related to this, we no longer have to worry about setting a proper
  value for a scope attribute. One had to know which type that attribute
  had and come up with a reasonable default for that type. Now there is
  a helper method that worries about this automatically.

* Finally, we remove tests around case_insensitive against an integer
  attribute (these don't make any sense, and don't work).
2015-02-11 16:09:40 -07:00
Elliot Winkler 547d8b762f Fix AR matcher tests for Rails 4.2 2014-12-25 00:45:06 -05:00
Elliot Winkler df6c0ef56e Clear schema cache after each test
When running unit tests in a random order, some tests may fail as the
columns hash within a model may not be in sync with the database. This
is because the columns hash is cached outside of the model, so removing
the model from the object space and then recreating that model won't
clear the columns hash.
2014-11-06 14:16:17 -07:00
Elliot Winkler 4c9dfa7616 Fix another warning 2014-11-05 16:39:04 -07:00
Elliot Winkler f922613386 Reorganize unit tests, part II
* Change 'spec' Rake task to 'spec:unit'
* Require unit_spec_helper.rb in unit tests, not spec_helper.rb
* Re-namespace files in spec/support/unit under UnitTests
* Files in spec/support/unit/helpers no longer automatically add
  themselves to RSpec - this happens in unit_spec_helper.rb
* Extract RecordWithDifferentErrorAttributeBuilder and
  RecordValidatingConfirmationBuilder to separate files
2014-11-05 09:53:20 -07:00
Elliot Winkler bbdf8a807e Reorganize unit tests, part I
* Move spec/shoulda to spec/unit_tests/shoulda
* Move spec/support/*.rb to spec/support/unit_tests/{helpers,matchers}
* Move spec_helper.rb to unit_spec_helper.rb
2014-11-04 14:43:59 -07:00
Renamed from spec/support/model_builder.rb (Browse further)