From 68c13ac4df09081c3f461cf8b082ad2ed1f42154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sat, 14 Nov 2020 09:57:26 +0100 Subject: [PATCH 1/3] Use pytest.raises() instead of custom raising() decorator Use the raises() decorator that is already present in pytest instead of a custom solution. --- tests/test_pid.py | 65 ++++++++++++----------------------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/tests/test_pid.py b/tests/test_pid.py index e2ddb66..f115a0f 100644 --- a/tests/test_pid.py +++ b/tests/test_pid.py @@ -25,39 +25,6 @@ pid.DEFAULT_PID_DIR = pid.DEFAULT_PID_DIR.replace("\\", "/") -# https://code.google.com/p/python-nose/issues/detail?id=175 -@contextmanager -def raising(*exc_types): - """ - A context manager to ensure that an exception of a given list of - types is thrown. - - Instead of:: - - @nose.tools.raises(ValueError) - def test_that_raises(): - # ... lengthy setup - raise ValueError - - you can write:: - - def test_that_raises_at_the_end(): - # ... lengthy setup - with raising(ValueError): - raise ValueError - - to make the scope for catching exceptions as small as possible. - """ - try: - yield - except exc_types: - pass - except Exception: - raise - else: - raise AssertionError("Failed to throw exception of type(s) %s." % (", ".join(exc_type.__name__ for exc_type in exc_types),)) - - @contextmanager def raising_windows_io_error(): try: @@ -136,7 +103,7 @@ def test_pid_custom_dir(): def test_pid_piddir_exists_as_file(): with tempfile.NamedTemporaryFile() as tmpfile: - with raising(IOError): + with pytest.raises(IOError): with pid.PidFile(piddir=tmpfile.name): pass @@ -195,14 +162,14 @@ def test_pid_chmod(): @pytest.mark.skipif(sys.platform != "win32", reason="only runs on windows") def test_pid_chmod_win32(): - with raising(pid.PidFileConfigurationError): + with pytest.raises(pid.PidFileConfigurationError): with pid.PidFile(chmod=0o600): pass def test_pid_already_locked(): with pid.PidFile() as _pid: - with raising(pid.PidFileAlreadyLockedError): + with pytest.raises(pid.PidFileAlreadyLockedError): with pid.PidFile(): pass assert os.path.exists(_pid.filename) @@ -211,7 +178,7 @@ def test_pid_already_locked(): def test_pid_already_locked_custom_name(): with pid.PidFile(pidname="testpidfile") as _pid: - with raising(pid.PidFileAlreadyLockedError): + with pytest.raises(pid.PidFileAlreadyLockedError): with pid.PidFile(pidname="testpidfile"): pass assert os.path.exists(_pid.filename) @@ -254,7 +221,7 @@ def test_pid_two_locks_multi_process(): def test_pid_already_running(): with pid.PidFile(lock_pidfile=False) as _pid: - with raising(pid.PidFileAlreadyRunningError): + with pytest.raises(pid.PidFileAlreadyRunningError): with pid.PidFile(lock_pidfile=False): pass assert os.path.exists(_pid.filename) @@ -263,7 +230,7 @@ def test_pid_already_running(): def test_pid_already_running_custom_name(): with pid.PidFile(lock_pidfile=False, pidname="testpidfile") as _pid: - with raising(pid.PidFileAlreadyRunningError): + with pytest.raises(pid.PidFileAlreadyRunningError): with pid.PidFile(lock_pidfile=False, pidname="testpidfile"): pass assert os.path.exists(_pid.filename) @@ -296,7 +263,7 @@ def test_pid_decorator_already_locked(): @pidfile("testpiddecorator") def test_decorator(): - with raising(pid.PidFileAlreadyLockedError): + with pytest.raises(pid.PidFileAlreadyLockedError): @pidfile("testpiddecorator") def test_decorator2(): pass @@ -319,7 +286,7 @@ def test_pid_multiplecreate(): pidfile = pid.PidFile() pidfile.create() try: - with raising(pid.PidFileAlreadyRunningError, pid.PidFileAlreadyLockedError): + with pytest.raises((pid.PidFileAlreadyRunningError, pid.PidFileAlreadyLockedError)): pidfile.create() finally: pidfile.close() @@ -337,7 +304,7 @@ def test_pid_gid(): @pytest.mark.skipif(sys.platform != "win32", reason="only runs on windows") def test_pid_gid_win32(): gid = 123 - with raising(pid.PidFileConfigurationError): + with pytest.raises(pid.PidFileConfigurationError): with pid.PidFile(gid=gid): pass @@ -368,7 +335,7 @@ def check_const_samepid(): if sys.platform != "win32": check_const_samepid() else: - with raising(pid.PidFileConfigurationError): + with pytest.raises(pid.PidFileConfigurationError): check_const_samepid() @@ -392,7 +359,7 @@ def check_const_notrunning(): def test_pid_check_already_running(): with pid.PidFile() as pidfile: pidfile2 = pid.PidFile() - with raising(pid.PidFileAlreadyRunningError): + with pytest.raises(pid.PidFileAlreadyRunningError): pidfile2.check() assert not os.path.exists(pidfile.filename) @@ -414,13 +381,13 @@ def check_samepid_with_blocks_same_objects(): if sys.platform != "win32": check_samepid_with_blocks_separate_objects() else: - with raising(pid.PidFileConfigurationError): + with pytest.raises(pid.PidFileConfigurationError): check_samepid_with_blocks_separate_objects() if sys.platform != "win32": check_samepid_with_blocks_same_objects() else: - with raising(pid.PidFileConfigurationError): + with pytest.raises(pid.PidFileConfigurationError): check_samepid_with_blocks_same_objects() @@ -439,7 +406,7 @@ def check_samepid(): if sys.platform != "win32": check_samepid() else: - with raising(pid.PidFileConfigurationError): + with pytest.raises(pid.PidFileConfigurationError): check_samepid() @@ -455,7 +422,7 @@ def test_pid_raises_already_running_when_samepid_and_two_different_pids(mock_get pidfile_proc1.create() mock_getpid.return_value = 2 - with raising(pid.PidFileAlreadyRunningError): + with pytest.raises(pid.PidFileAlreadyRunningError): pidfile_proc2.create() finally: @@ -544,7 +511,7 @@ def test_decorator(): def test_pid_contextdecorator_already_locked(): @pid.PidFile("testpiddecorator") def test_decorator(): - with raising(pid.PidFileAlreadyLockedError): + with pytest.raises(pid.PidFileAlreadyLockedError): @pid.PidFile("testpiddecorator") def test_decorator2(): pass From 34cc216df344025229e84c9203e6372b1d260036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sat, 14 Nov 2020 09:59:08 +0100 Subject: [PATCH 2/3] Update test dependencies and modernize setup.py Update the test dependencies in setup.py to state that pytest (and mock, for Python < 3) are required. Nose is not used anywhere. While at it, remove the deprecated test logic and replace it with more modern approach using extras_require (see [1]) and expecting the user to call pytest directly. [1] https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#optional-dependencies --- setup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index beb47a7..0aa3a37 100644 --- a/setup.py +++ b/setup.py @@ -56,6 +56,10 @@ def find_version(*file_paths): install_requires=[ 'psutil>=5.4.8 ; sys_platform == "win32"', ], - test_suite='nose.collector', - tests_require=['nose>=1.0'], + extras_require={ + 'tests': [ + 'mock ; python_version < "3"', + 'pytest', + ] + }, ) From 18599b943956c30e9752e860f45212b9055e2c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sat, 14 Nov 2020 10:08:24 +0100 Subject: [PATCH 3/3] Add a convenience tox.ini for running tests Tox is a de-facto standard for testing packages against multiple Python versions. Add a configuration file to provide for that. --- tox.ini | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tox.ini diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..6692092 --- /dev/null +++ b/tox.ini @@ -0,0 +1,8 @@ +[tox] +envlist = py27,py36,py37,py38,py39,pypy,pypy3 + +[testenv] +extras = + tests +commands = + pytest {posargs}