diff --git a/.gitignore b/.gitignore index 893eeec1..731c935f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ geckodriver.log # pyenv .python-version + +# codecov +.coverage +coverage.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index feecccd7..82e4906f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ override `selenium_standalone` fixture with `selenium_standalone_refresh`. [#65](https://github.com/pyodide/pytest-pyodide/pull/65) +- Breaking: `--runtime` commandline flag now requires runtimes to be comma-separated. + [#76](https://github.com/pyodide/pytest-pyodide/pull/76) + - Add support for a custom `SimpleHTTPRequestHandler` class in the pytest webserver code, by passing the `handler_cls` parameter in the `spawn_web_server` function. diff --git a/pytest_pyodide/hook.py b/pytest_pyodide/hook.py index 0c401d5e..3b42cf3c 100644 --- a/pytest_pyodide/hook.py +++ b/pytest_pyodide/hook.py @@ -18,12 +18,25 @@ RUNTIMES_NO_HOST = [f"{runtime}-no-host" for runtime in RUNTIMES] -def _filter_runtimes(runtime: list[str]) -> tuple[bool, set[str]]: +def _filter_runtimes(runtime: str) -> tuple[bool, set[str]]: + """Preprocess the given runtime commandline parameter + + >>> _filter_runtimes("chrome") + (True, {'chrome'}) + >>> _filter_runtimes("chrome-no-host") + (False, {'chrome'}) + >>> _filter_runtimes("chrome-no-host, host, firefox") + (True, ...) + """ + # Always run host test, unless 'no-host' is given. run_host = True + # "chrome, firefox, node" ==> ["chrome", "firefox", "node"] + runtimes = [rt.strip() for rt in runtime.split(",")] + # remove duplicates - runtime_set = set(runtime) + runtime_set = set(runtimes) runtime_filtered = set() for rt in runtime_set: @@ -33,11 +46,15 @@ def _filter_runtimes(runtime: list[str]) -> tuple[bool, set[str]]: runtime_filtered.add(rt) - # If '--rt chrome-no-host --rt host' is given, we run host tests. + # If '--rt "chrome-no-host, host"' is given, we run host tests. run_host = run_host or ("host" in runtime_filtered) runtime_filtered.discard("host") + for rt in runtime_filtered: + if rt not in RUNTIMES: + raise ValueError(f"Invalid runtime: {rt}") + return run_host, runtime_filtered @@ -89,10 +106,8 @@ def pytest_addoption(parser): "--rt", "--runtime", dest="runtime", - nargs="+", - default=["node"], - choices=RUNTIMES_AND_HOST + RUNTIMES_NO_HOST, - help="Select runtime (default: %(default)s)", + default="node", + help="Select runtimes to run tests (default: %(default)s)", ) diff --git a/tests/test_options.py b/tests/test_options.py index e7186d2c..e11c1574 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -56,20 +56,44 @@ def test_option(request): "firefox", "safari", "node", - "firefox chrome", + "firefox,chrome", ], ) def test_runtime(pytester, _runtime): - runtimes = _runtime.split() + runtimes = _runtime.split(",") pytester.makepyfile( f""" import pytest - def test_option(request): - assert request.config.getoption("--runtime") == {runtimes!r} + def test_option(): + assert pytest.pyodide_runtimes == set({runtimes!r}) """ ) - result = pytester.runpytest("--runtime", *runtimes) + result = pytester.runpytest("--runtime", _runtime) result.assert_outcomes(passed=1) + + +@pytest.mark.parametrize( + "_runtime", + [ + "invalid", + ], +) +def test_invalid_runtime(pytester, _runtime): + + runtimes = _runtime.split(",") + + pytester.makepyfile( + f""" + import pytest + def test_option(): + assert pytest.pyodide_runtimes == set({runtimes!r}) + """ + ) + + # TODO: catch internal errors directly? + with pytest.raises(ValueError, match="Pytest terminal summary report not found"): + result = pytester.runpytest("--runtime", _runtime) + result.assert_outcomes(errors=1)