-
-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Move to pytest? #7319
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
Comments
+1 i think this would be a good change. |
Should we create a plan to move to py.tests?
+1.
Now finding the resources to do that is going to be fun!
Maybe a GSOC next year?
|
Well I agree, nose has some deprecated code now and shifting to pytest can be a really good choice. |
@karandesai-96 we haven't settled on anything yet. GSOC is one option. I'm not sure you should start with PRs on this yet, but there will certainly be an opportunity to work on this. |
I wouldn't expect any major problems here: it's easy to get nose tests running in py.test. The harder part will be making the best use of py.test (proper sharing of fixtures, etc). |
Just replaced nosetests command in Makefile with py.test. Test system is working this way.
most errors come from sklearn/neighbors/tests/test_kde.py |
We need to remove all nose imports, though. |
I have an experience with fixtures, hooks and custom |
@karandesai-96 a bit of a problem with this parallel approach is that master is moving relatively fast. It might be the best option though? We need to be very careful not to drop any fixes that were applied to master since forking, though. |
Most of such imports are The only thing I'm not familiar with is:
|
those are fixtures. |
You mean with_setup? There are only two files with it: 3 occurrences in each |
Probably. we can just group those tests in classes and do this |
so the great py.test magic that gives helpful error messages is broken by the helpful assert helpers... at least partially. import numpy as np
from sklearn.utils.testing import assert_true
def test_greater():
X = np.random.normal((10, 10))
assert_true(np.all(X < 0)) produces a non-helpful error message (under nosetests or py.test), but def test_greater():
X = np.random.normal((10, 10))
assert np.all(X < 0) provides a helpful error message under pytest. So I guess as part of the transition we should change all |
This seems reasonable. Accordingly, would there be any use for |
Hi again, everyone! I undertook the nose to pytest migration in joblib ( joblib/joblib#411 ) and completed it within nearly a month, having @lesteve as my main reviewer. I saw that he is in the reviewers panel in scikit-learn as well. It has been approximately a month now, I had a little vacation from Python, visited the C++ land.. I wish to get back to contributing here on this issue. Quite a while since the last active discussion happened on this thread. What's the status here ? /ping @lesteve |
I don't think there's any question that this is the way we're going. But
it's no small task, I presume.
What are you proposing?
…On 1 February 2017 at 23:25, Karan Desai ***@***.***> wrote:
Hi again, everyone! I undertook the nose to pytest migration in *joblib*
( joblib/joblib#411 <joblib/joblib#411> ) and
completed it within nearly a month, having @lesteve
<https://github.com/lesteve> as my main reviewer. I saw that he is in the
reviewers panel in scikit-learn as well. It has been approximately a month
now, I had a little vacation from Python, visited the C++ land.. I wish to
get back to contributing here on this issue. It has been quite a while
since the last active discussion on this thread. What's the status here ?
/ping @lesteve <https://github.com/lesteve>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#7319 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz69mebFzXxSbxHh_N9_-xV3LVRt5jks5rYHm7gaJpZM4JyIJ0>
.
|
Shameless plug: first step is #8246. I have some further thoughts on this that I need to organize a bit. I'll post here when I get around to it. |
Karan, what do you think of potentially applying for this as a GSoC
project? If you feel that it is smaller in scope than a full GSoC project,
we can certainly add work related to check_estimator.
…On 2 February 2017 at 01:10, Loïc Estève ***@***.***> wrote:
What are you proposing?
Shameless plug: first step is #8246
<#8246>.
I have some further thoughts on this that I need to organize a bit. I'll
post here when I get around to it.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#7319 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz6yH0g2VacR4CSLP7KhxjxH5lljN-ks5rYJI_gaJpZM4JyIJ0>
.
|
@jnothman I will be happy to take this up as a GSoC project, scikit-learn is one of the frequently used libraries in my routine. Joblib migration was about 2000 lines 8000 and it took nearly a month, this is bigger so talking about time, I'll do the math now. The workflow will be similar so I can do it faster due to practice. About work related to |
Great! Because there aren't many projects we'd consider running this year, but I think this, and you, would be a worthwhile use of strained resources. |
FYI, it took less than 10 hours of work on skimage. If done properly, I don't think it should more than this on sklearn, specially considering part of the work has already been done. I really don't think this is near enough for a GSOC. Note that numpy.testing has some hidden dependencies on nose (assert_raises for instance). |
Out of interest, do you have a script that make most of the tedious conversion automatic? I have heard of https://github.com/pytest-dev/unittest2pytest but I have not given it a go. |
I used git grep + vim macros mostly (and a lot of travis running time…). On sklearn, all the imports are "localized", so I suspect the bulk is going to be the ~1000 assert raises. Sklearn also doesn't use any fancy nose plugins, which is going to simplify the migration. |
@NelleV I think probably you mean something like this work: joblib/joblib#433 I completely agree with you, this much work will hardly take a day or two now. Maybe a little more time if I take review cycles into account as well. Actually I was imagining a little more addition here, pytest provides a bunch of custom fixtures, and it has a different way to add testcases ( through a |
I don't take review cycle in account in my estimates. |
Here is my thoughts on the pytest move as promised: Towards pytest:
Transition period:
Dropping nose:
|
I started migrating scikit-learn to pytest before I saw this issue, and got a little carried away while doing all the changes. Implementing #8321 I came to the following conclusions
|
I am more than willing to hear others' opinion on this, but here is mine:
Current tests run almost without error with pytest. Only #8246 needs to be merged AFAIK. Do you have any specific problem in mind?
I could find only two occurences of numpy.testing.assert_raises and they can be replace by sklearn.testing.assert_raises, so I do not think this is a problem.
Yeah but such a PR is not that trivial to review, this is why I was proposing to break down into chunks in #7319 (comment). |
I agree with @lesteve. This migration should be broken down into chunks as the review cycle might get long and PRs here will have a longer life, which are bound to make merge conflicts. |
It took me a while to realize it. You are using the pytest test runner, with nose being installed in the same environment. And that is why #8246 only has very few changes. In contrast, I started with #8321 by not installing nose and making the whole test suite run on pytest-only. Then yes, with nose present it seems a more incremental approach of removing nose step-by-step would be doable. Anyway, it still might be interesting for you to have a look at #8321 as it has migrated the whole test suite to a state that is not using nose anymore. What would be left to do is to properly migrate the CI jobs, which would be diligent but routine kind of work. |
Incremental is key here IMHO. |
Scikit-learn currently uses `nose` for tests, while dask projects use `py.test` (and I like py.test better). Scikit-learn plans to move to py.test in the near-ish future because `nose` is no longer maintained (see issue scikit-learn/scikit-learn#7319). As such, this swaps out the current test/mock stuff that depends on `nose` to use `py.test` instead.
Scikit-learn currently uses `nose` for tests, while dask projects use `py.test` (and I like py.test better). Scikit-learn plans to move to py.test in the near-ish future because `nose` is no longer maintained (see issue scikit-learn/scikit-learn#7319). As such, this swaps out the current test/mock stuff that depends on `nose` to use `py.test` instead.
I think we should move to pytest as the default for CI before the next release, but we will need to have a small test suite for ensuring estimator_checks still all work with nose. |
Do you still want to support nose? Is there any feature which are not in pytest? We start to move the test in imbalanced learn and we saw that the yield will not be supported in the future by pytest. I think that it could be good to give you some feedback once we migrated since:
|
well we need the estimator checks to be amphibious for a deprecation period
in my opinion. I don't mind how that's done, even if it means duplicating
the check_estimator function.
…On 18 Aug 2017 5:44 am, "Guillaume Lemaitre" ***@***.***> wrote:
estimator_checks still all work with nose
Do you still want to support nose? Is there any feature which are not in
pytest?
We start to move the test in imbalanced learn and we saw that the yield
will not be supported in the future by pytest. I think that it could be
good to give you some feedback once we migrated since:
- we can tell you, as a user of the estimator check what we would need
- we will find out how to parametrize the tests to get away from the
yield
- @jorisvandenbossche <https://github.com/jorisvandenbossche> mention
that you can call a test with a specific parametrization to execute a
single estimator for instance, which could be really useful. I usually have
problem with the common test because I am executing everything each time
(maybe there is a nosetest feature that I don't know)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7319 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz6xqiJ0wVpon99wTQjbI5G6Xi7Vydks5sZJgMgaJpZM4JyIJ0>
.
|
I think it should be possible to keep the current Small toy example: import pytest
from sklearn.base import BaseEstimator
from sklearn.linear_model import LinearRegression, Lasso, Ridge
def check_estimator_aspect(estimator):
""" dummy example of existing check_... function """
# ...
assert isinstance(estimator(), BaseEstimator)
estimators = [LinearRegression, Lasso, Ridge]
# run this check function for a list of estimators by parametrizing them
test_estimator_aspect = pytest.mark.parametrize('estimator', estimators)(check_estimator_aspect)
# run this check function using yield (simplified version of how it is done now, but deprecated in pytest)
def test_estimator_aspect_orig():
for estimator in estimators:
yield check_estimator_aspect, estimator This way external project can import the Note: I only tested it with the above toy example, so not sure how it would work out in practice with all complexities. If you run the above with pytest, you get:
So the parametrized ones get automatically a nicer name, which you can use to run a single test (so not necessarily a single check for all estimators, but really a single test) |
Can I ask why? Is it just that you want to keep the |
Can't speak for @jnothman, but I think that is indeed the reason (downstream packages use those check functions to test compliance, and they can still be using nose). |
Yes, so we don't break downstream CIs relying on the public check_estimator
interface and the fact that it does not have a pytest dependency.
…On 21 August 2017 at 19:15, Joris Van den Bossche ***@***.***> wrote:
Can't speak for @jnothman <https://github.com/jnothman>, but I think that
is indeed the reason (downstream packages use those check functions to test
compliance, and they can still be using nose).
But also, even if we don't want to keep the estimator_checks.check_*
compatible with nose, we still need a way for downstream packages to run
the checks.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7319 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz67Yb_NSIpR3tpdlXii0kfdu09SdDks5saUq7gaJpZM4JyIJ0>
.
|
With my comment above (#7319 (comment)), I give one possible way how this could be possible I think (without needing to duplicate the check_estimators just to keep backwards compatibility, but keeping them working as is for downstream CI's) |
done in #9840. |
Something fairly similar is proposed in #11063 |
nosetests is no longer maintained and contains deprecated code (inspect.getargspec). It might not keep working with future versions of python. Should we create a plan to move to py.tests?
The text was updated successfully, but these errors were encountered: