Why frozen test fixtures are a problem on large projects and how to avoid them
1–10 of 67 posts
Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#2Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#3Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#4> This test has just made it impossible to introduce another active project without breaking it, even if the scope was not actually broken. Add a new variant of an active project for an unrelated test and now you have to also update this test.
And then goes on to test that the known active projects are indeed included in what the call to Project.active returns.
However, that doesn't test that "active scope returns active projects". Rather, it tests that
- active scope returns _at least some of the_ active projects, and
And it does not test that
- active scope returns _all_ of the active projects
- active scope does not return non-active projects
Which, admittedly, is only different because the original statement is ambiguous. But the difference is that the test will pass if it returns non-active projects, too; which probably is not the expected behavior.
I prefer to set things up so that my test fixtures (test data) are created as close to the test as possible, and then test it in the way the article is saying is wrong (in some cases)... ie, test that the call to Project.active returns _only_ those projects that should be active.
Another option would be to have 3 different tests that test all those things, but the second one (_all_ of the active projects) is going to fail if the text fixture changes to include more active projects.
Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#5Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#6Example 1 bothers me. It says > This test has just made it impossible to introduce another active project without breaking it, even if the scope was not actually broken. Add a new variant of an active project for an unrelated test and now you have to also update this test. And then goes on to test that the known active projects are indeed included in what the call to Project.active returns. However, that doesn't test…
The "doesn't include non-active projects objections is easy", please check the Example 1 test again, there's a line for that:
``` refute_includes active_projects, projects(:inactive) ```
Hm, if you missed it, perhaps I should have emphasised this part more, maybe add a blank line before it ...
Regarding the fact that the test does not check that the scope returns "all" active projects, that's a bit more complex to address but let me let tell you how I'm thinking about it:
The point of tests is to validate expected behaviours and prevent regressions (i.e. breaking old behaviour when introducing new features). It is impossible for tests to do this 100%. E.g. even if you test that the scope returns all active projects present in the fixtures that doesn't guarantee that the scope always returns all active projects for any possible list of active projects. If you want 100% validation your only choice is to turn to formal proof methods but that's whole different topic.
You could always add more active project examples. When you write a test that is checking that "Active projects A,B and C" are returned that is the same test as if your fixtures contained ONLY active projects A,B and C and then you tested that all of them are returned. In either case it is up to you to make sure that the projects are representative.
So by rewriting the test to check: 1. These example projects are included. 2. These other example projects are excluded.
You can write a test that is equally powerful as if you restricted your fixtures just to those example projects and then made an absolute comparison. You're not loosing any testing power. Expect you're making the test easier to maintain.
Does that make sense? Let me know which part is still confusing and I'll try to rephrase the explanation.
Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#7factories definitely are the cause of my test suite being slower than I'd like, I've been thinking of switching to fixtures. Good to see some context of what challenges I might be dealing with instead if I do.
Btw, I also have an article with some of my learnings using factories and I make a remark on how it helps with test speed: https://radanskoric.com/articles/test-factories-principal-of...
Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#8Example 1 bothers me. It says > This test has just made it impossible to introduce another active project without breaking it, even if the scope was not actually broken. Add a new variant of an active project for an unrelated test and now you have to also update this test. And then goes on to test that the known active projects are indeed included in what the call to Project.active returns. However, that doesn't test…
Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#9factories definitely are the cause of my test suite being slower than I'd like, I've been thinking of switching to fixtures. Good to see some context of what challenges I might be dealing with instead if I do.
Author here. I'm a big fan of factories but the slowness is a real drag on large test suites. If you're considering switching, remember that you can do it gradually, there's no law against using both fixtures and factories in the same project, in some cases (mostly on very complex domain data models) even makes sense: fixtures for the base setup that all tests share, factories for additional test specific records. Bt…
While I see the pro's (and con's) of fixtures, one thing I do _not_ like is Rails ordinary way of specifying fixtures, in yaml files. Especially gets terrible for associations.
It's occured to me there's no reason I can't use FactoryBot to create what are actually fixtures -- as they will be run once, at test boot, etc. It would not be that hard to set up a little harness code to use FactoryBot to create objects at test boot and store them (or logic for fetching them, rather) in specified I dunno $fixtures[:some_name] or what have you for referal. And seems much preferable to me, as I consider switching to/introducing fixtures.
But I haven't seen anyone do this or mention it or suggest it. Any thoughts?
Re: Why frozen test fixtures are a problem on large projects and how to avoid them
#10"assert_equal names, names.sort" is a wrong answer. It would accept an empty collection.