Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
TST: Use pytest #13856
Conversation
TomAugspurger
added Testing CI
labels
Jul 31, 2016
TomAugspurger
added this to the
0.20.0
milestone
Jul 31, 2016
|
factoring asserts can be in a later PR pytest will work with nose tools (though we mostly use our own tm.* ones) |
sinhrks
commented on an outdated diff
Jul 31, 2016
|
Thanks a lot @TomAugspurger ! One note on something above:
My understanding is that the only way to use pytest fixtures within a class is to not inherit from And pytest discovers tests in Let me know if that's unclear. |
Agreed, the only asserts I've manually rewritten were in @MaximilianR thanks for the heads about |
|
pytest 3 is out now. Do we want to make the switch just after 0.19 is released? |
TomAugspurger
referenced
this pull request
Sep 18, 2016
Closed
TST: Some nose generator tests not running #14244
codecov-io
commented
Nov 3, 2016
•
Codecov Report
@@ Coverage Diff @@
## master #13856 +/- ##
=========================================
Coverage ? 87.88%
=========================================
Files ? 142
Lines ? 51106
Branches ? 0
=========================================
Hits ? 44913
Misses ? 6193
Partials ? 0
Continue to review full report at Codecov.
|
| @@ -44,7 +44,7 @@ matrix: | ||
| - python: 2.7 | ||
| env: | ||
| - JOB_NAME: "27_slow_nnet_LOCALE" | ||
| - - NOSE_ARGS="slow and not network and not disabled" | ||
| + - NOSE_ARGS="--skip-network" |
| @@ -126,8 +126,8 @@ function UpdateConda ($python_home) { | ||
| function main () { | ||
| InstallMiniconda $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON | ||
| UpdateConda $env:PYTHON | ||
| - InstallCondaPackages $env:PYTHON "pip setuptools nose" | ||
| + InstallCondaPackages $env:PYTHON "pip setuptools nose pytest" |
TomAugspurger
Nov 12, 2016
Contributor
@jreback I think we should keep nose for now for things like SkipTest. I'll make a followup issue to clean all this up though (changing skips, removing generator-based tests, and using more fixtures are the big ones).
| @@ -82,7 +82,7 @@ matrix: | ||
| - python: 3.5 | ||
| env: | ||
| - JOB_NAME: "35_nslow" | ||
| - - NOSE_ARGS="not slow and not network and not disabled" | ||
| + - NOSE_ARGS="--skip-slow --skip-network" |
| @@ -32,6 +33,7 @@ class TestPickle(): | ||
| """ | ||
| _multiprocess_can_split_ = True | ||
| + @pytest.fixture(autouse=True) |
jreback
Nov 11, 2016
Contributor
don't use autouse its a bit magical, create explict fixtures (we can come back and fix this later though if easier)
MaximilianR
Nov 11, 2016
Contributor
I think this might have been my suggestion.
Without this, I'm not sure setUp will run unless the class inherits from unittest.TestCase.
I think we could change setUp to [setup_class](http://doc.pytest.org/en/latest/xunit_setup.html) and it would run pytest. (Or setup_method if we need access to self rather than class)
TomAugspurger
Nov 12, 2016
Contributor
@MaximilianR thanks, changed to use setup_class and all the tests run / pass. Made the same change in test_packers to remove autouse.
| @@ -236,7 +236,7 @@ def _close_conn(self): | ||
| pass | ||
| -class PandasSQLTest(unittest.TestCase): | ||
| +class PandasSQLTest(object): |
jreback
Nov 11, 2016
•
Contributor
I would still inherit from our base class for tests (which is not that useful for pytest, but simplifes things when changing)
TomAugspurger
Nov 11, 2016
Contributor
IIRC, the pytest runner either didn't discover real test subclasses below, or didn't properly run the setup and teardown methods. I needed to move the TestCase inheritance down to the actual Test* classes to get the tests to pass.
MaximilianR
Nov 15, 2016
Contributor
@TomAugspurger A gentle reminder here - in my experience pytest won't run this class, because of its name. Not 100% sure, but at least worth double-checking it's run.
TomAugspurger
Nov 15, 2016
Contributor
Thanks. This is the base class, there aren't any test_ methods attached to PandasSQLTest. All of the real test classes, which inherit from PandasSQLTest do start with with Test. IIRC the root problem was the setUp methods weren't being run with the prior inheritance. I'll post a fuller explanation later, because the diff isn't very informative.
MaximilianR
Nov 15, 2016
•
Contributor
I see! Sorry.
FWIW I've generally called those ...Base rather than ...Test, to make that explicit. But only a personal preference. And in time fixtures can replace most of this inheritance
| - t.disabled = True | ||
| - return t | ||
| - | ||
| +disabled = pytest.mark.disabled |
jreback
Nov 11, 2016
Contributor
I would put these in conftest (and then just import into this name space)
| @@ -4,7 +4,8 @@ command -v python-coverage >/dev/null && python-coverage erase | ||
| # nosetests pandas/tests/test_index.py --with-coverage --cover-package=pandas.core --pdb-failure --pdb | ||
| #nosetests -w pandas --with-coverage --cover-package=pandas --pdb-failure --pdb #--cover-inclusive |
| @@ -5,7 +5,8 @@ python setup.py build_ext --inplace | ||
| coverage erase | ||
| # nosetests pandas/tests/test_index.py --with-coverage --cover-package=pandas.core --pdb-failure --pdb | ||
| #nosetests -w pandas --with-coverage --cover-package=pandas --pdb-failure --pdb #--cover-inclusive | ||
| -nosetests -w pandas --with-coverage --cover-package=pandas $* #--cover-inclusive | ||
| +# nosetests -w pandas --with-coverage --cover-package=pandas $* #--cover-inclusive | ||
| +pytest pandas --cov=pandas $* #--cover-inclusive | ||
| # nosetests -w pandas/io --with-coverage --cover-package=pandas.io --pdb-failure --pdb | ||
| # nosetests -w pandas/core --with-coverage --cover-package=pandas.core --pdb-failure --pdb |
|
@TomAugspurger is this working? (aside from the core dump in master). issue is I think nose needs to be removed from the ci/requirements* files as well |
|
@jreback pretty close I think. The only ones I'm stumped on are the Other than that, I just have a bit of cleanup and verification that we didn't drop any tests. I'll do that tonight and on Sunday, hopefully get the merged soon. And the |
|
d653086 fixed Without pytest: >>> import pandas
>>> pandas.test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/tom.augspurger/Envs/py3/lib/python3.5/site-packages/pandas/pandas/api/test.py", line 13, in test
raise ImportError("Need pytest>=3.0 to run tests")
ImportError: Need pytest>=3.0 to run testsWith pytest (until I canceled it): >>> import pandas
>>> pandas.test()
...............^CI'd like to do the complete removal of nose (skips and generator-based tests for the most part) as a followup issue. |
TomAugspurger
referenced
this pull request
Nov 14, 2016
Merged
COMPAT: Cast to string before raise in read_stata #14657
|
@bashtage, do you have any guesses on what's causing this failure (scroll down a bit for the traceback)? The actual error comes from trying to lookup I suspect the problem is at a higher-level, since this passes with the nose runner, and it passes on other parts of our build matrix with pytest: https://travis-ci.org/pandas-dev/pandas/builds/175935337 Any hunches would be appreciated, but no worries if you're stumped. |
|
I don't recall having any issues there, so nothing obvious. |
jorisvandenbossche
reviewed
Dec 14, 2016
@TomAugspurger What's the status of this?
There are still few failures you didn't figure out? (the stata one? The others you know how to fix?)
| @@ -35,7 +35,7 @@ matrix: | ||
| osx_image: xcode6.4 | ||
| env: | ||
| - JOB_NAME: "35_osx" | ||
| - - NOSE_ARGS="not slow and not network and not disabled" | ||
| + - NOSE_ARGS="--skip-slow --skip-network" |
|
@TomAugspurger I have found the problem with Will need to either use a custom date converter for the month or to temporarily set the locale when writing stata files. Former is probably easier although maybe uglier. |
bashtage
added a commit
to bashtage/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage |
1eeda97
|
bashtage
added a commit
to bashtage/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage |
ec50395
|
|
@bashtage thanks! One of the other failing tests is locale related as well. Haven't been able to determine if it's an actual bug in pandas, or just something wrong with how we're setting up the test that pytest doesn't like. |
bashtage
added a commit
to bashtage/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage |
c8e0b52
|
bashtage
added a commit
to bashtage/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage |
5a54fc8
|
bashtage
referenced
this pull request
Jan 24, 2017
Closed
BUG: Remove locale conversion from Stata file date #15208
bashtage
added a commit
to bashtage/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage |
a23a92f
|
TomAugspurger
added a commit
to TomAugspurger/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage + TomAugspurger |
e56dc8e
|
|
@TomAugspurger The reason why you found this is that you ran all tests with |
|
@bashtage hmm, https://travis-ci.org/pandas-dev/pandas/jobs/194558929 DOES run all tests with a locale (IT and only on 2.7) |
|
@TomAugspurger if its easier (not sure), you can certainly make an additional build that runs py.test, of course then these changes need to be compat with |
But the short month for Italian is 3 non-unicode characters. For Chinese it is Unicode, which is why when writing the date as a string, Chinese requires an extra byte while Italian doesn't. I suspect that Chinese is a somewhat harder language to pass w.r.t. locale issues than most western languages. edit |
|
so does this make sense to flip the locale for these tests? (e.g. not-slow tests with chinese, e.g. more unicode), and IT for slow? |
|
I would think so. Should be OK since the other locale testing is allowed failure. |
Oh I guess I misunderstood our NOSE_ARGS. |
no |
|
@TomAugspurger yes we have essentially split tests, e.g. slow/non-slow. I think replicating that is a good ideal. in fact we can eventually define more markers to split things further at some point |
Then if you switched them master would be failing. It would probably make the most sense to run |
|
though its on the 34_notslow we try to cover everything.......but you know how that goes! |
| -def disabled(t): | ||
| - t.disabled = True | ||
| - return t | ||
| +disabled = pytest.mark.disabled |
jreback
Jan 24, 2017
•
Contributor
I don't think we actually have any disabled tests, so fine to remove this marker
but I think you need to make network a marker as well
bashtage
added a commit
to bashtage/pandas
that referenced
this pull request
Jan 24, 2017
|
|
bashtage |
a55bfd8
|
jreback
added a commit
that referenced
this pull request
Jan 25, 2017
|
|
bashtage + jreback |
3ad978a
|
|
Have you tried using pytest-xdist on travis,
Seeing nice speedup on slow statsmodels runs (18-20 min down to 11-13). Travis instances have 1.5 vCPUs. |
Will try that as soon as I get the basic version passing. Down to one failure on a single job: https://travis-ci.org/pandas-dev/pandas/jobs/197031785#L1445 a locale test on Any guess on why that is, before I dig into it? That job doesn't have any custom locale settings (and it passes fine locally). Looking into the appveyor failures now. |
|
@TomAugspurger you can simulate the locale locally easily put in
|
| @@ -93,6 +93,11 @@ def test_set_locale(self): | ||
| raise nose.SkipTest("Only a single locale found, no point in " | ||
| "trying to test setting another locale") | ||
| + if all(x is None for x in CURRENT_LOCALE): | ||
| + # Not sure why, but on some travis runs with pytest, |
jreback
Feb 1, 2017
Contributor
ok, though very odd that this occurs only in pytest......let's put a note to try to remove this later
TomAugspurger
Feb 1, 2017
Contributor
Yeah, very strange. Wasn't able to find anything about why that's happening, but that test / the .setlocale contextmanager relies on getlocale() being valid initially. I've started a list of followup issues, will add this.
|
@TomAugspurger all passing! that's great! and of course love the I would remove I'll have a look soon at the changes. did you fix |
I think so, but need to do a bit more testing here. I think that the appveyor testing proves that I have things setup correctly, since we |
|
some people use |
| +import pytest | ||
| + | ||
| + | ||
| +def pytest_addoption(parser): |
TomAugspurger
Feb 4, 2017
Contributor
I don't like where it's at now either, but I think it's necessary. As this note says:
This function [pytest_addoption] should be implemented only in plugins or conftest.py files situated at the tests root directory due to how pytest discovers plugins during startup.
The other option, I suppose is to bundle a setuptools entrypoint so that our custom options show up for anyone who has pytest and pandas. We could prefix our --run-slow, etc with --pandas-run-slow, to avoid name clashes.
Do you have a preference between the two?
|
i have never have a problem putting conftest in the root directory - an entry point is for a separate program not sure that is needed here |
|
Have you needed to distribute the conftest with the package though? Here's with python -c "import pandas; pandas.test(['--only-slow'])"
usage: -c [options] [file_or_dir] [file_or_dir] [...]
-c: error: unrecognized arguments: --only-slow
inifile: None
rootdir: /Users/tom.augspurger/Envs/stitch/lib/python3.5/site-packages/pandasIf we don't care about allowing users to specify any extra options we have (or anything else we add to the conftest in the future), then this isn't a problem. |
|
moving ``conftest``` to ~/pandas works fine for me (and the command above works just fine as well)
|
|
I think where to put the
I was having trouble getting appveyor to work, since IIUC the package is installed into |
| @@ -30,7 +30,7 @@ class TestPDApi(Base, tm.TestCase): | ||
| # these are optionally imported based on testing | ||
| # & need to be ignored | ||
| - ignored = ['tests', 'locale'] | ||
| + ignored = ['tests', 'locale', 'conftest'] |
| +""" | ||
| +import os | ||
| + | ||
| +PKG = os.path.dirname(os.path.dirname(__file__)) |
jreback
Feb 5, 2017
•
Contributor
FYI, I think this might just work if you make PKG= PKG + '../..' IOW make it outside the package)
TomAugspurger
Feb 5, 2017
Contributor
That would, but I think then pytest discovers "tests" in vb_suite, numpydoc, and scripts.
|
@TomAugspurger as soon as you get this fully working, we can merge it. also add a whatsnew in highlites (but can do later if needbe) |
jorisvandenbossche
reviewed
Feb 5, 2017
Possibly that a rebase went wrong? (or not yet done?) as the diff seems to indicate that a full test_timeseries.py is added
Some small comments added.
| - exit=False) | ||
| + import pytest | ||
| + | ||
| + pytest.main([__file__, '-vvs', '-x', '--pdb']) |
jorisvandenbossche
Feb 5, 2017
Owner
Is it actually needed to keep those if __name__ == '__main__': parts? Does anybody use this?
(but can of course remove this in another PR if we want this)
jreback
Feb 7, 2017
Contributor
yeah I agree. I think we should do a separate PR to remove ALL of these (makes this PR a bit simpler too).
we don't advocate actually running indivdidual files, rather it is appropriate to use the test framework.
TomAugspurger
Feb 7, 2017
Contributor
I have these all in a single commit. If someone (I'll have time tonight) wants to make a PR removing them, I should be able to delete that commit before rebasing, and there won't be any conflicts (hopefully).
| @@ -552,8 +552,8 @@ use cases and writing corresponding tests. | ||
| Adding tests is one of the most common requests after code is pushed to *pandas*. Therefore, | ||
| it is worth getting in the habit of writing tests ahead of time so this is never an issue. | ||
| -Like many packages, *pandas* uses the `Nose testing system | ||
| -<https://nose.readthedocs.io/en/latest/index.html>`_ and the convenient | ||
| +Like many packages, *pandas* uses `pytest` |
jorisvandenbossche
Feb 5, 2017
Owner
the backtick at the end of pytest is incorrect, as the 'env' is closed with the backtick after the link on the following line
| @@ -0,0 +1,23 @@ | ||
| +""" | ||
| +Entrypoint for testing from the top-level namespace | ||
| +""" |
jorisvandenbossche
Feb 5, 2017
Owner
I would keep this in util (but maybe util/_tester.py instead of util/nosetester.py
In any case, IMO this is a strange place, as we currently use pd.api to put things from other places in a consistent place, not to put actual code for which the entry point for users is not here.
|
re the rebas: FYI @TomAugspurger I did merge a few new files yesterday (and removed test_timeseries.py). sorry about that.... |
|
Fixed the rebase. I saw the new files, just forgot to remove the old one. here's the problem I saw with the conftest earlier. Added a debug print to this next appveyor run, so we'll see. I've addressed your other comments Joris, thanks. |
|
The re-addition of |
It's a zombie module, won't stay dead. I've removed it for real now. This run shows the trouble I'm having with appveyor. Dunno why, but the setup of
AFAICT, the same layout (running test from the git repo, but having the package installed to |
| @@ -795,18 +795,19 @@ class TestMsgpack(): | ||
| http://stackoverflow.com/questions/6689537/nose-test-generators-inside-class | ||
| """ | ||
| - def setUp(self): |
bashtage
Feb 5, 2017
Contributor
Pytest will run setup but not setUp before each test in a class. Guessing this change in structure was intentional.
|
You probably need something like |
|
Last commit moved conftest.py back to the package, under Should I change appveyor to be an inplace install? |
jreback
referenced
this pull request
Feb 7, 2017
Merged
TST: remove __main__ from all test files #15330
|
Rebased on top of #15330. Only one tiny conflict thankfully. |
| @@ -1 +1,2 @@ | ||
| -nosetests -A "not slow and not network" pandas --processes=4 $* | ||
| +# nosetests -A "not slow and not network" pandas --processes=4 $* |
| @@ -3,10 +3,4 @@ | ||
| python setup.py clean | ||
| python setup.py build_ext --inplace |
| @@ -32,7 +32,7 @@ matrix: | ||
| env: | ||
| - PYTHON_VERSION=3.5 | ||
| - JOB_NAME: "35_osx" | ||
| - - NOSE_ARGS="not slow and not network and not disabled" | ||
| + - NOSE_ARGS="--skip-slow --skip-network" |
|
I think the 124 instances of |
hmm, since we don't actually use parallel nose testing...... will take these out in a separate PR |
jreback
referenced
this pull request
Feb 7, 2017
Closed
TST/STYLE: remove multiprocess nose flags and slight PEP fixes #15333
jreback
added a commit
that referenced
this pull request
Feb 7, 2017
|
|
jreback |
542c916
|
|
Rebased on #15333 |
| @@ -11,6 +11,7 @@ Highlights include: | ||
| - Building pandas for development now requires ``cython >= 0.23`` (:issue:`14831`) | ||
| - The ``.ix`` indexer has been deprecated, see :ref:`here <whatsnew_0200.api_breaking.deprecate_ix>` | ||
| +- Switched the test framework to pytest (:issue:`13097`) |
| + help="run network tests") | ||
| + parser.addoption("--only-slow", action="store_true", | ||
| + help="run only slow tests") | ||
| + parser.addoption("--run-disabled", action="store_false", |
| + if 'skip' in item.keywords and item.config.getoption("--skip-network"): | ||
| + pytest.skip("skipping due to --skip-network") | ||
| + | ||
| + if 'disabled' in item.keywords and item.config.getoption("--run-disabled"): |
| @@ -24,7 +24,7 @@ class TestCompressedUrl(object): | ||
| 'xz': '.xz', | ||
| } | ||
| - def __init__(self): | ||
| + def setUp(self): |
| @@ -3938,6 +3938,15 @@ def test_period(self): | ||
| self.assertEqual(str(df), exp) | ||
TomAugspurger
Feb 7, 2017
Contributor
Was gonna do fixtures as a follow up. Right now it's runnable under nose and pytest.
jreback
Feb 7, 2017
Contributor
yep, np. Though I don't think its a big deal to completely drop nose (but sure can do later).
jreback
Feb 7, 2017
Contributor
in fact fixture setup / changing to parameterized is actually quite a bit of work :> we have so many loop-y type tests which really should be parametrized.
TomAugspurger
Feb 7, 2017
Contributor
One of the indexing tests had over 100 variations in a single test :D
jreback
Feb 7, 2017
Contributor
yep, I think when you merge this can pretty much go crazy on params / fixtures.
|
I have 2 PR's ready to go in (shortly): #15336 (groupby test) and #15324 (timedelta tests) I don't actually think this will cause a rebase for you or if so should be trivial. If you are close on this (appears so), then I will wait on future things (that change tests a lot) until we merge this (aside from these 2)? |
|
AFAIK this is ready to go. The only lingering issue is Rebasing isn't too bad now that I don't touch every test file, so up to you when you want to merge these. I'll just keep rebasing when there are conflicts :) |
|
ok, let me merge these and you rebase. I think let's put this in tomorrow (when you are ready). BTW did you change NOSE_ARGS -> TEST_ARGS? (or something). yeah I really want |
| - nosetests pandas/tests/[test-module].py:[TestClass] | ||
| - nosetests pandas/tests/[test-module].py:[TestClass].[test_method] | ||
| + pytest pandas/tests/[test-module].py | ||
| + pytest pandas/tests/[test-module].py::[TestClass] |
jreback
Feb 8, 2017
Contributor
I would instead recommend using -k, in fact this is one of the main reasons I really like pytest, e.g.
pytest pandas/[tests-module].py -k cool_test IMHO is much easiest then finding class names and the exact names of the methods.
|
@TomAugspurger all merged. rebase and let's get this in! |
jreback
changed the title from
[WIP] TST: Use pytest to TST: Use pytest
Feb 8, 2017
| + | ||
| +For more, see the `pytest<http://doc.pytest.org/en/latest/>`_ documentation. | ||
| + | ||
| + .. versionadded:: 0.18.0 |
| + if 'slow' not in item.keywords and item.config.getoption("--only-slow"): | ||
| + pytest.skip("skipping due to --only-slow") | ||
| + | ||
| + if 'skip' in item.keywords and item.config.getoption("--skip-network"): |
jreback
Feb 8, 2017
Contributor
on the todo list, let's just make @network an actual marker then this becomes trival
| @@ -2549,9 +2550,7 @@ def assert_produces_warning(expected_warning=Warning, filter_level="always", | ||
| % extra_warnings) | ||
| -def disabled(t): | ||
| - t.disabled = True |
jreback
Feb 8, 2017
Contributor
I think you might need to fix TestCase, IOW the setUpClass and such.
|
can you rebase and we will try for tomorrow for merging? |
TomAugspurger
added some commits
Jul 31, 2016
|
Rebased and travis is green. I'm under a deadline for Wednesday, so won't be able to start on followup issues till later next week. |
|
ok thanks @TomAugspurger let me play a bit with this. I think we can just merge and fix anything else later. |
jreback
closed this
in ab8822a
Feb 10, 2017
|
thanks @TomAugspurger awesome job! |
|
I made a couple of minor changes: 7713f29 and added a bit to the 'list' of TODOs, but otherwise merged very nicely! |
AnkurDedania
added a commit
to AnkurDedania/pandas
that referenced
this pull request
Mar 21, 2017
|
|
bashtage + AnkurDedania |
2ad7c44
|
AnkurDedania
added a commit
to AnkurDedania/pandas
that referenced
this pull request
Mar 21, 2017
|
|
jreback + AnkurDedania |
0f10b04
|
AnkurDedania
added a commit
to AnkurDedania/pandas
that referenced
this pull request
Mar 21, 2017
|
|
TomAugspurger + AnkurDedania |
eaf2216
|
TomAugspurger commentedJul 31, 2016
•
edited
git diff upstream/master | flake8 --diffJust a WIP for now, will need to iterate on the CI stuff to ensure that's all good.
What can I provide to make this easier to review? Refactoring tests is scary.
I'll give verbose outputs of nose on master and pytest on this branch.
junit.xml output too. Anything else?
Here are some notes I took along the way
Kinds of Changes
See TestPickle, TestMsgPack and this SO post. We switched to using parametrized fixtures (yay) and dependency injection instead of setUp + a for loop inside the test.
See the sql tests.
py.testdiscovers_Test*class (if they inherit fromTestCase?), while unittest does not.Solution: move TestCase inheritance down a level
See e.g. pandas/src/testing.py
assert cond, msgasif not cond; raise AssertionError(msg)