3 ms·
This isn't an rspec problem, it's a Factories-for-ActiveRecord problem. The two main options to mitigate are: - just work with in-memory objects (FactoryBot u
by jamie_ca 4y ago
This isn't an rspec problem, it's a Factories-for-ActiveRecord problem.
The two main options to mitigate are:
- just work with in-memory objects (FactoryBot using build or build_stubbed, or just MyModel.new) and stub/mock finders as needed,
- or there's this thing people like to hate that was introduced in Rails 1 called test fixtures, which allow you to prepopulate the database with some initial data and then your test just runs in a transaction and rolls back.
The best suggestion I've heard recently (though I can't recall where to give credit) for managing complexity w/ fixtures is to write an extremely minimal fixture set aiming for 2 instances per model with minimal data required to be valid, and then customize it as part of your test. For a blog example, that means you have two Posts in your fixtures and would write a test around drafts by updating one of them to draft status (be it state, toggle, or publication date) and then test your query, or controller, or whatever. This keeps the data churn inside each test minimal, while keeping the out-of-scope data minimal as well -- if there's only 2 blog posts, all your tests can assume there will be one you care about and one you don't, which is useful for testing filtering/search/visibility/authorization/etc while remaining pretty consistent.
- itake 4y ago> - just work with in-memory objects (FactoryBot using build or build_stubbed, or just MyModel.new) and stub/mock finders as needed, Mocking the finders is obnoxious, since ActiveRecord returns a relation class, not an array. Plus stubbing out relational coupling isn't easy (e.g. the user model might have a `company_name` method that delegates to the company table.). > - or there's this thing people like to hate that was introduced in Rails 1 called test fixtures, which allow you to prepopulate the database with some initial data and then your test just runs in a transaction and rolls back. Fixtures and Factories have the same issue are vulnerable to inserting unnecessary data for the test. Models may have validation requirements that must be satisfied to be stored, but completely unnecessary for the test. For example, all users need a `company_id` with a foreign key constraint, so to test _anything_ on user, you have to insert a valid company as well. Maybe I need to re-evaluate fixtures though, since they would be simpler to run than a factory.
- piperswe 4y agoThe idea is that you write one set of fixtures for the whole app that you then use in all tests. You'd have a valid company and a valid user in your fixtures, but that's fine because you probably want to test both the company and user models. In the user model tests, you can ignore the existence of the company fixtures, and vice versa. Since the inserts only happen once for the whole test suite, the marginal cost of adding more fixtures is minimal, so it makes sense to just make the fixtures as complete as possible.
- itake 4y agointeresting. I haven't used fixtures before. Wouldn't this make individual tests slow (like in development?) since all fixtures must be inserted all the time?
- matthew-puku 4y agoIt doesn't add as much overhead as you might expect because the fixture data is inserted into the database without instantiating any ActiveRecord models. Unless you're loading a truly crazy amount of fixtures (gigabytes?), the database can ingest all the data in single-digit milliseconds.