diff --git a/template/tests/test_examples.py.jinja b/template/tests/test_examples.py.jinja deleted file mode 100644 index 9fb18f1..0000000 --- a/template/tests/test_examples.py.jinja +++ /dev/null @@ -1,44 +0,0 @@ -{% if include_examples %}"""Tests for marimo notebook examples. - -This module validates that all notebook examples in the examples/ directory -can be executed successfully as Python scripts. - -Marimo notebooks can be run directly with Python: -https://docs.marimo.io/getting_started/quickstart/#run-as-scripts -""" - -import pathlib -import subprocess - -import pytest - -# Discover all example notebooks -EXAMPLES_DIR = pathlib.Path(__file__).parent.parent / "examples" - - -@pytest.mark.example -@pytest.mark.parametrize("notebook_file", sorted(EXAMPLES_DIR.glob("*.py"))) -def test_notebook_runs_without_error(notebook_file: pathlib.Path) -> None: - """Test that a notebook example runs successfully as a script. - - Marimo notebooks can be run directly as Python scripts. - See: https://docs.marimo.io/getting_started/quickstart/#run-as-scripts - - Args: - notebook_file: Path to the notebook file to test. - """ - # stdin is closed and the run is bounded: a notebook that blocks on input -- - # a stray breakpoint(), an input() -- otherwise inherits the terminal's stdin - # and hangs here forever with no output instead of failing. - result = subprocess.run( - ["python", str(notebook_file)], - capture_output=True, - text=True, - check=False, - stdin=subprocess.DEVNULL, - timeout=300, - ) - assert result.returncode == 0, ( - f"Notebook {notebook_file.name} failed with:\\nSTDOUT:\\n{result.stdout}\\nSTDERR:\\n{result.stderr}" - ) -{%- endif %} diff --git a/template/tests/{% if include_examples %}test_examples.py{% endif %}.jinja b/template/tests/{% if include_examples %}test_examples.py{% endif %}.jinja index 4f2c58b..6e8175d 100644 --- a/template/tests/{% if include_examples %}test_examples.py{% endif %}.jinja +++ b/template/tests/{% if include_examples %}test_examples.py{% endif %}.jinja @@ -39,6 +39,6 @@ def test_notebook_runs_without_error(notebook_file: pathlib.Path) -> None: timeout=300, ) assert result.returncode == 0, ( - f"Notebook {notebook_file.name} failed with:\\nSTDOUT:\\n{result.stdout}\\nSTDERR:\\n{result.stderr}" + f"Notebook {notebook_file.name} failed with:\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}" ) {% endif -%} diff --git a/tests/test_template.py b/tests/test_template.py index c712546..c76f628 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -564,6 +564,16 @@ def test_examples_directory_when_enabled(copie): assert "subprocess.run" in test_examples_content assert '["python", str(notebook_file)]' in test_examples_content assert "https://docs.marimo.io/getting_started/quickstart/#run-as-scripts" in test_examples_content + # The failure message must use a real newline escape (single backslash). A doubled + # backslash in the .jinja source renders as a literal two-character \n, printing the + # diagnostic on one line with a visible \n instead of breaking it. + assert r"failed with:\nSTDOUT" in test_examples_content, "assert message lost its newline escape" + assert r"failed with:\\nSTDOUT" not in test_examples_content, ( + "assert message double-escapes the newline; use a single backslash in the .jinja source" + ) + # The bounded-run guards from v0.27.0 must survive here too. + assert "stdin=subprocess.DEVNULL" in test_examples_content + assert "timeout=" in test_examples_content # Check docs/examples/ directory exists for exports docs_examples_dir = result.project_dir / "docs" / "examples" @@ -641,6 +651,14 @@ def test_examples_directory_when_disabled(copie): noxfile_content = (result.project_dir / "noxfile.py").read_text(encoding="utf-8") assert "def test_examples(session:" not in noxfile_content + # The example test itself must not exist at all. A previous template shipped two + # near-duplicate .jinja sources for it -- one filename-gated, one not -- and the + # ungated one rendered a stray 1-byte tests/test_examples.py here, invisible because + # an empty file breaks nothing. + assert not (result.project_dir / "tests" / "test_examples.py").exists(), ( + "tests/test_examples.py should not exist when include_examples=False" + ) + # Check justfile doesn't have example command justfile_content = (result.project_dir / "justfile").read_text(encoding="utf-8") # Should not have the example command, but might have other content