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

Tests: replace nose with pytest #603

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ script:
- scons config
- export RM_TS_PRINT_CMD=1
- export RM_TS_PEDANTIC=0
- sudo -E nosetests -s -v -a '!slow'
- sudo -E pytest -s -v -k 'not slow'
6 changes: 3 additions & 3 deletions docs/developers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,13 @@ Notable targets

:test:

Build the tests (requires ``python`` and ``nosetest`` installed).
Optionally ``valgrind`` can be installed to run the tests through
Build the tests (requires ``python`` and ``pytest`` installed).
Optionally ``valgrind`` can be installed to run the tests through
valgrind:

.. code-block:: bash

$ USE_VALGRIND=1 nosetests # or nosetests-3.3, python3 needed.
$ USE_VALGRIND=1 pytest

:xgettext:

Expand Down
2 changes: 1 addition & 1 deletion docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Here's a list of readily prepared commands for known operating systems:

.. code-block:: bash

$ apt-get install pkg-config git scons python3-sphinx python3-nose gettext build-essential
$ apt-get install pkg-config git scons python3-sphinx python3-pytest gettext build-essential
# Optional dependencies for more features:
$ apt-get install libelf-dev libglib2.0-dev libblkid-dev libjson-glib-1.0 libjson-glib-dev
# Optional dependencies for the GUI:
Expand Down
23 changes: 10 additions & 13 deletions docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Testsuite
complete yet (and probably never will), but it's already a valuable boost of
confidence in ``rmlint's`` correctness.

The tests are based on ``nosetest`` and are written in ``python>=3.0``.
The tests are based on ``pytest`` and are written in ``python>=3.0``.
Every testcase just runs the (previously built) ``rmlint`` binary a
and parses its json output. So they are technically blackbox-tests.

Expand Down Expand Up @@ -34,17 +34,17 @@ variables which are:
- ``RM_TS_PRINT_CMD``: Print the command that is currently run.
- ``RM_TS_KEEP_TESTDIR``: If a test failed, keep the test files.

Additionally slow tests can be omitted with by appending ``-a '!slow'`` to
the commandline. More information on this syntax can be found on the `nosetest
Additionally slow tests can be omitted with by appending ``-k 'not slow'`` to
the commandline. More information on this syntax can be found on the `pytest
documentation`_.

.. _`nosetest documentation`: http://nose.readthedocs.org/en/latest/plugins/attrib.html
.. _`pytest documentation`: https://docs.pytest.org/en/stable/example/markers.html

Before each release we call the testsuite (at least) like this:

.. code-block:: bash

$ sudo RM_TS_USE_VALGRIND=1 RM_TS_PRINT_CMD=1 RM_TS_PEDANTIC=1 nosetests-3.4 -s -a '!slow !known_issue'
$ sudo RM_TS_USE_VALGRIND=1 RM_TS_PRINT_CMD=1 RM_TS_PEDANTIC=1 pytest -s -a 'not slow and not known_issue'

The ``sudo`` here is there for executing some tests that need root access (like
the creating of bad user and group ids). Most tests will work without.
Expand All @@ -59,7 +59,7 @@ were executed (and how often) by the testsuite. Here's a short quickstart using
.. code-block:: bash

$ CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs -ftest-coverage" scons -j4 DEBUG=1
$ sudo RM_TS_USE_VALGRIND=1 RM_TS_PRINT_CMD=1 RM_TS_PEDANTIC=1 nosetests-3.4 -s -a '!slow !known_issue'
$ sudo RM_TS_USE_VALGRIND=1 RM_TS_PRINT_CMD=1 RM_TS_PEDANTIC=1 pytest -s -a 'slow and not known_issue'
$ lcov --capture --directory . --output-file coverage.info
$ genhtml coverage.info --output-directory out

Expand All @@ -85,11 +85,9 @@ A template for a testcase looks like this:

.. code-block:: python

from nose import with_setup
from tests.utils import *

@with_setup(usual_setup_func, usual_teardown_func)
def test_basic():
def test_basic(usual_setup_usual_teardown):
create_file('xxx', 'a')
create_file('xxx', 'b')

Expand Down Expand Up @@ -117,11 +115,10 @@ Rules

.. code-block:: python

from nose.plugins.attrib import attr
import pytest

@attr('slow')
@with_setup(usual_setup_func, usual_teardown_func)
def test_debian_support():
@pytest.mark.slow
def test_debian_support(usual_setup_usual_teardown):
assert random.choice([True, False]):

* Unresolved issues can be marked with `known_issue` attribute to avoid failing automated travis testing
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
markers =
slow: slow tests.
3 changes: 1 addition & 2 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
nose==1.3.7
parameterized==0.6.1
xattr==0.9.6
psutil==5.6.6
pytest
8 changes: 4 additions & 4 deletions tests/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ def cmd_exists(cmd):


def run_tests(target=None, source=None, env=None):
names = ['nosetests-3.3', 'nosetests-3', 'python3-nosetests', 'nosetests3', 'nosetests']
names = ["pytest"]
exes = [exe for exe in names if cmd_exists(exe)]
if any(exes):
name = exes[0]
print('Found nosetests as "{}"'.format(name))
Exit(subprocess.call(name + ' -s -v -a !slow', shell=True))
print('Found pytest as "{}"'.format(name))
Exit(subprocess.call(name + ' -s -v -k "not slow"', shell=True))

print('Unable to find nosetests, tried these: ' + str(names))
print('Unable to find pytest, tried these: ' + str(names))
Exit(-1)


Expand Down
21 changes: 21 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pytest

from tests.utils import mount_bind_teardown_func, usual_setup_func, usual_teardown_func

@pytest.fixture(params=["sh", "bash", "dash"])
def shell(request):
yield request.param


@pytest.fixture
def usual_setup_usual_teardown():
usual_setup_func()
yield
usual_teardown_func()


@pytest.fixture
def usual_setup_mount_bind_teardown():
usual_setup_func()
yield
mount_bind_teardown_func()
4 changes: 1 addition & 3 deletions tests/test_formatters/test_csv.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
# encoding: utf-8
from nose import with_setup
from tests.utils import *

import csv
Expand All @@ -10,8 +9,7 @@ def csv_string_to_data(csv_dump):
return data[1:]


@with_setup(usual_setup_func, usual_teardown_func)
def test_simple():
def test_simple(usual_setup_usual_teardown):
create_file('1234', 'a')
create_file('1234', 'b')
create_file('1234', 'stupid\'file,name')
Expand Down
4 changes: 1 addition & 3 deletions tests/test_formatters/test_json.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#!/usr/bin/env python3
# encoding: utf-8
from nose import with_setup
from tests.utils import *


@with_setup(usual_setup_func, usual_teardown_func)
def test_simple():
def test_simple(usual_setup_usual_teardown):
full_path_a = create_file('x', '\t\r\"\b\f\\')
full_path_b = create_file('x', '\"\t\n2134124')
head, *data, footer = run_rmlint('-S a')
Expand Down
4 changes: 1 addition & 3 deletions tests/test_formatters/test_others.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#!/usr/bin/env python3
# encoding: utf-8
from nose import with_setup
from tests.utils import *


@with_setup(usual_setup_func, usual_teardown_func)
def test_just_call_it():
def test_just_call_it(usual_setup_usual_teardown):
create_file('1234', 'a')
create_file('1234', 'b')

Expand Down
11 changes: 4 additions & 7 deletions tests/test_formatters/test_py.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#!/usr/bin/env python3
# encoding: utf-8
from nose import with_setup
from tests.utils import *

import subprocess

from parameterized import parameterized
import pytest


def _check_interpreter(interpreter):
Expand All @@ -16,16 +15,14 @@ def _check_interpreter(interpreter):
return False


@parameterized(["python2", "python3"])
@with_setup(usual_setup_func, usual_teardown_func)
def test_paranoia(interpreter):
@pytest.mark.parametrize("interpreter", ["python2", "python3"])
def test_paranoia(usual_setup_usual_teardown, interpreter):
if not _check_interpreter(interpreter):
print(
pytest.skip(
"Interpreter {} does not seem to be working, skipping test".format(
interpreter
)
)
return

create_file('xxx', 'a')
create_file('xxx', 'b')
Expand Down
42 changes: 11 additions & 31 deletions tests/test_formatters/test_sh.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#!/usr/bin/env python3
# encoding: utf-8
from nose import with_setup
from tests.utils import *

import subprocess

from parameterized import parameterized
import pytest


def run_shell_script(shell, sh_path, *args):
Expand All @@ -21,9 +20,7 @@ def filter_part_of_directory(data):
return [e for e in data if e['type'] != 'part_of_directory']


@with_setup(usual_setup_func, usual_teardown_func)
@parameterized([("sh", ), ("bash", ), ("dash", )])
def test_basic(shell):
def test_basic(usual_setup_usual_teardown, shell):
create_file('xxx', 'a')
create_file('xxx', 'b')

Expand Down Expand Up @@ -71,9 +68,7 @@ def test_basic(shell):
assert '/a' in text


@parameterized([("sh", ), ("bash", ), ("dash", )])
@with_setup(usual_setup_func, usual_teardown_func)
def test_paranoia(shell):
def test_paranoia(usual_setup_usual_teardown, shell):
create_file('xxx', 'a')
create_file('xxx', 'b')
create_file('xxx', 'c')
Expand Down Expand Up @@ -124,8 +119,7 @@ def test_paranoia(shell):
assert footer['duplicates'] == 0


@with_setup(usual_setup_func, usual_teardown_func)
def test_anon_pipe():
def test_anon_pipe(usual_setup_usual_teardown):
create_file('xxx', 'long-dummy-file-1')
create_file('xxx', 'long-dummy-file-2')

Expand All @@ -140,9 +134,7 @@ def test_anon_pipe():
assert b'/long-dummy-file-2' in data


@parameterized([("sh", ), ("bash", ), ("dash", )])
@with_setup(usual_setup_func, usual_teardown_func)
def test_hardlink_duplicate_directories(shell):
def test_hardlink_duplicate_directories(usual_setup_usual_teardown, shell):
create_file('xxx', 'dir_a/x')
create_file('xxx', 'dir_b/x')

Expand Down Expand Up @@ -174,12 +166,8 @@ def _check_if_empty_dirs_deleted(shell, inverse_order, sh_path, data):
assert not os.path.exists(data[1]["path"])


@parameterized([
("sh", False), ("bash", False), ("dash", False),
("sh", True), ("bash", True), ("dash", True)
])
@with_setup(usual_setup_func, usual_teardown_func)
def test_remove_empty_dirs(shell, inverse_order):
@pytest.mark.parametrize("inverse_order", [False, True])
def test_remove_empty_dirs(usual_setup_usual_teardown, shell, inverse_order):
create_file('xxx', 'deep/a/b/c/d/e/1')
create_file('xxx', 'deep/x/2')

Expand Down Expand Up @@ -207,12 +195,8 @@ def test_remove_empty_dirs(shell, inverse_order):
_check_if_empty_dirs_deleted(shell, inverse_order, sh_path, data)


@parameterized([
("sh", False), ("bash", False), ("dash", False),
("sh", True), ("bash", True), ("dash", True)
])
@with_setup(usual_setup_func, usual_teardown_func)
def test_remove_empty_dirs_with_dupe_dirs(shell, inverse_order):
@pytest.mark.parametrize("inverse_order", [False, True])
def test_remove_empty_dirs_with_dupe_dirs(usual_setup_usual_teardown, shell, inverse_order):
create_file('xxx', 'deep/a/b/c/d/e/1')
create_file('xxx', 'deep/x/1')

Expand Down Expand Up @@ -240,9 +224,7 @@ def test_remove_empty_dirs_with_dupe_dirs(shell, inverse_order):

_check_if_empty_dirs_deleted(shell, inverse_order, sh_path, data)

@with_setup(usual_setup_func, usual_teardown_func)
@parameterized([("sh", ), ("bash", ), ("dash", )])
def test_cleanup_emptydirs(shell):
def test_cleanup_emptydirs(usual_setup_usual_teardown, shell):
create_file('xxx', 'dir1/a')

# create some ugly dir names
Expand Down Expand Up @@ -271,9 +253,7 @@ def test_cleanup_emptydirs(shell):



@with_setup(usual_setup_func, usual_teardown_func)
@parameterized([("sh", ), ("bash", ), ("dash", )])
def test_keep_parent_timestamps(shell):
def test_keep_parent_timestamps(usual_setup_usual_teardown, shell):
create_file('xxx', 'dir/a')
create_file('xxx', 'dir/b')

Expand Down
Loading