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

Run tests without pytests #2456

Merged
merged 20 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
*Bug tracker at https://github.com/giampaolo/psutil/issues*

6.0.1 (IN DEVELOPMENT)
6.1.0 (IN DEVELOPMENT)
======================

XXXX-XX-XX
Expand All @@ -14,6 +14,10 @@ XXXX-XX-XX
targets. They can be used to install dependencies meant for running tests and
for local development. They can also be installed via ``pip install .[test]``
and ``pip install .[dev]``.
- 2456_: allow to run tests via ``python3 -m psutil.tests`` even if ``pytest``
module is not installed. This is useful for production environments that
don't have pytest installed, but still want to be able to test psutil
installation.

**Bug fixes**

Expand Down
8 changes: 8 additions & 0 deletions docs/DEVGUIDE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ Once you have a compiler installed run:
make install
make test

- If you don't have the source code, and just want to test psutil installation.
This will work also if ``pytest`` module is not installed (e.g. production
environments) by using unittest's test runner:

.. code-block:: bash

python3 -m psutil.tests

- ``make`` (and the accompanying `Makefile`_) is the designated tool to build,
install, run tests and do pretty much anything that involves development.
This also includes Windows, meaning that you can run `make command` similarly
Expand Down
2 changes: 1 addition & 1 deletion psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
AF_LINK = _psplatform.AF_LINK

__author__ = "Giampaolo Rodola'"
__version__ = "6.0.1"
__version__ = "6.1.0"
version_info = tuple([int(num) for num in __version__.split('.')])

_timer = getattr(time, 'monotonic', time.time)
Expand Down
23 changes: 9 additions & 14 deletions psutil/tests/README.rst
Original file line number Diff line number Diff line change
@@ -1,40 +1,35 @@
Instructions for running tests
==============================

Setup:
There are 2 ways of running tests. If you have the source code:

.. code-block:: bash

make install-pydeps-test # install pytest
make test

There are two ways of running tests. As a "user", if psutil is already
installed and you just want to test it works on your system:
If you don't have the source code, and just want to test psutil installation.
This will work also if ``pytest`` module is not installed (e.g. production
environments) by using unittest's test runner:

.. code-block:: bash

python -m psutil.tests

As a "developer", if you have a copy of the source code and you're working on
it:

.. code-block:: bash

make test

You can run tests in parallel with:
To run tests in parallel (faster):

.. code-block:: bash

make test-parallel

You can run a specific test with:
Run a specific test:

.. code-block:: bash

make test ARGS=psutil.tests.test_system.TestDiskAPIs

You can run memory leak tests with:
Test C extension memory leaks:

.. code-block:: bash

make test-parallel
make test-memleaks
78 changes: 77 additions & 1 deletion psutil/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
from socket import AF_INET6
from socket import SOCK_STREAM

import pytest

try:
import pytest
except ImportError:
pytest = None

import psutil
from psutil import AIX
Expand Down Expand Up @@ -71,6 +75,8 @@
if PY3:
import enum
else:
import unittest2 as unittest

enum = None

if POSIX:
Expand Down Expand Up @@ -913,6 +919,76 @@ def get_testfn(suffix="", dir=None):
# ===================================================================


class fake_pytest:
"""A class that mimics some basic pytest APIs. This is meant for
when unit tests are run in production, where pytest may not be
installed. Still, the user can test psutil installation via:

$ python3 -m psutil.tests
"""

@staticmethod
def main(*args, **kw): # noqa ARG004
"""Mimics pytest.main(). It has the same effect as running
`python3 -m unittest -v` from the project root directory.
"""
suite = unittest.TestLoader().discover(HERE)
unittest.TextTestRunner(verbosity=2).run(suite)
warnings.warn(
"Fake pytest module was used. Test results may be inaccurate.",
UserWarning,
stacklevel=1,
)
return suite

@staticmethod
def raises(exc, match=None):
"""Mimics `pytest.raises`."""

class ExceptionInfo:
_exc = None

@property
def value(self):
return self._exc

@contextlib.contextmanager
def context(exc, match=None):
einfo = ExceptionInfo()
try:
yield einfo
except exc as err:
if match and not re.search(match, str(err)):
msg = '"{}" does not match "{}"'.format(match, str(err))
raise AssertionError(msg)
einfo._exc = err
else:
raise AssertionError("%r not raised" % exc)

return context(exc, match=match)

@staticmethod
def warns(warning, match=None):
"""Mimics `pytest.warns`."""
if match:
return unittest.TestCase().assertWarnsRegex(warning, match)
return unittest.TestCase().assertWarns(warning)

class mark:
class xdist_group:
"""Mimics `@pytest.mark.xdist_group` decorator (no-op)."""

def __init__(self, name=None):
pass

def __call__(self, cls_or_meth):
return cls_or_meth


if pytest is None:
pytest = fake_pytest


class TestCase(unittest.TestCase):
# ...otherwise multiprocessing.Pool complains
if not PY3:
Expand Down
2 changes: 1 addition & 1 deletion psutil/tests/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
$ python -m psutil.tests.
"""

import pytest
from psutil.tests import pytest


pytest.main(["-v", "-s", "--tb=short"])
3 changes: 1 addition & 2 deletions psutil/tests/test_bsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import time
import unittest

import pytest

import psutil
from psutil import BSD
from psutil import FREEBSD
Expand All @@ -26,6 +24,7 @@
from psutil.tests import HAS_BATTERY
from psutil.tests import TOLERANCE_SYS_MEM
from psutil.tests import PsutilTestCase
from psutil.tests import pytest
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import spawn_testproc
Expand Down
3 changes: 1 addition & 2 deletions psutil/tests/test_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
from socket import SOCK_DGRAM
from socket import SOCK_STREAM

import pytest

import psutil
from psutil import FREEBSD
from psutil import LINUX
Expand All @@ -38,6 +36,7 @@
from psutil.tests import check_connection_ntuple
from psutil.tests import create_sockets
from psutil.tests import filter_proc_net_connections
from psutil.tests import pytest
from psutil.tests import reap_children
from psutil.tests import retry_on_failure
from psutil.tests import skip_on_access_denied
Expand Down
3 changes: 1 addition & 2 deletions psutil/tests/test_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import unittest
import warnings

import pytest

import psutil
from psutil import LINUX
from psutil._compat import PY3
Expand All @@ -46,6 +44,7 @@
from psutil.tests import ThreadTask
from psutil.tests import call_until
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import reload_module
from psutil.tests import retry_on_failure
from psutil.tests import safe_rmpath
Expand Down
24 changes: 13 additions & 11 deletions psutil/tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import sys
import unittest

import pytest

import psutil
import psutil.tests
from psutil import POSIX
Expand Down Expand Up @@ -50,6 +48,7 @@
from psutil.tests import PsutilTestCase
from psutil.tests import mock
from psutil.tests import process_namespace
from psutil.tests import pytest
from psutil.tests import reload_module
from psutil.tests import sh
from psutil.tests import system_namespace
Expand Down Expand Up @@ -634,26 +633,29 @@ def test_debug(self):
else:
from StringIO import StringIO

with redirect_stderr(StringIO()) as f:
debug("hello")
sys.stderr.flush()
with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
with redirect_stderr(StringIO()) as f:
debug("hello")
sys.stderr.flush()
msg = f.getvalue()
assert msg.startswith("psutil-debug"), msg
assert "hello" in msg
assert __file__.replace('.pyc', '.py') in msg

# supposed to use repr(exc)
with redirect_stderr(StringIO()) as f:
debug(ValueError("this is an error"))
with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
with redirect_stderr(StringIO()) as f:
debug(ValueError("this is an error"))
msg = f.getvalue()
assert "ignoring ValueError" in msg
assert "'this is an error'" in msg

# supposed to use str(exc), because of extra info about file name
with redirect_stderr(StringIO()) as f:
exc = OSError(2, "no such file")
exc.filename = "/foo"
debug(exc)
with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
with redirect_stderr(StringIO()) as f:
exc = OSError(2, "no such file")
exc.filename = "/foo"
debug(exc)
msg = f.getvalue()
assert "no such file" in msg
assert "/foo" in msg
Expand Down
3 changes: 1 addition & 2 deletions psutil/tests/test_posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
import time
import unittest

import pytest

import psutil
from psutil import AIX
from psutil import BSD
Expand All @@ -31,6 +29,7 @@
from psutil.tests import QEMU_USER
from psutil.tests import PsutilTestCase
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import skip_on_access_denied
Expand Down
8 changes: 4 additions & 4 deletions psutil/tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import types
import unittest

import pytest

import psutil
from psutil import AIX
from psutil import BSD
Expand Down Expand Up @@ -65,6 +63,7 @@
from psutil.tests import create_py_exe
from psutil.tests import mock
from psutil.tests import process_namespace
from psutil.tests import pytest
from psutil.tests import reap_children
from psutil.tests import retry_on_failure
from psutil.tests import sh
Expand Down Expand Up @@ -1452,8 +1451,9 @@ def test_reused_pid(self):

# make sure is_running() removed PID from process_iter()
# internal cache
with redirect_stderr(StringIO()) as f:
list(psutil.process_iter())
with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
with redirect_stderr(StringIO()) as f:
list(psutil.process_iter())
assert (
"refreshing Process instance for reused PID %s" % p.pid
in f.getvalue()
Expand Down
3 changes: 1 addition & 2 deletions psutil/tests/test_process_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import time
import traceback

import pytest

import psutil
from psutil import AIX
from psutil import BSD
Expand All @@ -43,6 +41,7 @@
from psutil.tests import is_namedtuple
from psutil.tests import is_win_secure_system_proc
from psutil.tests import process_namespace
from psutil.tests import pytest


# Cuts the time in half, but (e.g.) on macOS the process pool stays
Expand Down
3 changes: 1 addition & 2 deletions psutil/tests/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import time
import unittest

import pytest

import psutil
from psutil import AIX
from psutil import BSD
Expand Down Expand Up @@ -56,6 +54,7 @@
from psutil.tests import check_net_address
from psutil.tests import enum
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import retry_on_failure


Expand Down
Loading
Loading