Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
789b682
Python: add unit tests for colors.py
gusthoff Jun 19, 2026
3f1fc47
Python: add pytest + pytest-cov as optional test dependencies
gusthoff Jun 19, 2026
842a3ea
Python: add unit tests for toolchain_info.py
gusthoff Jun 19, 2026
3808c1e
Python: add unit tests for fmt_utils.py
gusthoff Jun 19, 2026
1cbb17c
Python: configure pytest and coverage in pyproject.toml
gusthoff Jun 19, 2026
daa517b
Python: add unit tests for toolchain_setup.py
gusthoff Jun 19, 2026
050a183
Python: add unit tests for resource.py
gusthoff Jun 19, 2026
594cb63
Makefile: add test_rst_pipeline target for epub VM
gusthoff Jun 19, 2026
14ed13c
Python: add unit tests for extract_projects.py
gusthoff Jun 19, 2026
ee1d46d
Python: add unit tests for checks.py
gusthoff Jun 19, 2026
e20f850
Docs: document how to install test deps and run the pytest suite
gusthoff Jun 19, 2026
71790f0
Python: add unit tests for check_projects.py
gusthoff Jun 19, 2026
2e13dc2
Python: add unit tests for blocks.py
gusthoff Jun 19, 2026
a7dfc81
Docs: cross-link unit test suite from root README testing section
gusthoff Jun 19, 2026
a0faa2a
Python: add unit tests for check_code_block.py
gusthoff Jun 19, 2026
691e1a1
Python: add edge-case unit tests for chop.py
gusthoff Jun 19, 2026
ae048b2
Merge feat/pytest-infra: pytest + coverage setup for rst_code_example…
gusthoff Jun 19, 2026
0f723ff
Python: update coverage threshold and exclude CLI entry points
gusthoff Jun 19, 2026
76504e9
Merge feat/pure-module-tests: unit tests for pure Python modules
gusthoff Jun 19, 2026
c60db8b
Python: add pragma: no cover to structurally unreachable blocks
gusthoff Jun 19, 2026
1378160
Python: add pragma: no cover to extract_projects ConfigBlock guard
gusthoff Jun 19, 2026
5a774be
Python: add pragma: no branch to colors TTY check
gusthoff Jun 19, 2026
82d754d
Python: extend unit tests for blocks.py (gnatprove/gprbuild version s…
gusthoff Jun 19, 2026
027f314
Python: extend unit tests for extract_projects.py (Diag class, verbos…
gusthoff Jun 19, 2026
3427d4c
Python: extend unit tests for check_projects.py (verbose, inactive bl…
gusthoff Jun 19, 2026
702e1c4
Python: add pragma: no cover to __main__ blocks in three modules
gusthoff Jun 20, 2026
bdbd606
Python: extend unit tests for chop.py (real_gnatchop — valid Ada, com…
gusthoff Jun 19, 2026
e550f7f
Merge feat/toolchain-module-tests: unit tests for toolchain-dependent…
gusthoff Jun 19, 2026
463b6b3
Python: add pragma: no cover / no branch to remaining dead paths
gusthoff Jul 24, 2026
4dc6b7f
Python: extend integration tests for check_code_block.py
gusthoff Jun 20, 2026
bc7a84f
Python: extend unit tests for toolchain_setup.py (uninitialised TOOLC…
gusthoff Jun 19, 2026
85033df
Infra: ignore *.egg-info/ directories
gusthoff Jun 19, 2026
d1ede69
Python: extend unit tests for check_code_block.py
gusthoff Jul 24, 2026
b2a2af3
Python: extend integration tests for extract_projects.py
gusthoff Jun 20, 2026
dd483d4
Merge feat/coverage-improvements: pragmas and extended unit tests
gusthoff Jun 19, 2026
516d034
Python: extend unit tests for extract_projects.py
gusthoff Jul 24, 2026
d924fb9
Python: extend integration tests for check_projects.py
gusthoff Jun 20, 2026
60dd770
Python: remove references from test file headers
gusthoff Jun 20, 2026
4911750
Python: extend unit tests for blocks.py
gusthoff Jul 24, 2026
b31566e
Merge feat/integration-tests: integration tests for Ada compilation/r…
gusthoff Jun 20, 2026
2840374
Python: extend unit tests for chop.py
gusthoff Jul 24, 2026
b4b75b9
Python: raise coverage threshold to 90
gusthoff Jun 20, 2026
84d8268
Python: extend unit tests for check_code_block.py
gusthoff Jul 24, 2026
418dc0f
Merge feat/coverage-completion: pragmas and clean-path coverage tests
gusthoff Jul 24, 2026
8eae486
Python: extend unit tests for extract_projects.py
gusthoff Jul 24, 2026
6ec6507
Python: raise coverage threshold to 95
gusthoff Jul 24, 2026
f1b4d90
Python: extend unit tests for blocks.py
gusthoff Jul 24, 2026
2038dd4
Python: extend unit tests for check_code_block.py
gusthoff Jul 24, 2026
f8d0a4b
Merge feat/coverage-real-input-tests: real-input coverage for previou…
gusthoff Jul 24, 2026
64ae56d
Python: extend unit tests for check_code_block.py
gusthoff Jul 24, 2026
eda264f
Merge feat/coverage-missing-toolchain-test: environment-isolated miss…
gusthoff Jul 24, 2026
a4e2726
Merge feat/coverage-bonus-pickups: small coverage gaps found during t…
gusthoff Jul 24, 2026
e6af3ce
Python: remove dead has_error assignment in C cleanup handler
gusthoff Jul 24, 2026
c747da1
Python: extend unit tests for check_code_block.py
gusthoff Jul 25, 2026
6957f30
Python: extend unit tests for extract_projects.py
gusthoff Jul 25, 2026
9eb40e8
Merge feat/coverage-cleanup-failure-tests: cleanup-failure and gnatch…
gusthoff Jul 25, 2026
953c63d
Python: raise coverage threshold to 99
gusthoff Jul 25, 2026
37e7fe2
CI: install test extras before running pyright on code_projects
gusthoff Jul 25, 2026
a65da84
Python: narrow blocks to CodeBlock/ConfigBlock before accessing subcl…
gusthoff Jul 25, 2026
d4058e3
CI: rename workflow and add a job that runs the pytest suite
gusthoff Jul 25, 2026
88d50f4
Merge feat/ci-tests: pyright fixes and a CI job for the pytest suite
gusthoff Jul 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 0 additions & 34 deletions .github/workflows/code-projects-type-check.yml

This file was deleted.

62 changes: 62 additions & 0 deletions .github/workflows/rst-code-example-pipeline-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: rst_code_example_pipeline CI

on:
push:
paths:
- 'frontend/python/rst_code_example_pipeline/**'
pull_request:
branches:
- main
paths:
- 'frontend/python/rst_code_example_pipeline/**'

jobs:
pyright:

runs-on: ubuntu-24.04

strategy:
matrix:
python-version: ['3.12']

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install pyright
run: pip install pyright
- name: Install rst_code_example_pipeline
run: pip install -e 'frontend/python/rst_code_example_pipeline[test]'
- name: Run pyright on rst_code_example_pipeline
working-directory: frontend/python/rst_code_example_pipeline
run: pyright .

pytest:

runs-on: ubuntu-24.04

strategy:
matrix:
python-version: ['3.12']

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install OS deps
run: |
sudo apt-get update && \
sudo apt-get install -y \
crudini
- name: Install GNAT FSF
run: |
${GITHUB_WORKSPACE}/.github/workflows/install_toolchain.sh --gnat --gnatprove --gprbuild
- name: Install rst_code_example_pipeline
run: pip install -e 'frontend/python/rst_code_example_pipeline[test]'
- name: Run rst_code_example_pipeline test suite
working-directory: frontend
run: make test_rst_pipeline
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
*.pyc
*.egg-info/
env
.idea
.vagrant*
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,8 @@ check-code \

For more examples and alternative configurations, please refer to the
[README of the rst_code_example_pipeline package](frontend/python/rst_code_example_pipeline/README.md)

The package also has its own pytest-based unit test suite. On the epub VM,
run it with `make test_rst_pipeline` (from the `frontend/` directory). See
the "Development" section of the package README for installation and usage
details.
3 changes: 3 additions & 0 deletions frontend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ test_parser: #
@coverage run --source=widget,rst_code_example_pipeline.chop,rst_code_example_pipeline.resource -m unittest discover --start-directory sphinx
@coverage report --fail-under=90 -m

test_rst_pipeline: ## Test the rst_code_example_pipeline package (epub VM).
@cd python/rst_code_example_pipeline && pytest

##@ Build website
publish: ## [DEPRECATED] Publish contents to the learn website.
@echo "Publishing current branch to learn..."
Expand Down
32 changes: 32 additions & 0 deletions frontend/python/rst_code_example_pipeline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,35 @@ check-block \
--max-columns 80 \
test_output/projects/Courses/Intro_To_Ada/Imperative_Language/Greet/cba89a34b87c9dfa71533d982d05e6ab/block_info.json
```


## Development

### Installing with test dependencies

The package declares an optional `test` extras group that installs
[pytest](https://docs.pytest.org/) and
[pytest-cov](https://pytest-cov.readthedocs.io/).
Install the package in editable mode together with those extras:

```sh
pip install -e ".[test]"
```

### Running the unit tests

Coverage options and test paths are configured in `pyproject.toml`, so a plain
`pytest` invocation from the package root is enough:

```sh
pytest
```

Some modules require an Ada toolchain (GNAT) to be on `PATH`; run the full
suite in an environment where GNAT is available.

To pass coverage options explicitly:

```sh
pytest --cov=rst_code_example_pipeline --cov-report=term-missing tests/
```
21 changes: 21 additions & 0 deletions frontend/python/rst_code_example_pipeline/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,32 @@ extract-code = "rst_code_example_pipeline.cli.extract:main"
check-code = "rst_code_example_pipeline.cli.check:main"
check-block = "rst_code_example_pipeline.cli.check_block:main"

[project.optional-dependencies]
test = ["pytest", "pytest-cov"]

[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools.package-data]
rst_code_example_pipeline = ["data/*.ini"]

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=rst_code_example_pipeline --cov-report=term-missing"

[tool.coverage.run]
source = ["rst_code_example_pipeline"]
branch = true

[tool.coverage.report]
show_missing = true
fail_under = 99
exclude_lines = [
# Standard pragma for uncoverable lines
"pragma: no cover",
# CLI __main__ entry points are not exercised by unit tests
"if __name__ == .__main__.:",
]

[tool.pyright]
pythonVersion = "3.10"
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ def cleanup_project(language, project_filename, main_file):
except S.CalledProcessError as e:
print_error(loc, "Failed to clean-up example")
print(e.output)
has_error = True

toolchain_setup.set_toolchain(block)

Expand All @@ -152,7 +151,7 @@ def cleanup_project(language, project_filename, main_file):
print("Skipping code block {}".format(loc))
return has_error

if LOOK_FOR_PREVIOUS_CHECKS:
if LOOK_FOR_PREVIOUS_CHECKS: # pragma: no branch
ref_block_check = None

try:
Expand All @@ -164,7 +163,7 @@ def cleanup_project(language, project_filename, main_file):
has_error = not ref_block_check.status_ok
if verbose:
print("Code block {} already checked. Skipping...".format(loc))
if __name__ == '__main__':
if __name__ == '__main__': # pragma: no cover
print("WARNING: Code block {} already checked: use '--force' to re-run the check. Skipping...".format(loc))
if has_error:
print_error(
Expand Down Expand Up @@ -372,7 +371,7 @@ def cleanup_project(language, project_filename, main_file):
if check_error:
has_error = True

if False:
if False: # pragma: no cover
check_error = False

for source_file in block.source_files:
Expand Down Expand Up @@ -473,7 +472,7 @@ def cleanup_project(language, project_filename, main_file):
has_error = True


if True:
if True: # pragma: no cover
check_error = False

if len(block.buttons) == 0:
Expand Down Expand Up @@ -556,7 +555,7 @@ def check_code_block_json(json_file: str) -> bool:
return has_error


if __name__ == "__main__":
if __name__ == "__main__": # pragma: no cover
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('json_files', type=str, nargs="+",
help="The JSON file for each code block")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def check_projects(build_dir: str, projects_list_file: str | None = None) -> boo
return check_error


if __name__ == "__main__":
if __name__ == "__main__": # pragma: no cover
import argparse

parser = argparse.ArgumentParser(description=__doc__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def disable_colors(cls) -> None:

# Keep colors when we are running under GDB. Otherwise, disable colors as soon
# as one of stdout or stderr is not a TTY.
if not sys.stdout.isatty() or not sys.stderr.isatty():
if not sys.stdout.isatty() or not sys.stderr.isatty(): # pragma: no branch
Colors.disable_colors()


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def analyze_file(rst_file: str, extracted_projects_list_file: str | None = None)
if block.line_start < code_block_at < block.line_end:
block.active = True

def remove_string(some_text, rem):
def remove_string(some_text, rem): # pragma: no cover
return re.sub(".*" + rem + ".*\n?","", some_text)

projects = dict()
Expand Down Expand Up @@ -248,7 +248,7 @@ def init_project_dir(project):
print("Number of code blocks: {}".format(len(projects[project])))

for i, block in projects[project]:
if isinstance(block, blocks.ConfigBlock):
if isinstance(block, blocks.ConfigBlock): # pragma: no cover
current_config.update(block)
toolchain_setup.reset_toolchain()
continue
Expand Down Expand Up @@ -397,7 +397,7 @@ def get_main_filename(block):

return analysis_error

if __name__ == "__main__":
if __name__ == "__main__": # pragma: no cover
import argparse

parser = argparse.ArgumentParser(description=__doc__)
Expand Down
Loading
Loading