mirror of https://github.com/streamlink/streamlink
tests: add custom markers for conditional tests
- Remove `posix_only`/`windows_only` `skipIf` marker aliases - Add `posix_only`/`windows_only` custom markers based on generic conditional test markers in the root conftest module
This commit is contained in:
parent
5ff3b32ce5
commit
8dae1eea72
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
import signal
|
||||
|
||||
import freezegun.config
|
||||
|
@ -23,10 +22,3 @@ freezegun.config.configure(extend_ignore_list=["_pytest.runner", "_pytest.termin
|
|||
# make pytest rewrite assertions in dynamically parametrized plugin tests
|
||||
# https://docs.pytest.org/en/stable/how-to/writing_plugins.html#assertion-rewriting
|
||||
pytest.register_assert_rewrite("tests.plugins")
|
||||
|
||||
|
||||
windows_only = pytest.mark.skipif(os.name != "nt", reason="test only applicable on Windows")
|
||||
posix_only = pytest.mark.skipif(os.name != "posix", reason="test only applicable on a POSIX OS")
|
||||
|
||||
|
||||
__all__ = ["windows_only", "posix_only"]
|
||||
|
|
|
@ -8,7 +8,6 @@ from unittest.mock import Mock, call, patch
|
|||
import pytest
|
||||
|
||||
from streamlink_cli.output import FileOutput, PlayerOutput
|
||||
from tests import posix_only, windows_only
|
||||
|
||||
|
||||
@patch("streamlink_cli.output.stdout")
|
||||
|
@ -70,12 +69,12 @@ class TestFileOutput(unittest.TestCase):
|
|||
|
||||
return mock_path
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
@patch("builtins.open")
|
||||
def test_open_posix(self, mock_open: Mock, mock_stdout: Mock):
|
||||
self._test_open(mock_open, mock_stdout)
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
@patch("streamlink_cli.output.msvcrt")
|
||||
@patch("builtins.open")
|
||||
def test_open_windows(self, mock_open: Mock, mock_msvcrt: Mock, mock_stdout: Mock):
|
||||
|
|
|
@ -4,7 +4,6 @@ from unittest.mock import Mock, call, patch
|
|||
import pytest
|
||||
|
||||
from streamlink_cli.output import PlayerOutput
|
||||
from tests import posix_only, windows_only
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
@ -28,25 +27,25 @@ def mock_popen(playeroutput: PlayerOutput):
|
|||
pytest.param(
|
||||
dict(cmd="mpv", title="foo bar"),
|
||||
["mpv", "--force-media-title=foo bar", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="MPV title POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
{"cmd": "mpv.exe", "title": "foo bar"},
|
||||
"mpv.exe \"--force-media-title=foo bar\" -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="MPV title Windows",
|
||||
),
|
||||
pytest.param(
|
||||
{"cmd": "vlc", "title": "foo bar"},
|
||||
["vlc", "--input-title-format", "foo bar", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="VLC title POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
{"cmd": "vlc.exe", "title": "foo bar"},
|
||||
"vlc.exe --input-title-format \"foo bar\" -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="VLC title Windows",
|
||||
),
|
||||
], indirect=["playeroutput"])
|
||||
|
@ -61,73 +60,73 @@ def test_playeroutput(mock_popen: Mock, playeroutput: PlayerOutput, expected):
|
|||
pytest.param(
|
||||
dict(cmd="foo"),
|
||||
["foo", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="None POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar"),
|
||||
["foo", "--bar", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="Implicit POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {playerinput}"),
|
||||
["foo", "--bar", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="Explicit POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {filename}"),
|
||||
["foo", "--bar", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="Fallback POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {playerinput} {filename}"),
|
||||
["foo", "--bar", "-", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="Fallback duplicate POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {qux}"),
|
||||
["foo", "--bar", "{qux}", "-"],
|
||||
marks=posix_only,
|
||||
marks=pytest.mark.posix_only,
|
||||
id="Unknown POSIX",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo"),
|
||||
"foo -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="None Windows",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar"),
|
||||
"foo --bar -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="Implicit Windows",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {playerinput}"),
|
||||
"foo --bar -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="Explicit Windows",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {filename}"),
|
||||
"foo --bar -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="Fallback Windows",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {playerinput} {filename}"),
|
||||
"foo --bar - -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="Fallback duplicate Windows",
|
||||
),
|
||||
pytest.param(
|
||||
dict(cmd="foo", args="--bar {qux}"),
|
||||
"foo --bar {qux} -",
|
||||
marks=windows_only,
|
||||
marks=pytest.mark.windows_only,
|
||||
id="Unknown Windows",
|
||||
),
|
||||
], indirect=["playeroutput"])
|
||||
|
|
|
@ -2,10 +2,11 @@ import unittest
|
|||
from pathlib import Path
|
||||
from unittest.mock import ANY, Mock, call, patch
|
||||
|
||||
import pytest
|
||||
|
||||
import streamlink_cli.main
|
||||
import tests
|
||||
from streamlink import Streamlink
|
||||
from tests import posix_only, windows_only
|
||||
|
||||
|
||||
class CommandLineTestCase(unittest.TestCase):
|
||||
|
@ -51,7 +52,7 @@ class CommandLineTestCase(unittest.TestCase):
|
|||
assert mock_call.call_args_list == [call(commandline, stderr=ANY, stdout=ANY)]
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
class TestCommandLinePOSIX(CommandLineTestCase):
|
||||
"""
|
||||
Commandline tests under POSIX-like operating systems
|
||||
|
@ -89,7 +90,7 @@ class TestCommandLinePOSIX(CommandLineTestCase):
|
|||
["/usr/bin/player", "-v", "-"])
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
class TestCommandLineWindows(CommandLineTestCase):
|
||||
"""
|
||||
Commandline tests for Windows
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
from unittest.mock import Mock, patch
|
||||
|
||||
from tests import posix_only, windows_only
|
||||
import pytest
|
||||
|
||||
from tests.cli.test_cmdline import CommandLineTestCase
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
@patch("streamlink_cli.main.NamedPipe", Mock(return_value=Mock(path="/tmp/streamlinkpipe")))
|
||||
class TestCommandLineWithPlayerFifoPosix(CommandLineTestCase):
|
||||
def test_player_fifo_default(self):
|
||||
|
@ -16,7 +17,7 @@ class TestCommandLineWithPlayerFifoPosix(CommandLineTestCase):
|
|||
)
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
@patch("streamlink_cli.main.NamedPipe", Mock(return_value=Mock(path="\\\\.\\pipe\\streamlinkpipe")))
|
||||
class TestCommandLineWithPlayerFifoWindows(CommandLineTestCase):
|
||||
def test_player_fifo_default(self):
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from tests import posix_only, windows_only
|
||||
import pytest
|
||||
|
||||
from tests.cli.test_cmdline import CommandLineTestCase
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
class TestCommandLineWithTitlePOSIX(CommandLineTestCase):
|
||||
def test_open_player_with_title_vlc(self):
|
||||
self._test_args(["streamlink", "-p", "/usr/bin/vlc",
|
||||
|
@ -26,7 +27,7 @@ class TestCommandLineWithTitlePOSIX(CommandLineTestCase):
|
|||
["mpv", "--force-media-title=★ ★ ★", "-"])
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
class TestCommandLineWithTitleWindows(CommandLineTestCase):
|
||||
def test_open_player_with_title_vlc(self):
|
||||
self._test_args(
|
||||
|
|
|
@ -28,7 +28,6 @@ from streamlink_cli.main import (
|
|||
resolve_stream_name,
|
||||
)
|
||||
from streamlink_cli.output import FileOutput, PlayerOutput
|
||||
from tests import posix_only, windows_only
|
||||
from tests.plugin.testplugin import TestPlugin as _TestPlugin
|
||||
|
||||
|
||||
|
@ -637,7 +636,7 @@ class TestCLIMainLoggingStreams(_TestCLIMainLogging):
|
|||
|
||||
|
||||
class TestCLIMainLoggingInfos(_TestCLIMainLogging):
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
@patch("streamlink_cli.main.log")
|
||||
def test_log_root_warning(self, mock_log):
|
||||
self.subject(["streamlink"], euid=0)
|
||||
|
@ -774,7 +773,7 @@ class TestCLIMainLoggingLogfile(_TestCLIMainLogging):
|
|||
)
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
class TestCLIMainLoggingLogfilePosix(_TestCLIMainLogging):
|
||||
@patch("sys.stdout")
|
||||
@patch("builtins.open")
|
||||
|
@ -813,7 +812,7 @@ class TestCLIMainLoggingLogfilePosix(_TestCLIMainLogging):
|
|||
)
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
class TestCLIMainLoggingLogfileWindows(_TestCLIMainLogging):
|
||||
@patch("sys.stdout")
|
||||
@patch("builtins.open")
|
||||
|
|
|
@ -5,7 +5,6 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
|
||||
from streamlink_cli.utils.path import replace_chars, replace_path
|
||||
from tests import posix_only, windows_only
|
||||
|
||||
|
||||
@pytest.mark.parametrize("char", list(range(32)))
|
||||
|
@ -13,29 +12,29 @@ def test_replace_chars_unprintable(char: int):
|
|||
assert replace_chars(f"foo{chr(char)}{chr(char)}bar") == "foo_bar", "Replaces unprintable characters"
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
@pytest.mark.parametrize("char", "/".split())
|
||||
def test_replace_chars_posix(char: str):
|
||||
assert replace_chars(f"foo{char}{char}bar") == "foo_bar", "Replaces multiple unsupported characters in a row"
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
@pytest.mark.parametrize("char", "\x7f\"*/:<>?\\|".split())
|
||||
def test_replace_chars_windows(char: str):
|
||||
assert replace_chars(f"foo{char}{char}bar") == "foo_bar", "Replaces multiple unsupported characters in a row"
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
def test_replace_chars_posix_all():
|
||||
assert replace_chars("".join(chr(i) for i in range(32)) + "/") == "_"
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
def test_replace_chars_windows_all():
|
||||
assert replace_chars("".join(chr(i) for i in range(32)) + "\x7f\"*/:<>?\\|") == "_"
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
def test_replace_chars_posix_override():
|
||||
all_chars = "".join(chr(i) for i in range(32)) + "\x7f\"*:/<>?\\|"
|
||||
assert replace_chars(all_chars) == "_\x7f\"*:_<>?\\|"
|
||||
|
@ -45,7 +44,7 @@ def test_replace_chars_posix_override():
|
|||
assert replace_chars(all_chars, "win32") == "_"
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
def test_replace_chars_windows_override():
|
||||
all_chars = "".join(chr(i) for i in range(32)) + "\x7f\"*:/<>?\\|"
|
||||
assert replace_chars(all_chars) == "_"
|
||||
|
@ -68,14 +67,14 @@ def test_replace_path():
|
|||
assert replace_path(path, mapper) == expected, "Only replaces mapped parts which are in the special parts tuple"
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
def test_replace_path_expanduser_posix():
|
||||
with patch.object(os, "environ", {"HOME": "/home/foo"}):
|
||||
assert replace_path("~/bar", lambda s: s) == Path("/home/foo/bar")
|
||||
assert replace_path("foo/bar", lambda s: dict(foo="~").get(s, s)) == Path("~/bar")
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
def test_replace_path_expanduser_windows():
|
||||
with patch.object(os, "environ", {"USERPROFILE": "C:\\Users\\foo"}):
|
||||
assert replace_path("~\\bar", lambda s: s) == Path("C:\\Users\\foo\\bar")
|
||||
|
|
|
@ -7,7 +7,6 @@ import freezegun
|
|||
import pytest
|
||||
|
||||
from streamlink_cli.utils.progress import Progress, ProgressFormatter
|
||||
from tests import posix_only, windows_only
|
||||
|
||||
|
||||
class TestProgressFormatter:
|
||||
|
@ -183,7 +182,7 @@ class TestPrint:
|
|||
def progress(self, stream: StringIO):
|
||||
return Progress(stream, Mock())
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
def test_print_posix(self, progress: Progress, stream: StringIO):
|
||||
progress.print_inplace("foo")
|
||||
progress.print_inplace("barbaz")
|
||||
|
@ -192,7 +191,7 @@ class TestPrint:
|
|||
progress.print_end()
|
||||
assert stream.getvalue() == "\rfoo \rbarbaz \r0123456789\rabcdefghijk\n"
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
def test_print_windows(self, progress: Progress, stream: StringIO):
|
||||
progress.print_inplace("foo")
|
||||
progress.print_inplace("barbaz")
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import os
|
||||
import sys
|
||||
from typing import List
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
_TEST_CONDITION_MARKERS: Dict[str, Tuple[bool, str]] = {
|
||||
"posix_only": (os.name == "posix", "only applicable on a POSIX OS"),
|
||||
"windows_only": (os.name == "nt", "only applicable on Windows"),
|
||||
}
|
||||
|
||||
_TEST_PRIORITIES = (
|
||||
"tests/testutils/",
|
||||
"tests/utils/",
|
||||
|
@ -15,6 +21,16 @@ _TEST_PRIORITIES = (
|
|||
)
|
||||
|
||||
|
||||
def pytest_configure(config: pytest.Config):
|
||||
config.addinivalue_line("markers", "posix_only: tests which are only applicable on a POSIX OS")
|
||||
config.addinivalue_line("markers", "windows_only: tests which are only applicable on Windows")
|
||||
config.addinivalue_line("markers", "nomockedhttprequest: tests where no mocked HTTP request will be made")
|
||||
|
||||
|
||||
def pytest_runtest_setup(item: pytest.Item):
|
||||
_check_test_condition(item)
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(items: List[pytest.Item]): # pragma: no cover
|
||||
default = next((idx for idx, string in enumerate(_TEST_PRIORITIES) if string is None), sys.maxsize)
|
||||
priorities = {
|
||||
|
@ -31,5 +47,10 @@ def pytest_collection_modifyitems(items: List[pytest.Item]): # pragma: no cover
|
|||
items.sort(key=lambda item: priorities.get(item, default))
|
||||
|
||||
|
||||
def pytest_configure(config: pytest.Config):
|
||||
config.addinivalue_line("markers", "nomockedhttprequest: tests where no mocked HTTP request will be made")
|
||||
def _check_test_condition(item: pytest.Item): # pragma: no cover
|
||||
for m in item.iter_markers():
|
||||
if m.name not in _TEST_CONDITION_MARKERS:
|
||||
continue
|
||||
cond, msg = _TEST_CONDITION_MARKERS[m.name]
|
||||
if not cond:
|
||||
pytest.skip(msg if not m.args and not m.kwargs else f"{msg} ({m.kwargs.get('reason') or m.args[0]})")
|
||||
|
|
|
@ -5,7 +5,6 @@ from unittest.mock import Mock, call, patch
|
|||
import pytest
|
||||
|
||||
from streamlink.utils.named_pipe import NamedPipe, NamedPipeBase, NamedPipePosix, NamedPipeWindows
|
||||
from tests import posix_only, windows_only
|
||||
|
||||
|
||||
try:
|
||||
|
@ -78,7 +77,7 @@ class TestNamedPipe(unittest.TestCase):
|
|||
]
|
||||
|
||||
|
||||
@posix_only
|
||||
@pytest.mark.posix_only()
|
||||
class TestNamedPipePosix(unittest.TestCase):
|
||||
def test_export(self):
|
||||
assert NamedPipe is NamedPipePosix
|
||||
|
@ -121,7 +120,7 @@ class TestNamedPipePosix(unittest.TestCase):
|
|||
assert not reader.is_alive()
|
||||
|
||||
|
||||
@windows_only
|
||||
@pytest.mark.windows_only()
|
||||
class TestNamedPipeWindows(unittest.TestCase):
|
||||
def test_export(self):
|
||||
assert NamedPipe is NamedPipeWindows
|
||||
|
|
Loading…
Reference in New Issue