Let the pytest fixtures use a custom user factory - #259
Open
jefftriplett wants to merge 5 commits into
Open
jefftriplett wants to merge 5 commits into
jefftriplett wants to merge 5 commits into
Conversation
Closes #125. TestCase subclasses can set user_factory so make_user() builds users through a factory instead of User.objects.create_user(). The tp and tp_api fixtures had no class of their own to set it on, so anyone whose User model needs a factory, because it has required fields or no username field, could not use tp.make_user() at all. Adds a test_plus_user_factory ini option holding a dotted path. Unset, which is the default, everything behaves exactly as before. The fixtures build a subclass rather than assigning to the instance: make_user() is a classmethod and reads cls.user_factory, so an instance attribute never reaches it. That was not obvious and cost a debugging round, hence the comment in the code. Bad values fail as pytest.UsageError with the reason, rather than an ImportError or AttributeError from inside a fixture.
Ruff's PLW1510. The test asserts on returncode itself so it can report the subprocess output on failure.
The reference rendered test_plus.test, status_codes, and runner, but not plugin, so tp, tp_api, and api_client had no entry at all. Adds the module, and docstrings for the three fixtures, which had none.
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #125, open since 2020.
The gap
TestCasesubclasses can set auser_factoryattribute andmake_user()will build users through it instead ofUser.objects.create_user(). Thetpandtp_apifixtures have no class of their own to set it on, so pytest users could never reach that hook. If yourUsermodel has required fields or nousernamefield,tp.make_user()simply could not build one.The option
A dotted path to the factory. Unset, which is the default, nothing changes:
make_user()callsUser.objects.create_user()exactly as before. Bad values raisepytest.UsageErrornaming the problem rather than leaking anImportErrororAttributeErrorout of a fixture.The part that was not obvious
Assigning
t.user_factory = factoryon the fixture instance looks right and does nothing.make_user()is aclassmethodand readscls.user_factory, so an instance attribute never reaches it. The fixtures build a small subclass instead:My first attempt did the instance assignment. The option loaded correctly,
tp.user_factorywas set, and users were still created bycreate_user(). The end to end test is what caught it, which is why it is written the way it is rather than asserting on the attribute alone.Backwards compatibility
Purely additive. The option defaults to unset,
TestCase.user_factorystill defaults toNone, and the 105 pre-existing tests are untouched and passing.Tests
Nine added, covering the loader and the real behaviour:
Nonepytest.UsageErrorwith a useful messagetp.user_factoryisNoneby default, andmake_user()still works without a factory-o test_plus_user_factory=...and asserts the created user's email comes from the factory's sequence, which is the field that proves the factory ran114 passed, 1 skipped, 2 xfailed, up from 105. Lint clean, docs build clean.
Docs
docs/usage.mdgains a "A custom user factory" section under pytest usage, showing both thepyproject.tomlandpytest.iniforms and saying when you would want it.