done
This commit is contained in:
		
							
								
								
									
										263
									
								
								lib/python3.11/site-packages/dash/testing/plugin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								lib/python3.11/site-packages/dash/testing/plugin.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,263 @@
 | 
			
		||||
# pylint: disable=missing-docstring,redefined-outer-name
 | 
			
		||||
from typing import Any
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
from .consts import SELENIUM_GRID_DEFAULT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# pylint: disable=too-few-public-methods
 | 
			
		||||
class MissingDashTesting:
 | 
			
		||||
    def __init__(self, **kwargs):
 | 
			
		||||
        raise Exception(
 | 
			
		||||
            "dash[testing] was not installed. "
 | 
			
		||||
            "Please install to use the dash testing fixtures."
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def __enter__(self) -> Any:
 | 
			
		||||
        """Implemented to satisfy type checking."""
 | 
			
		||||
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
    def __exit__(self, exc_type, exc_val, exc_tb) -> bool:
 | 
			
		||||
        """Implemented to satisfy type checking."""
 | 
			
		||||
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from dash.testing.application_runners import (
 | 
			
		||||
        ThreadedRunner,
 | 
			
		||||
        ProcessRunner,
 | 
			
		||||
        RRunner,
 | 
			
		||||
        JuliaRunner,
 | 
			
		||||
        MultiProcessRunner,
 | 
			
		||||
    )
 | 
			
		||||
    from dash.testing.browser import Browser
 | 
			
		||||
    from dash.testing.composite import DashComposite, DashRComposite, DashJuliaComposite
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=unused-import
 | 
			
		||||
    import dash_testing_stub  # noqa: F401
 | 
			
		||||
 | 
			
		||||
    _installed = True
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # Running pytest without dash[testing] installed.
 | 
			
		||||
    ThreadedRunner = MissingDashTesting
 | 
			
		||||
    ProcessRunner = MissingDashTesting
 | 
			
		||||
    MultiProcessRunner = MissingDashTesting
 | 
			
		||||
    RRunner = MissingDashTesting
 | 
			
		||||
    JuliaRunner = MissingDashTesting
 | 
			
		||||
    Browser = MissingDashTesting
 | 
			
		||||
    DashComposite = MissingDashTesting
 | 
			
		||||
    DashRComposite = MissingDashTesting
 | 
			
		||||
    DashJuliaComposite = MissingDashTesting
 | 
			
		||||
    _installed = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pytest_addoption(parser):
 | 
			
		||||
    if not _installed:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    dash = parser.getgroup("Dash", "Dash Integration Tests")
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--webdriver",
 | 
			
		||||
        choices=("Chrome", "Firefox"),
 | 
			
		||||
        default="Chrome",
 | 
			
		||||
        help="Name of the selenium driver to use",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--remote", action="store_true", help="instruct pytest to use selenium grid"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--remote-url",
 | 
			
		||||
        action="store",
 | 
			
		||||
        default=SELENIUM_GRID_DEFAULT,
 | 
			
		||||
        help="set a different selenium grid remote url if other than default",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--headless", action="store_true", help="set this flag to run in headless mode"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--percy-assets",
 | 
			
		||||
        action="store",
 | 
			
		||||
        default="tests/assets",
 | 
			
		||||
        help="configure how Percy will discover your app's assets",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--nopercyfinalize",
 | 
			
		||||
        action="store_false",
 | 
			
		||||
        help="set this flag to control percy finalize at CI level",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    dash.addoption(
 | 
			
		||||
        "--pause",
 | 
			
		||||
        action="store_true",
 | 
			
		||||
        help="pause using pdb after opening the test app, so you can interact with it",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.tryfirst
 | 
			
		||||
def pytest_addhooks(pluginmanager):
 | 
			
		||||
    if not _installed:
 | 
			
		||||
        return
 | 
			
		||||
    # https://github.com/pytest-dev/pytest-xdist/blob/974bd566c599dc6a9ea291838c6f226197208b46/xdist/plugin.py#L67
 | 
			
		||||
    # avoid warnings with pytest-2.8
 | 
			
		||||
    from dash.testing import newhooks  # pylint: disable=import-outside-toplevel
 | 
			
		||||
 | 
			
		||||
    method = getattr(pluginmanager, "add_hookspecs", None)
 | 
			
		||||
    if method is None:
 | 
			
		||||
        method = pluginmanager.addhooks  # pragma: no cover
 | 
			
		||||
    method(newhooks)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
 | 
			
		||||
def pytest_runtest_makereport(item, call):  # pylint: disable=unused-argument
 | 
			
		||||
    # execute all other hooks to obtain the report object
 | 
			
		||||
    outcome = yield
 | 
			
		||||
    if not _installed:
 | 
			
		||||
        return
 | 
			
		||||
    rep = outcome.get_result()
 | 
			
		||||
 | 
			
		||||
    # we only look at actual failing test calls, not setup/teardown
 | 
			
		||||
    if rep.when == "call" and rep.failed and hasattr(item, "funcargs"):
 | 
			
		||||
        for name, fixture in item.funcargs.items():
 | 
			
		||||
            try:
 | 
			
		||||
                if name in {"dash_duo", "dash_br", "dashr", "dashjl"}:
 | 
			
		||||
                    fixture.take_snapshot(item.name)
 | 
			
		||||
            except Exception as e:  # pylint: disable=broad-except
 | 
			
		||||
                print(e)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
# Fixtures
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dash_thread_server() -> ThreadedRunner:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    """Start a local dash server in a new thread."""
 | 
			
		||||
    with ThreadedRunner() as starter:
 | 
			
		||||
        yield starter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dash_process_server() -> ProcessRunner:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    """Start a Dash server with subprocess.Popen and waitress-serve."""
 | 
			
		||||
    with ProcessRunner() as starter:
 | 
			
		||||
        yield starter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dash_multi_process_server() -> MultiProcessRunner:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with MultiProcessRunner() as starter:
 | 
			
		||||
        yield starter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dashr_server() -> RRunner:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with RRunner() as starter:
 | 
			
		||||
        yield starter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dashjl_server() -> JuliaRunner:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with JuliaRunner() as starter:
 | 
			
		||||
        yield starter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dash_br(request, tmpdir) -> Browser:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with Browser(
 | 
			
		||||
        browser=request.config.getoption("webdriver"),
 | 
			
		||||
        remote=request.config.getoption("remote"),
 | 
			
		||||
        remote_url=request.config.getoption("remote_url"),
 | 
			
		||||
        headless=request.config.getoption("headless"),
 | 
			
		||||
        options=request.config.hook.pytest_setup_options(),
 | 
			
		||||
        download_path=tmpdir.mkdir("download").strpath,
 | 
			
		||||
        percy_assets_root=request.config.getoption("percy_assets"),
 | 
			
		||||
        percy_finalize=request.config.getoption("nopercyfinalize"),
 | 
			
		||||
        pause=request.config.getoption("pause"),
 | 
			
		||||
    ) as browser:
 | 
			
		||||
        yield browser
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dash_duo(request, dash_thread_server, tmpdir) -> DashComposite:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with DashComposite(
 | 
			
		||||
        server=dash_thread_server,
 | 
			
		||||
        browser=request.config.getoption("webdriver"),
 | 
			
		||||
        remote=request.config.getoption("remote"),
 | 
			
		||||
        remote_url=request.config.getoption("remote_url"),
 | 
			
		||||
        headless=request.config.getoption("headless"),
 | 
			
		||||
        options=request.config.hook.pytest_setup_options(),
 | 
			
		||||
        download_path=tmpdir.mkdir("download").strpath,
 | 
			
		||||
        percy_assets_root=request.config.getoption("percy_assets"),
 | 
			
		||||
        percy_finalize=request.config.getoption("nopercyfinalize"),
 | 
			
		||||
        pause=request.config.getoption("pause"),
 | 
			
		||||
    ) as dc:
 | 
			
		||||
        yield dc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dash_duo_mp(request, dash_multi_process_server, tmpdir) -> DashComposite:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with DashComposite(
 | 
			
		||||
        server=dash_multi_process_server,
 | 
			
		||||
        browser=request.config.getoption("webdriver"),
 | 
			
		||||
        remote=request.config.getoption("remote"),
 | 
			
		||||
        remote_url=request.config.getoption("remote_url"),
 | 
			
		||||
        headless=request.config.getoption("headless"),
 | 
			
		||||
        options=request.config.hook.pytest_setup_options(),
 | 
			
		||||
        download_path=tmpdir.mkdir("download").strpath,
 | 
			
		||||
        percy_assets_root=request.config.getoption("percy_assets"),
 | 
			
		||||
        percy_finalize=request.config.getoption("nopercyfinalize"),
 | 
			
		||||
        pause=request.config.getoption("pause"),
 | 
			
		||||
    ) as dc:
 | 
			
		||||
        yield dc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dashr(request, dashr_server, tmpdir) -> DashRComposite:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with DashRComposite(
 | 
			
		||||
        server=dashr_server,
 | 
			
		||||
        browser=request.config.getoption("webdriver"),
 | 
			
		||||
        remote=request.config.getoption("remote"),
 | 
			
		||||
        remote_url=request.config.getoption("remote_url"),
 | 
			
		||||
        headless=request.config.getoption("headless"),
 | 
			
		||||
        options=request.config.hook.pytest_setup_options(),
 | 
			
		||||
        download_path=tmpdir.mkdir("download").strpath,
 | 
			
		||||
        percy_assets_root=request.config.getoption("percy_assets"),
 | 
			
		||||
        percy_finalize=request.config.getoption("nopercyfinalize"),
 | 
			
		||||
        pause=request.config.getoption("pause"),
 | 
			
		||||
    ) as dc:
 | 
			
		||||
        yield dc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dashjl(request, dashjl_server, tmpdir) -> DashJuliaComposite:  # type: ignore[reportInvalidTypeForm]
 | 
			
		||||
    with DashJuliaComposite(
 | 
			
		||||
        server=dashjl_server,
 | 
			
		||||
        browser=request.config.getoption("webdriver"),
 | 
			
		||||
        remote=request.config.getoption("remote"),
 | 
			
		||||
        remote_url=request.config.getoption("remote_url"),
 | 
			
		||||
        headless=request.config.getoption("headless"),
 | 
			
		||||
        options=request.config.hook.pytest_setup_options(),
 | 
			
		||||
        download_path=tmpdir.mkdir("download").strpath,
 | 
			
		||||
        percy_assets_root=request.config.getoption("percy_assets"),
 | 
			
		||||
        percy_finalize=request.config.getoption("nopercyfinalize"),
 | 
			
		||||
        pause=request.config.getoption("pause"),
 | 
			
		||||
    ) as dc:
 | 
			
		||||
        yield dc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def diskcache_manager():
 | 
			
		||||
    from dash.background_callback import (  # pylint: disable=import-outside-toplevel
 | 
			
		||||
        DiskcacheManager,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    return DiskcacheManager()
 | 
			
		||||
		Reference in New Issue
	
	Block a user