4 ms·
I think one example where duplication > abstraction is in tests. I personally find tests that have a ton of extra helper classes/functions to do stuff like set
by msluyter 3y ago
I think one example where duplication > abstraction is in tests. I personally find tests that have a ton of extra helper classes/functions to do stuff like set up fixtures or do assertions to be painful to deal with. Taken to an extreme you end up with a mini test framework that obscures the actual test cases and is as hard to understand as the code in question.
I'm not against shared test fixtures or some utility functions, but IMHO, it's better to have some duplication but clearer tests.
- echelon 3y agoFully agree. I would add that you should duplicate the common, cross-cutting setup (eg. faked/mocked dependencies that don't matter), but make the test conditions themselves explicit. You get a feel for the correct granularity the more tests you write within the codebase. If you try to be too clever in saving boilerplate, you'll cause pain for future modifications and maintainers. Sometimes fixing "clever" tests takes longer than the code change itself.
- abcdaiojjdfoj 3y agoI like it when you have nice, composable utility functions. Ideally each test contains a short preamble setting up the appropriate context for the test to run. The preamble elucidates what the tests are actually testing. It can also serve as documentation on how to use those functions. There will probably be some duplication across tests, but if the utility functions are idempotent/composable, they're usually pretty easy to read/understand and equally mechanical to write/update.
- ezekg 3y ago> I personally find tests that have a ton of extra helper classes/functions to do stuff like set up fixtures or do assertions to be painful to deal with. I think it depends on the context. For example, I typically agree, but when I was writing authz tests [0], I ended up writing a DSL so that 1) I'd more more inclined to write the thousands and thousands of tests, and 2) I'd be able to focus on the actual authz assertion and not on verbose setup. I couldn't imagine writing those policy tests without that abstraction. I would have lost my mind with all of the repetition, and would have almost assuredly made mistakes. [0]: https://github.com/keygen-sh/keygen-api/blob/master/spec/policies/license_policy_spec.rb https://github.com/keygen-sh/keygen-api/blob/master/spec/pol...
- HumanOstrich 3y agoThank you for the link. This is inspiring. Do you have any resources you could link to that would explain some or all of the style for these tests? The general approach I mean.
- ezekg 3y agoHonestly, I don't have many resources to provide. I read a lot of policy tests via GitHub search (e.g. path:spec/policies/*/*.rb), but couldn't find anything that looked like what I wanted. I wrote the DSL as-needed in order to fully test my app's authz while migrating from Pundit to ActionPolicy (while also introducing fine-grained permissions). It's not the prettiest when you actually look beneath the covers [0], but it does what I wanted -- providing an easy way to write exhaustive authz tests. Without the DSL, I probably wouldn't have written the tests. The PR for said migration was massive [1], and was a prerequisite to going open source [2]. [0]: https://github.com/keygen-sh/keygen-api/blob/master/spec/support/helpers/authorization_helper.rb https://github.com/keygen-sh/keygen-api/blob/master/spec/sup... [1]: https://github.com/keygen-sh/keygen-api/pull/647 https://github.com/keygen-sh/keygen-api/pull/647 [2]: https://github.com/keygen-sh/keygen-api/issues/644 https://github.com/keygen-sh/keygen-api/issues/644
- HumanOstrich 3y agoThanks! I'll dig around in the pull request and issue as well.