Opened 7 years ago
Closed 7 years ago
#28869 closed Bug (fixed)
Make test tags inherit from the class rather than be overridden by tags on the method
Reported by: | William Ayd | Owned by: | William Ayd |
---|---|---|---|
Component: | Testing framework | Version: | 1.11 |
Severity: | Normal | Keywords: | testing, tag |
Cc: | Hrishikesh Barman | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When subclassing test cases, decorated tags are inherited ONLY when the subclass does not provide its own tag decorator. If the subclass provides its own decorator(s) then the parent's tags are ignored.
If you use the attached file, running:
python manage.py test
yields two test cases as expected. However, running
python manage.py test --tag=foo-tests
OR
python manage.py test --tag=baz-tests
Will each only run one test a piece. I would expect that the former would run both test cases, given all of the test cases in the attached file are inherited from a class which is decorated with that tag.
Attachments (1)
Change History (12)
by , 7 years ago
Attachment: | test_foo.py added |
---|
comment:1 by , 7 years ago
Description: | modified (diff) |
---|
comment:2 by , 7 years ago
Replying to William Ayd:
When subclassing test cases, decorated tags are inherited ONLY when the subclass does not provide its own tag decorator. If the subclass provides its own decorator(s) then the parent's tags are ignored.
Will each only run one test a piece. I would expect that the former would run both test cases, given all of the test cases in the attached file are inherited from a class which is decorated with that tag.
I am a new contributor, I might be completely wrong but I think this is how the tag
decorator is supposed to work. When a parameter is explitcitly passed into the tag decorator, the function should use that tag and if the need is to specify another tag it should be done by separating by commas.
@tag('slow', 'core') def test_slow_but_core(self): pass
docs: https://docs.djangoproject.com/en/1.11/topics/testing/tools/#tagging-tests
If this is a confirmed bug, I'd like to work on it if you let me. :)
comment:3 by , 7 years ago
Cc: | added |
---|
comment:4 by , 7 years ago
Hi Hrishikesh,
My point was that it's strange that FooBar inherits the tag from it's parent while FooBaz does not, simply because the latter adds another tag of its own. Either neither class should inherit the tag from its parent, or both of them should (I think both inheriting would be preferred).
From what I see this can be easily fixed changing the tag function in Django.tests.util from:
def tag(*tags): """ Decorator to add tags to a test class or method. """ def decorator(obj): setattr(obj, 'tags', set(tags)) return obj return decorator
To
def tag(*tags): """ Decorator to add tags to a test class or method. """ def decorator(obj): if hasattr(obj, 'tags'): obj.tags = obj.tags | set(tags) else: setattr(obj, 'tags', set(tags)) return obj return decorator
So that subclasses can inherit any existing tags from their parents
comment:5 by , 7 years ago
Triage Stage: | Unreviewed → Accepted |
---|
The proposed fix looks appropriate.
Please submit a PR with your proposed patch and a regression test in tests/test_runner/test_discover_runner.py based on the structure introduced by d4dc775620fc57e962165eab98a77264e3dd16b2.
comment:7 by , 7 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:8 by , 7 years ago
Has patch: | set |
---|
Please note that I have fixed this and included regression tests in branch ticket_28869 available in my GitHub repo
comment:9 by , 7 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:10 by , 7 years ago
Patch needs improvement: | set |
---|---|
Summary: | Django.test.tag Inconsistent Inheritance → Make test tags inherit from the class rather than be overridden by tags on the method |
Triage Stage: | Ready for checkin → Accepted |
I left comments for improvement on the PR.
test_foo.py