-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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 more than twice slower than Nosetest on trivial test with huge library to load #7111
Comments
Which command do you use to run pytest? |
@bluetech It was |
To comparison just $ time python test.py
python test.py 0.80s user 0.08s system 98% cpu 0.900 total |
I don't think pytest should look into If you can provide a minimal reproduction (i.e. a fresh venv with just what's needed installed and a test file, and the commands you run), I'll take a look. I also use Arch Linux and can install Sagemath if needed, even though IIRC it is was quite massive! |
I'm not familiar with venv so I have trouble with it: pacman -S community/sagemath
python -m venv test_venv
cd test_venv
ln -s /usr/lib/python3.8/site-packages/sage lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/cysignals/ ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/gmpy2/ ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/cypari2 ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/psutil ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/pexpect ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/ptyprocess ./lib/python3.8/site-packages/
ln -s /usr/bin/sage-maxima.lisp ./bin/
ln -s /usr/lib/python3.8/site-packages/ppl ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/IPython ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/traitlets ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/ipython_genutils ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/decorator ./lib/python3.8/site-packages/
ln -s /usr/lib/python3.8/site-packages/decorator-4.4.2-py3.8.egg-info ./lib/python3.8/site-packages/
source bin/activate
pip install nose
pip install pytest
cat << EOF > test.py
from sage.all_cmdline import * # import sage library
class TestClass:
def test_method(self):
assert True
EOF I cannot fix an error of import: ModuleNotFoundError: No module named 'decorator' P.S. I can create Vagrantfile for you. |
Possibly it is convinient to use vagrant together with VirtualBox. Vagrant is a tool for managing and configuring virtualised development environments. All of it is in Arch repositories and OSS. I've created Vagrantfile with provision shell-script: sudo pacman -Sy reflector --noconfirm
sudo reflector --verbose --latest 5 --sort rate --save /etc/pacman.d/mirrorlist
sudo pacman -Syu python sagemath python-pytest python-nose --noconfirm
cat << EOF > test.py
from sage.all_cmdline import * # import sage library
class TestClass:
def test_method(self):
assert True
EOF So it installs on virutal machine So on this bare ArchLinux installation with minimal dependencies for our needs. In order to use it you should: sudo pacman -Sy vagrant virtualbox --noconfirm
mkdir test_vagrant
cd test_vagrant
curl http://dpaste.com/0V5Q4SE.txt > Vagrantfile
vagrant up
vagrant provision
vagrant ssh Inside virtual environment you can compare runtime and output for 3 commands: time python test.py
time nosetests test.py
time pytest test.py My output: [vagrant@archlinux ~]$ time python test.py
real 0m0.862s
user 0m0.441s
sys 0m0.369s
[vagrant@archlinux ~]$ time nosetests test.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
real 0m0.850s
user 0m0.741s
sys 0m0.100s Full output of pytest: http://dpaste.com/3PM71XB, short version: [vagrant@archlinux ~]$ time pytest test.py
===================================================================== test session starts =====================================================================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/vagrant
collected 1 item
test.py . [100%]
====================================================================== warnings summary =======================================================================
<A lot of warnings I've ommited>
/usr/lib/python3.8/site-packages/_pytest/fixtures.py:1420
/usr/lib/python3.8/site-packages/_pytest/fixtures.py:1420: DeprecationWarning:
Importing tests from here is deprecated. If you need to use it, please import it directly from sage.tests
See https://trac.sagemath.org/27337 for details.
marker = getfixturemarker(obj)
:0
:0: PytestCollectionWarning: cannot collect 'tests' because it is not a function.
/usr/lib/python3.8/site-packages/sage/misc/sage_unittest.py:20
/usr/lib/python3.8/site-packages/sage/misc/sage_unittest.py:20: PytestCollectionWarning: cannot collect test class 'TestSuite' because it has a __init__ constructor (from: test.py)
class TestSuite(object):
-- Docs: https://docs.pytest.org/en/latest/warnings.html
=============================================================== 1 passed, 36 warnings in 2.57s ================================================================
real 0m3.071s
user 0m2.096s
sys 0m0.797s Still 3-4 times longer than nosetests and some noisy output. |
If you change: from sage.all_cmdline import * To: import sage.all_cmdline What happens? I suspect that star import is importing a lot of classes which look like tests to pytest. EDIT: I bet that's it, |
This code is actually what from sage.all_cmdline import * If I change it to import sage.all_cmdline I have almost same time with [vagrant@archlinux ~]$ time python test.py
real 0m0.744s user 0m0.638s
sys 0m0.103s
[vagrant@archlinux ~]$ time nosetests test.py
.
---------------------------------------------------------------------- Ran 1 test in 0.000s
OK
real 0m0.863s user 0m0.751s
sys 0m0.094s In case of [vagrant@archlinux ~]$ time python test.py
============================= test session starts ==============================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/vagrant
collected 1 item
test.py . [100%]
=============================== warnings summary ===============================
/usr/lib/python3.8/site-packages/sage/databases/conway.py:33
/usr/lib/python3.8/site-packages/sage/databases/conway.py:33: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
class DictInMapping(collections.Mapping):
/usr/lib/python3.8/site-packages/sage/matrix/matrix_space.py:46
/usr/lib/python3.8/site-packages/sage/matrix/matrix_space.py:46
/usr/lib/python3.8/site-packages/sage/matrix/matrix_space.py:46: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
from . import matrix_modn_sparse
/usr/lib/python3.8/site-packages/sage/plot/colors.py:1465
/usr/lib/python3.8/site-packages/sage/plot/colors.py:1465: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
class Colormaps(collections.MutableMapping):
/usr/lib/python3.8/site-packages/sage/combinat/ranker.py:22
/usr/lib/python3.8/site-packages/sage/combinat/ranker.py:22: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
from collections import Iterable, Sequence
/usr/lib/python3.8/site-packages/sage/geometry/cone.py:690
/usr/lib/python3.8/site-packages/sage/geometry/cone.py:690: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
collections.Hashable,
/usr/lib/python3.8/site-packages/sage/geometry/cone.py:1333
/usr/lib/python3.8/site-packages/sage/geometry/cone.py:1333: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
collections.Container):
/usr/lib/python3.8/site-packages/sage/geometry/fan.py:1069
/usr/lib/python3.8/site-packages/sage/geometry/fan.py:1069: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
collections.Callable,
-- Docs: https://docs.pytest.org/en/latest/warnings.html
======================== 1 passed, 8 warnings in 0.64s =========================
real 0m1.007s
user 0m0.866s
sys 0m0.133s
But still little bit slower and more noisy. And if you are using SageMath with it's preparsing you don't have much choice what to import. And you are right we don't have answer why nose is ok on original code. |
Hi @petRUShka,
I'm not familiar with
Although pytest certainly could use some optimization work, we need to remember that pytest has many more features, so it is expected for it to be slower than nose.
The verbose output is that pytest shows deprecation warnings by default, which is considered a good thing for test runners to do ( [pytest]
addopts = -p no:warnings -q I've cloned the repository, and indeed there are 4294 matches for A few options then:
[pytest]
python_classes = *Suite Then you need to change the name of your test class in your example from |
SageMath code is basically Python code with some minor additions and it is preparsing to Python. You can do it automatically with
Thanks so much for your advises! By the way is it desirable behavior of pytest to collect tests from import? It looks like kind of unwanted way of things. |
That's pretty much how every test framework for python works AFAIK, including |
@petRUShka can you close the issue if you don't have further questions? Thanks! |
If it is so why nose much faster on that code than pytest? Is it true that speed difference above is by design? |
Not sure, someone would need to investigate... but pytest has more overhead during collection because of plugins/fixtures/etc, while nose is much simpler. That many classes being collected might explain the difference. But this is really a hunch. In other words, both nose and pytest are collecting the same 4.7k+ classes, but because pytest has more overhead, it shows. But one thing to keep in mind, in a real test suite with 4.7k+ test classes, that difference becomes negligible. Here we are comparing the overhead using a single test, which all it does is |
Difference is quite significant on red-green-red cycle with one particular test you are working on. But possibly your advises will help! Thanks a lot. |
Ahhh definitely. In that case my previous advice should help, as you stated. Thanks! |
pip list
from the virtual environment you are usingSuppose we have installed huge library like SageMath. Let consider trivial test file:
It runs for about 1.5 sec with Nosetest
Whereas with pytest it runs for ~4.5 sec!
It looks (according to the warning) like pytest collects some tests from the library itself or may be something else.
P.S. Arch linux with latest upgrades.
Pip list: http://dpaste.com/34FAXBR
The text was updated successfully, but these errors were encountered: