diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d5a85fc8..b86c7f9e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Expose `shiny.playwright`, `shiny.run`, and `shiny.pytest` modules that allow users to testing their Shiny apps. (#1448, #1456, #1481) * `shiny.playwright` contains `controller` and `expect` submodules. `controller` will contain many classes to interact with (and verify!) your Shiny app using Playwright. `expect` contains expectation functions that enhance standard Playwright expectation methods. * `shiny.run` contains the `run_shiny_app` command and the return type `ShinyAppProc`. `ShinyAppProc` can be used to type the Shiny app pytest fixtures. - * `shiny.pytest` contains pytest test fixtures. The `local_app` pytest fixture is automatically available and runs a sibling `app.py` file. Where as `create_app_fixture(PATH_TO_APP)` allows for a Shiny app to be instantiated from a different folder. + * `shiny.pytest` contains pytest test fixtures. The `local_app` pytest fixture is automatically available and runs a sibling `app.py` file. Where as `create_app_fixture(PATH_TO_APP)` allows for a relative path to a Shiny app to be instantiated from a different folder. * Added CLI command `shiny add test` to add a test file to an existing Shiny app. (#1461) diff --git a/shiny/pytest/_fixture.py b/shiny/pytest/_fixture.py index e0c3c6df2..bb649e7f5 100644 --- a/shiny/pytest/_fixture.py +++ b/shiny/pytest/_fixture.py @@ -1,6 +1,6 @@ from __future__ import annotations -from pathlib import PurePath +from pathlib import Path, PurePath from typing import Literal, Union import pytest @@ -29,13 +29,22 @@ def create_app_fixture( ---------- app The path to the Shiny app file. + + If `app` is a `Path` or `PurePath` instance and `Path(app).is_file()` returns `True`, then this value will be used directly. + Note, `app`'s file path will be checked from where corresponding `pytest` test is collected, not necessarily where `create_app_fixture()` is called. + + Otherwise, all `app` paths will be considered to be relative paths from where the test function was collected. + + To be sure that your app path is always relative, supply a `str` value. scope The scope of the fixture. """ @pytest.fixture(scope=scope) - def fixture_func(): - sa_gen = shiny_app_gen(app) + def fixture_func(request: pytest.FixtureRequest): + app_purepath_exists = isinstance(app, PurePath) and Path(app).is_file() + app_path = app if app_purepath_exists else request.path.parent / app + sa_gen = shiny_app_gen(app_path) yield next(sa_gen) return fixture_func