-
Notifications
You must be signed in to change notification settings - Fork 692
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
Pytest Style: test_util.py #1494
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kain88-de @richardjgowers @jbarnoud @mnmelo Please have a look at this fixture I've created. I have used lambdas to save myself from writing a function that sets up the data and is then called in parametrize
. Is this style okay (it works fine)?
map(lambda format: format[0], formats)) + | ||
map(lambda ext: ext.lower(), map(lambda format: format[0], formats) | ||
)) | ||
def test_get_extention(self, ext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the new function. (FYI this will be done directly on _check_get_ext
- this wrapper method will not be there in the final version).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out that I don't really need nested calls, I can just do
map(lambda format: format[0].upper(), formats) +
map(lambda format: format[0].lower(), formats)
for extention in [format.upper(), format.lower()]: | ||
file_name = 'file.{0}'.format(extention) | ||
# check extention doesn't trip up get_ext or guess_format | ||
yield self._check_get_ext, extention, file_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This call is replaced by that fixture funciton.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had just a quick check. Some changes, though.
package/.pylintrc
Outdated
@@ -199,7 +199,6 @@ enable=abstract-class-instantiated, | |||
print-statement, | |||
xrange-builtin, | |||
zip-builtin-not-iterating, | |||
map-builtin-not-iterating, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not remove that check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That check is erroring out the build. Do you know of any alternate way to write the labdas I've written?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just make the list somewhere in the module namespace, you keep reusing it anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look bellow. It probably fails because you use +
on map
. In python 3, map
is an iterator so you cannot use +
on it. You need to convert the map output to a list to extend it.
By the way, if you use map
, you should import it from six
.
In general, you should never remove checks from pylint. If you understand exactly why the test fail, and you are sure about why you are doing, you may deactivate the check locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a map you can also use a normal list comprehension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List comprehensions dont work. TypeError: zip argument #1 must support iteration
|
||
def _check_compressed(self, f, fn): | ||
@pytest.mark.parametrize('extention', | ||
map(lambda format: format[0].upper(), formats) + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The +
will break on python 3. You need to consume the iterator in a list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
turn it into a list comprehension [f[0].upper() for f in formats]
. Please also try not to use keywords of the language itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kain88-de List comprehensions don't work inside parametrize calls. I get a TypeError.
assert_equal(self.obj.val3, self.obj.ref3) | ||
assert_equal('val3' in self.obj._cache, True) | ||
assert obj.val3 == obj.ref3 | ||
assert ('val3' in obj._cache) == True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'val3' in obj._cache
is enough. The == True
is useless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same above.
def test_convert_aa_code_long(self): | ||
for resname1, strings in self.aa: | ||
for resname3 in strings: | ||
yield check_convert_aa_3to1, resname3, resname1 | ||
yield self.check_convert_aa_3to1, resname3, resname1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't the yield still raise a internal pytest warning? We should remove all the yields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is marked as TODO.
# self.e2 = np.array([0, 1., 0]) | ||
# self.e3 = np.array([0, 0, 1.]) | ||
# self.a = np.array([np.cos(np.pi / 3), np.sin(np.pi / 3), 0]) | ||
# self.null = np.zeros(3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please remove these comments.
class TestGeometryFunctions(object): | ||
e1 = np.array([1., 0, 0]) | ||
e2 = np.array([0, 1., 0]) | ||
e3 = np.array([0, 0, 1.]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more concise would be e1, e2, e3 = np.eye(3)
# ]) | ||
# def test_normal(self, vec1, vec2, value): | ||
# assert mdamath.normal(vec1, vec2) == value | ||
# # add more non-trivial tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this fail?
assert_equal(ret, self.obj.ref1) | ||
obj._clear_caches() | ||
ret = obj.val1() | ||
assert ('val1' in obj._cache) == True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as @jbarnoud mentioned you don't need to do assert foo == True
just using assert foo
is enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should check the whole file for this pattern
|
||
def _load_bonds(self): | ||
def _load_bonds(self, universe): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make a fixture called universe_with_bonds
which is just the universe fixture and this function called? Ie put the body of this method into a fixture and use that instead?
I am able to get rid of lambda functions but oddly my linter complaints about references. Let's see what the Travis lint build says. |
@richardjgowers @kain88-de Can you help me with these lint errors
My IDE also complaints the same, but it is subscriptable! The tests pass on my system. |
@utkbansal it's because |
('TRZ', None, mda.coordinates.TRZ.TRZReader), | ||
] | ||
# list of possible compressed extensions | ||
# include no extension too! | ||
compressed_extensions = ['.bz2', '.gz'] | ||
|
||
def _check_get_ext(self, f, fn): | ||
@pytest.mark.parametrize('extention', [format[0].upper() for format in formats] + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if you choose another name. A static analyzer might confuse this with the built-in format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kain88-de @richardjgowers Let's say I rename format
to foo
. Then the linter complaints Unresolved reference
The tests still work though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe that. Please give it a try and let travis run on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@kain88-de @richardjgowers The build passed. I still have lint errors in my IDE though. Is there anything else that needs to be done here? |
|
||
def check_convert_aa_1to3(resname1, resname3_canonical): | ||
assert_equal(util.convert_aa_code(resname1), resname3_canonical) | ||
def test_convert_aa_code_long_data(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this getting also ran as a test because of the name?
Could this get rewritten as a generator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can think of a list comprehension to replace that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to rebase against develop and to fix the order of the imports.
data = [] | ||
for resname1, strings in aa: | ||
for resname3 in strings: | ||
data.append((resname3, resname1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a generator. Would not change much, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kain88-de @jbarnoud I need help converting this to a list comprehension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is not to make it a list comprehension, but a generator. To do that, replace this line by yield (resname3, resname1)
, remove the data
list, and remove the return
. But as I said, it does not change much, I like the generator better but the list is fine too.
import MDAnalysis.lib.mdamath as mdamath | ||
from MDAnalysis.lib.util import cached | ||
import MDAnalysis.lib.util as util |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The imports are disordered.
|
||
def test_VE_1(self): | ||
assert_raises(ValueError, util.convert_aa_code, 'XYZXYZ') | ||
with pytest.raises(ValueError): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_VE_1
and test_VE_2
test the same thing, it could be a parametrized test. It could also be renamed to test_ValueError
or something.
]) | ||
def test_string(self, name, ext, keep, actual_name): | ||
file_name = util.filename(name, ext, keep) | ||
assert file_name, actual_name #TODO: why is a comma here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix the todo
@utkbansal can you finish this up. |
@@ -605,103 +591,138 @@ class TestGuessFormat(object): | |||
('XYZ', mda.topology.XYZParser.XYZParser, mda.coordinates.XYZ.XYZReader), | |||
] | |||
if six.PY2: | |||
# DCD, LAMMPS, and TRZ are not supported on Python 3 yet | |||
# TRZ is not supported on Python 3 yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything is supported in py3, this should get rebased onto develop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So should I remove the check?
@@ -817,32 +819,38 @@ def _check_multiframe_fails(fmt): | |||
] | |||
if six.PY2: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this if can get removed too
Yes, there should not be special cases for python 3 anymore.
…On 07/27/2017 06:18 PM, Utkarsh Bansal wrote:
***@***.**** commented on this pull request.
------------------------------------------------------------------------
In testsuite/MDAnalysisTests/lib/test_util.py
<#1494 (comment)>:
> @@ -605,103 +591,138 @@ class TestGuessFormat(object):
('XYZ', mda.topology.XYZParser.XYZParser, mda.coordinates.XYZ.XYZReader),
]
if six.PY2:
- # DCD, LAMMPS, and TRZ are not supported on Python 3 yet
+ # TRZ is not supported on Python 3 yet
So should I remove the check?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1494 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABUWup3Kl_RvnCxOUE2cyEyn_usliiljks5sSLhngaJpZM4OZInh>.
|
for resname1, strings in aa: | ||
for resname3 in strings: | ||
data.append((resname3, resname1)) | ||
yield (resname3, resname1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't the goal to remove yield?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this isn't a yield based test. @jbarnoud recommended this #1494 (comment)
@kain88-de @jbarnoud Better now? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, a few more comments. In addition, all the tests that have a exception name abbreviated in their name could be rename to avoid the abbreviation. There are a few tests named test_*_VE
or test_*_TE
.
# Does ``get_writer_for`` fails with non string filename, no format | ||
with pytest.raises(ValueError): | ||
mda.coordinates.core.get_writer_for(filename = StringIO(), format = None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should not be spaces around the =
.
# does ``get_writer_for`` fail with invalid format and multiframe not None | ||
with pytest.raises(TypeError): | ||
mda.coordinates.core.get_writer_for(filename = "fail_me", format = 'UNK', multiframe = True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No spaces.
# does ``get_writer_for`` fail with invalid format and multiframe not None | ||
with pytest.raises(TypeError): | ||
mda.coordinates.core.get_writer_for(filename = "fail_me", format = 'UNK', multiframe = True) | ||
mda.coordinates.core.get_writer_for(filename = "fail_me", format = 'UNK', multiframe = False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No spaces.
mda.coordinates.core.get_writer_for, | ||
'this', format=fmt, multiframe=True) | ||
with pytest.raises(ValueError): | ||
mda.coordinates.core.get_writer_for(filename = 'this.gro', multiframe = 'sandwich') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No spaces.
def test_setattr(self): | ||
self.ns.this = 42 | ||
with pytest.raises(AttributeError): | ||
deller() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not need to be a nested function.
assert_equal(ret['delta'], 0.4) | ||
assert_almost_equal(ret['min'], 3.9) | ||
assert_almost_equal(ret['max'], 5.1) | ||
with pytest.raises(ValueError): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename test_VE
to test_ValueError
.
@utkbansal this isn't fully resolved yet |
@kain88-de @jbarnoud Fixed the whitespace and naming issues. |
Fixes #
Changes made in this Pull Request:
PR Checklist