Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow staticmethods to be detected as test functions #2531

Merged
merged 1 commit into from
Jun 29, 2017

Conversation

waisbrot
Copy link
Contributor

Allow a class method decorated @staticmethod to be collected as a test function
(if it meets the usual criteria).

Fixes #2528


  • Add a new news fragment into the changelog folder
  • Target: for bugfix, vendor, doc or trivial fixes, target master; for removals or features target features;
  • Make sure to include reasonable tests for your change if necessary
  • Add yourself to AUTHORS;

@@ -143,6 +143,18 @@ class test(object):
"*collected 0*",
])

def test_staticmethid(self, testdir):
Copy link

@robert-cody robert-cody Jun 26, 2017

Choose a reason for hiding this comment

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

test_static_method or test_staticmethod would be better

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Spelling fix: argh, yes. Underscores: happy to change it but I was copying the decorator name and the method just below named test_setup_teardown_class_as_classmethod (for the @classmethod decorator)

@The-Compiler
Copy link
Member

Thanks! This should go to features though, IMHO.

@nicoddemus
Copy link
Member

This should go to features though, IMHO.

Definitely. 👍

Also, please rename the changelog entry to 2528.feature

@waisbrot waisbrot changed the base branch from master to features June 26, 2017 18:10
@waisbrot
Copy link
Contributor Author

waisbrot commented Jun 26, 2017

Changed it to a feature and changed the target branch to features.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.002%) to 92.14% when pulling bd3c7ef on waisbrot:staticmethods into 6e2b5a3 on pytest-dev:master.

@nicoddemus
Copy link
Member

Thanks!

@coveralls
Copy link

Coverage Status

Coverage increased (+0.002%) to 92.155% when pulling beb63d2 on waisbrot:staticmethods into 9b51fc6 on pytest-dev:features.

@blueyed
Copy link
Contributor

blueyed commented Jun 26, 2017

Seems to fail with "py26" (restarted out of current habit).

Copy link
Member

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Choose a reason for hiding this comment

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

i like it and i'd like to hear other opinions

@RonnyPfannschmidt
Copy link
Member

python 2.6 needs support code - we do have a helper for that

@waisbrot
Copy link
Contributor Author

Sorry I didn't try the fix on 2.6 earlier.

The 2.6 failure is because 2.6 staticmethods are different -- they don't have the __func__ reference that I was using to unwrap them in 2.7 and beyond. I'll look for how I can do it in 2.6, but suggestions are welcome.

@RonnyPfannschmidt can you point me to the 2.6 helper-code you mentioned?

@RonnyPfannschmidt
Copy link
Member

i was wrong, the helper cant apply because the functionality cant work on python 2.6

i propose intentionally leaving it crippled on python2.6 and skipping the tests there + adding a comment

the problem is that staticmethod on python26 doesn't expose __func__ or other attributes,

one can abuse __get__ to obtain it, but i oppose cripling our code more just to keep python2.6 working

@The-Compiler
Copy link
Member

By the way, are staticmethods always guaranteed to have a __func__ outside of Python 2.6? Should we use safe_getattr to get it? Should we just ignore when it hasn't been found?

@RonnyPfannschmidt
Copy link
Member

@The-Compiler as far as i can tell its supported on all python versions that are not EOL

@RonnyPfannschmidt
Copy link
Member

i propose simply issuing a warning if the attribute is not present

@waisbrot
Copy link
Contributor Author

Thanks for all the comments! I pushed a new version where I attempt to implement @RonnyPfannschmidt's suggestion: if it looks like a test, and it's a static method, but we can't find a __func__, issue a warning and don't collect.
The test for this expects to collect nothing on 2.6 and below and succeed otherwise. I tested locally with 2.6, 2.7, and 3.6.

self.warn(code="C2", message="cannot collect static method %r because it is not a function (always the case in Python 2.6)" % name)
return (
safe_getattr(obj, "__call__", False) and fixtures.getfixturemarker(obj) is None
)
Copy link
Member

Choose a reason for hiding this comment

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

There should probably be a return False here?

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.007%) to 92.147% when pulling fc400b2 on waisbrot:staticmethods into 9b51fc6 on pytest-dev:features.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.02%) to 92.137% when pulling 0a9489d on waisbrot:staticmethods into 9b51fc6 on pytest-dev:features.

Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

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

Thanks a lot! Just asking for two small changes which once addressed it can be merged IMHO.

result = testdir.runpytest()
if sys.version_info < (2,7):
# in 2.6, the code to handle static methods doesn't work
result.stdout.fnmatch_lines(["*collected 0*"])
Copy link
Member

Choose a reason for hiding this comment

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

Please improve matching here:

if sys.version_info < (2, 7):
    result.stdout.fnmatch_lines([
        "*collected 0 items*",
        "*cannot collect static method*",
    ])
else:
    result.stdout.fnmatch_lines([
        "*collected 1*",
        "*1 passed in*",
    ])

This way we ensure that we are showing the appropriate warning and that we are collecting and running it in Py27+.

return False
return (
safe_getattr(obj, "__call__", False) and fixtures.getfixturemarker(obj) is None
)
Copy link
Member

Choose a reason for hiding this comment

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

For consistency please return False in case you don't execute the block inside if self.funcnamefilter(name) or self.isnosetest(obj):.

@waisbrot
Copy link
Contributor Author

waisbrot commented Jun 27, 2017 via email

@nicoddemus
Copy link
Member

Sure thing, no rush, and thanks again!

Allow a class method decorated `@staticmethod` to be collected as a test
function (if it meets the usual criteria).

This feature will not work in Python 2.6 -- static methods will still be
ignored there.
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.02%) to 92.138% when pulling 9b9fede on waisbrot:staticmethods into 9b51fc6 on pytest-dev:features.

@RonnyPfannschmidt RonnyPfannschmidt merged commit 0303d95 into pytest-dev:features Jun 29, 2017
@RonnyPfannschmidt
Copy link
Member

thanks, well done 👍

@waisbrot
Copy link
Contributor Author

Thank you! This was a fun PR. You're all doing an awesome job of making contributions easy!

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.

7 participants