Skip to content

Conversation

PetterS
Copy link
Member

@PetterS PetterS commented Nov 13, 2020

Fixes #8032

Pytest already supports doCleanups; I added tests for this.

@PetterS PetterS changed the title Call Python 3.8 doCleanup and doClassCleanup. Call Python 3.8 doClassCleanup Nov 13, 2020
@PetterS PetterS changed the title Call Python 3.8 doClassCleanup Call Python 3.8 doClassCleanups Nov 13, 2020
Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @PetterS, LGTM with a few comments. The extensive tests are nice.

I see there is also a new addModuleCleanup but that'd be more tricky to support since the code for setUpModule/tearDownModule is not in the unittest plugin for some reason.

cls,
"setup_method",
"teardown_method",
"<no cleanup function>",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer not to do this trickery. I suggest allowing None and passing None here instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Done.

):
setup = getattr(obj, setup_name, None)
teardown = getattr(obj, teardown_name, None)
if setup is None and teardown is None:
return None

cleanup = getattr(obj, cleanup_name, lambda *args: None)

def docleanup(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to inline it. The setup code already does it, it's not too bad and will help with showing proper coverage for the different cases.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Linter would not let me assign a lambda to a variable so it looks like this now.

setup(self, request.function)
else:
setup()
except Exception:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would add a comment here about why only Exception is caught while below finally is used (-> to match what unittest does).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.



@pytest.mark.skipif(
sys.version_info < (3, 1), reason="Feature introduced in Python 3.1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we only support Python>=3.6, the Python 3.1 skips can be removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

def cleanup():
cls.values.append(1)
cls.addClassCleanup(cleanup)
def test_one(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps also add test_two to the class tests, to ensure that the cleanup indeed only runs once.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

cls.addClassCleanup(cleanup)
def test_one(self):
pass
class Second(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the fact that this is a unittest.TestCase is part of the test or not. If the purpose is just to check the MyTestCase.values value, then using a regular pytest function test would remove this ambiguity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@PetterS
Copy link
Member Author

PetterS commented Nov 16, 2020

I think this patch still can be improved. The pass_self branches for cleanup are not taken. I added those for consistency.

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think it's good to go. Will merge in a couple of days in case someone else also wants to review.

@PetterS
Copy link
Member Author

PetterS commented Nov 16, 2020

Cheers! This will help our internal development!

@bluetech bluetech merged commit eda681a into pytest-dev:master Nov 19, 2020
@PetterS PetterS deleted the fix8032 branch November 20, 2020 11:38
@PetterS
Copy link
Member Author

PetterS commented Dec 7, 2020

@bluetech Do you know when the next release of pytest will be?

@bluetech
Copy link
Member

bluetech commented Dec 7, 2020

@PetterS Planned for this Saturday (see #8101)

@PetterS
Copy link
Member Author

PetterS commented Dec 7, 2020

Cheers, thanks!

osandov added a commit to osandov/drgn that referenced this pull request Oct 7, 2024
pytest calls doClassCleanups() directly:
pytest-dev/pytest#8033. This ends up calling our
"backport" on Python 3.6 even when the test case doesn't use any class
cleanups or the @classCleanups decorator, resulting in the following
error:

  AttributeError: type object 'TestFsRefs' has no attribute '_class_cleanups'

Fix it by allowing our doClassCleanups() to be called unconditionally.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Class cleanups in Python 3.8+ are not called
2 participants