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

fix unintentional skipped tests #1557

Merged
merged 10 commits into from
Oct 4, 2017
Merged

fix unintentional skipped tests #1557

merged 10 commits into from
Oct 4, 2017

Conversation

jhamman
Copy link
Member

@jhamman jhamman commented Sep 7, 2017

As @crusaderky pointed out, just moving the @requires_pynio decorator inside the TestPyNio class seems to fix the problems described in #1531. It looks like requires_pynio is nullifying CFEncodedDataTest, Only32BitTypes, TestCase in addition to TestPyNio, hence the propagation.

This PR also includes a cleanup of tests/__init__.py.

Copy link
Contributor

@crusaderky crusaderky left a comment

Choose a reason for hiding this comment

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

What about the other @requires class decorators?

@fmaussion
Copy link
Member

I wonder if this propagation to parent classes is a feature or a bug? Seems quite messy to me

@jhamman
Copy link
Member Author

jhamman commented Sep 7, 2017

What about the other @requires class decorators?

I had this thought too. We don't decorate too many classes but I image we have other issues.

I wonder if this propagation to parent classes is a feature or a bug?

I would think this is a bug. I'm working on a simplified example to report this to pytest.

Copy link
Member

@shoyer shoyer left a comment

Choose a reason for hiding this comment

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

Thanks for taking this on!

I wonder if it might work to use pytest's importorskip inside the roundtrip() methods?

has_h5netcdf, requires_h5netcdf = _importorskip('h5netcdf')
has_pynio, requires_pynio = _importorskip('pynio')
has_dask, requires_dask = _importorskip('dask')
has_bottleneck, requires_bottleneck = _importorskip('bottleneck', '1.0')
Copy link
Member

Choose a reason for hiding this comment

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

bottleneck 1.0 came out in Feb 2015. I'm not sure it's worth having the version check here.

@@ -1529,6 +1527,8 @@ def roundtrip(self, data, save_kwargs={}, open_kwargs={},
autoclose=self.autoclose, **open_kwargs) as ds:
yield ds

@requires_scipy
@requires_pynio
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is enough -- the other methods defined on super-classes should also need pynio to pass for this TestCase. Looking at the test log on Travis, I see a lot of xfail and XPASS test cases, so maybe they are getting disabled by something else?

Copy link
Member Author

Choose a reason for hiding this comment

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

totally agree, this move does fix most of the issues but there are some additional issues. Now that we know what the problem is and have confirmation that this is a bug from the pytest team, I'll work on a more robust solution.

@shoyer
Copy link
Member

shoyer commented Sep 7, 2017

Maybe it's worth trying the work-around from pytest-dev/pytest#568 (comment)

@jhamman
Copy link
Member Author

jhamman commented Sep 7, 2017

Maybe it's worth trying the work-around from pytest-dev/pytest#568 (comment)

This gets us quite close but doesn't allow us to have use multiple decorators at once. I'll keep digging.

@shoyer
Copy link
Member

shoyer commented Oct 2, 2017

Another option is to give up on class decorators and only use a method decorator -- which we could even write ourselves if necessary. We have most of us backend specific logic in a few helper functions that we override for each subclass, so we only really need to decorate those, e.g.,

def conditional_skip(condition, reason=''):
    def wrapped(*args, **kwargs):
        if condition:
            raise unittest.SkipTest(reason)
        return wrapped(*args, **kwargs)
    return wrapped

class NetCDFSubclassTest(UnitTest):
    ...
    @contextmanager
    @conditional_skip(...)
    def roundtrip(self):
        ...

Copy link
Member

@shoyer shoyer left a comment

Choose a reason for hiding this comment

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

Looks great, thank you!

Can we note this as "Bug fix", since this is probably relevant to redistributors?

def _importorskip(modname, minversion=None):
try:
mod = importlib.import_module(modname)
has = True
Copy link
Member

Choose a reason for hiding this comment

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

put everything from here on down an the else clause

@pytest.mark.xfail
class H5NetCDFDataTestAutocloseTrue(H5NetCDFDataTest):
autoclose = True
# @pytest.mark.xfail @shoyer - is this still an issue?
Copy link
Member

Choose a reason for hiding this comment

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

Yes, I'm afraid so. It's probably an h5py issue -- not really clear what's going on.

Copy link
Member Author

Choose a reason for hiding this comment

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

reminder to myself to remove this comment

raise ImportError('Minimum version not satisfied')
except ImportError:
has = False
func = pytest.mark.skipif((not has), reason='requires {}'.format(modname))
Copy link
Member

Choose a reason for hiding this comment

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

remove redundant parentheses around (not has).

Copy link
Member

@shoyer shoyer left a comment

Choose a reason for hiding this comment

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

Looks great, thanks!

@@ -212,6 +212,11 @@ Bug fixes
the first argument was a numpy variable (:issue:`1588`).
By `Guido Imperiale <https://github.com/crusaderky>`_.

- Fix bug when using ``pytest`` class decorators to skiping certain unittests.
The previous behavior unintentionally causing additional tests to be skipped.
A temporary work-around has been applied in :issue:`1531`.
Copy link
Member

Choose a reason for hiding this comment

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

This is temporary for xarray, but from a user (or distributor) perspective the bug is fixed. I would probably drop that part.

Copy link
Member Author

@jhamman jhamman left a comment

Choose a reason for hiding this comment

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

I don't think this is ready to merge. I have a few small syntax/cleanup things to fix but more importantly, the TestPyNioAutocloseTrue test class is not being skipped correctly.

@pytest.mark.xfail
class H5NetCDFDataTestAutocloseTrue(H5NetCDFDataTest):
autoclose = True
# @pytest.mark.xfail @shoyer - is this still an issue?
Copy link
Member Author

Choose a reason for hiding this comment

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

reminder to myself to remove this comment

@requires_pynio
def setUp(self):
pass

Copy link
Member Author

Choose a reason for hiding this comment

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

This doesn't seem to be working. I'll try to come up with something else but if anyone has any ideas for how to get around this, I'm all ears.

Copy link
Member

Choose a reason for hiding this comment

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

Does it work if you hand-write the test-skipping decorator to raise unittest.SkipTest rather than relying on pytest.mark.skipif?

@@ -91,6 +90,7 @@ def contourf_called(self, plotmethod):

class TestPlot(PlotTestCase):

@requires_matplotlib
Copy link
Member

Choose a reason for hiding this comment

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

We don't need to move the requires_matplotlib decorator, since we don't rely on inheritance for enabling/disabling tests.

@requires_pynio
def setUp(self):
pass

Copy link
Member

Choose a reason for hiding this comment

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

Does it work if you hand-write the test-skipping decorator to raise unittest.SkipTest rather than relying on pytest.mark.skipif?

@jhamman jhamman changed the title move requires_pynio stop using class decorators with pytest Oct 4, 2017
@jhamman jhamman changed the title stop using class decorators with pytest fix unintentional skipped tests Oct 4, 2017
@jhamman
Copy link
Member Author

jhamman commented Oct 4, 2017

@shoyer - ready for a final review. Turns out, we can just use the unittest decorators. Basically no changes to the test code base :).

@jhamman jhamman requested a review from rabernat October 4, 2017 21:42
Copy link
Member

@shoyer shoyer left a comment

Choose a reason for hiding this comment

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

Even better, thank you!

)

has = False
# TODO: use pytest skip
Copy link
Member

Choose a reason for hiding this comment

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

can you briefly elaborate on why pytest.skip doesn't work? a link to this issue would be heplful.

@shoyer
Copy link
Member

shoyer commented Oct 4, 2017

LGTM, thanks

@jhamman jhamman merged commit e713668 into pydata:master Oct 4, 2017
@jhamman jhamman deleted the fix/1531 branch October 4, 2017 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@requires_pinio mass disables unrelated tests
4 participants