Skip to content

test: add unit test suite for syncAddonWithTemplate.py#43

Open
abdel792 wants to merge 47 commits into
nvaccess:masterfrom
abdel792:unitTests-syncAddon
Open

test: add unit test suite for syncAddonWithTemplate.py#43
abdel792 wants to merge 47 commits into
nvaccess:masterfrom
abdel792:unitTests-syncAddon

Conversation

@abdel792

@abdel792 abdel792 commented Jul 23, 2026

Copy link
Copy Markdown

Note

This PR is a follow-up to and depends on #41.

Link to issue number:

Not applicable. Follow-up to #41.

Summary of the issue:

While syncAddonWithTemplate.py manages the automated migration and merging of add-on metadata, there was no automated test suite to ensure its internal transformations, TOML formatting rules, and AST-aware merges remain reliable over time and across future template updates.

Additionally, test files required proper linter exclusions and build protections to avoid cluttering static analysis reports and the final add-on package.

Description of developer facing changes:

  • Introduces a comprehensive unit test suite in tests/test_syncAddonWithTemplate.py validating core transformation, parsing, and merging functions in syncAddonWithTemplate.py.
  • Excludes the tests/ directory from ruff and pyright checks in pyproject.toml.
  • Updates technical documentation to guide developers on running the test suite locally.

Description of development approach

  • Unit Test Suite Creation: Created tests/test_syncAddonWithTemplate.py using Python's standard unittest framework and tempfile module to safely perform file-system merges in isolated temporary workspaces.
  • TOML Formatting Validation: Implemented testFixTomlIndentation to ensure 4-space indentations within array blocks (authors/maintainers) are strictly converted to tabs while preserving formatting elsewhere.
  • Author Parsing Validation: Implemented testFormatAuthorList to ensure raw author strings with name and email format parse cleanly into structured tomlkit arrays.
  • AST-Aware Merge Verification:
    • Added testMergeLegacyBuildvarsWithOfficialTemplate to verify legacy dictionary-based buildVars.py files migrate correctly into modern AddonInfo AST call structures.
    • Added testMergeModernBuildvarsMissingSpeechDictionaries to verify automatic injection of missing global variables (such as speechDictionaries) when merging configurations.
  • Linter & Scope Protection:
    • Added tests to the exclude arrays in [tool.ruff] and [tool.pyright] within pyproject.toml so test files do not trigger strict static analysis alerts during validation.
    • Verified that tests/ remains outside the addon/ runtime directory so it is never packaged into final .nvda-addon distribution files.
  • Documentation Updates: Updated developer documentation with clear guidelines for running the full test suite (uv run python -m unittest -v) or individual test files.

Testing strategy:

The test suite and workspace configuration were validated locally using uv:

  1. Ran targeted execution of the test suite via terminal:
uv run python -m unittest -v tests/test_syncAddonWithTemplate.py
  1. Confirmed that all 4 unit tests executed successfully in verbose mode:
    • testFixTomlIndentation -> ok
    • testFormatAuthorList -> ok
    • testMergeLegacyBuildvarsWithOfficialTemplate -> ok
    • testMergeModernBuildvarsMissingSpeechDictionaries -> ok
  2. Ran test discovery from the repository root to ensure seamless integration with standard CI workflows:
uv run python -m unittest -v
  1. Verified that ruff and pyright successfully ignore the tests/ folder according to pyproject.toml configuration.

Known issues with pull request:

None.


Code Review Checklist

  • Testing: Automated unit test suite implemented and verified locally. Steps to reproduce are detailed in the testing strategy.
  • API is compatible with existing add-ons: This is a developer-facing test suite; it introduces no breaking API changes or modifications to add-on runtime behavior.
  • Documentation: Technical developer documentation has been updated with unit testing execution guidelines.
  • UX of all users considered: Not applicable (Developer-facing testing infrastructure).
  • Security precautions taken: Not applicable (Tests run locally in isolated temporary directories during development).

abdel792 and others added 30 commits July 9, 2026 16:41
…ration merges for legacy add-ons.

- Add tomlkit to project dependencies in pyproject.toml to support robust AST-aware TOML parsing.
- Update updatingExistingAddons.md to provide clear instructions and prerequisites for the new automated tool.
- Exclude the update script from ruff and pyright configurations to prevent strict environment linting conflicts.
- Remove trailing "Press Enter to exit..." prompt at successful script completion to allow seamless execution in automated environments.
- Implement specific file/folder exclusion handling during synchronization, with full architecture setup requested by @CyrilleB79.
- Completely restructure the guide to separate the recommended automated tool method from the manual Git merge workflow.
- Integrate detailed instructions for the automated companion script (`updateAddon.py`).
- Document the new template synchronization exclusions feature (`IGNORED_FILES`).
- Improve overall clarity, formatting, and prerequisites for initial repository setup.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Rename `updateAddon.py` to `updateAddonFromTemplate.py` for clarity.
- Update `pyproject.toml` to exclude the renamed script from ruff and pyright.
- Overhaul `updatingExistingAddons.md` documentation to match the new script name and integrate Copilot's review recommendations regarding prerequisites, correct paths, and accurate backup details.
- Fix initial repository cloning paths by adding missing folder transition.
- Document both standard and target directory execution modes (`addonDir`).
- Align minimum Python requirements to 3.13 to match upstream template.
- Clarify dynamic full-copy backup directory naming schema (`<addon>_bak_<timestamp>`).
- Add comprehensive structural explanations for both legacy dictionary-based and modern AddonInfo-based add-on updates.
- Note that `IGNORED_FILES` configuration supports excluding whole directories.
…ExistingAddons.md

- Fix broken Markdown syntax for the backup directory naming template.
- Remove redundant folder transition step from the initial setup guide.
- Refine typography and adopt a neutral technical tone by removing promotional phrasing.
- Apply overall documentation adjustments to improve layout and workflow clarity.
…ted pyproject.toml

Updated `mergePyprojectToml` to configure `tomlkit` with `.multiline(True)` when programmatically migrating legacy `addon_author` metadata. This ensures that authors/maintainers are generated in a clean, vertically indented structure during initial add-on template migrations, matching official repository design guidelines.
Update the prerequisites section in updatingExistingAddons.md to document that `tomlkit` must be installed globally before running `updateAddonFromTemplate.py`. This ensures users don't encounter missing module errors when executing the script on legacy repositories or before the upstream template merges the new dependency.
Commented out the default `build_addon.yml` path entry within the `IGNORED_FILES` set in `updateAddonFromTemplate.py`. This ensures all infrastructure components are synchronized out of the box while providing developers with a clear syntax example for excluding custom files or directories.
Updated the `mergePyprojectToml` function in `updateAddonFromTemplate.py` to ensure that when a new `pyproject.toml` is created from the template for legacy add-ons, any generated multiline arrays (such as `maintainers`) strictly use tab indentation instead of four spaces.
Restores the comprehensive function docstrings and parameter descriptions
originally written by @nvdaes, which were accidentally removed during
the recent module refactoring. All documentation is aligned with the
current module structure.
- Extract core update logic from main() into a standalone runSynchronization() function.
- Convert the positional add-on directory argument into a standard named option with short (-ad) and long (--addon-dir) flags.
- Add -td and --template-dir short/long flags to support using a local NVDA AddonTemplate folder.
- Streamline Phase 3 logic to cleanly bypass remote Git cloning when a local template directory is supplied.
- Fix a duplicate parser declaration line for the --dry-run option.
… camelCase

- Add support for custom exclusion patterns via a local `.addonmergeignore` file in the target add-on root.
- Refactor all functions, variables, and CLI arguments to strictly adhere to camelCase naming conventions.
- Standardise all docstrings to use the Sphinx documentation format (including detailed `:param:` and `:return:` fields).
- Modernise and tighten type hinting across the entire module (using Python 3.10+ native unions `|` and explicit annotations).
Create an empty `.addonmergeignore` file at the root of the repository. This template file allows developers to easily specify local file and directory exclusion patterns to prevent them from being overwritten during subsequent synchronization phases.
- Move all import statements to the module header for better code structure.
- Update the documentation to explain the .addonmergeignore procedure instead of the manual IGNORED_FILES code modification.
- Document the automated update tool CLI flags and options.
abdel792 and others added 11 commits July 14, 2026 14:20
- Integrate upstream changes from Leonard de Ruijter.
- Resolve merge conflict in pyproject.toml by merging build groups and retaining tomlkit.
- Merge structural improvements from @nvdaes and the latest PR.
- Restore critical details about the cleanup of placeholder metadata (such as conditional nvaccess author removal).
- Clarify Git and companion tool prerequisites, aligning Python versions.
- Format all paragraphs using @nvdaes' structural guidelines (frequent line breaks after periods) for optimal readability.
- Extract the "addon_url" metadata from buildVars.py when generating a new pyproject.toml.
- Write the "Repository" key to [project.urls], preserving empty values ("") if the URL is not set in the add-on.
- Rename the script from `updateAddonFromTemplate.py` to `syncAddonWithTemplate.py` to better reflect its synchronization purpose.
- Update ruff and pyright exclusions and tool settings in `pyproject.toml` to reference the new file name.
- Update the documentation (`updatingExistingAddons.md`) to align all text, examples, and `.addonmergeignore` instructions with the new module name.
- Standardize all documentation commands to use the safer `uv run python` syntax.
- Change `addonDir` from an optional flagged argument (`-ad`/`--addon-dir`) to a positional optional argument using `nargs="?"`.
- Allow running the script with a target directory directly (e.g., `syncAddonWithTemplate.py myAddon`) without needing the `-ad` flag.
- Preserve the default behavior (`None`/current directory) when no path argument is provided.
- Add instructions for running unit tests via pytest and uv.
- Update syncAddonWithTemplate.py usage guides to enforce the mandatory -ad option.
- Include guidelines for using uv run with the --with tomlkit flag to execute the companion tool without prior installation.
- Align script usage and testing recommendations with guidelines from @seanbudd.
…view

* Script (`syncAddonWithTemplate.py`):
  * Replace stdout prints with structured logging for file output support
  * Refactor CLI argument parsing into a dedicated helper function
  * Generate sync report in Markdown format for better readability
  * Support tomlkit mutable sequences for author/maintainer checks
  * Remove global whitespace replacements on TOML output to avoid string corruption
  * Restore strictly tab-indented author/maintainer arrays via scoped block formatting
  * Replace naive text search with ast.Name verification to detect actual `os` module usage
  * Clean up trailing EOF whitespace

* Configuration (`buildVars.py`):
  * Ensure single top-level import os insertion during AST-based merging when `os` is used

* Documentation (`updatingExistingAddons.md`):
  * Remove duplicated instruction sections and fix broken Markdown code blocks
  * Defer unit testing documentation section to PR nvaccess#42
@abdel792
abdel792 force-pushed the unitTests-syncAddon branch from ceaceeb to cd2de3e Compare July 23, 2026 17:10
@abdel792
abdel792 force-pushed the unitTests-syncAddon branch 3 times, most recently from dae8afa to c290042 Compare July 23, 2026 23:47
abdel792 added 4 commits July 25, 2026 00:46
…roups

Prevent duplicate declarations and version conflicts during uv sync by filtering
out legacy developer dependencies from project.dependencies if they are already
managed by PEP 735 dependency groups.
…ump tomlkit

- Ensure `project.dependencies` type safety during pyproject TOML merging.
- Skip `addonTemplate.egg-info` when synchronizing from a local template directory.
- Update `tomlkit` pinned version in `pyproject.toml`.
- Implement unit tests in tests/test_syncAddonWithTemplate.py covering:
  * TOML indentation fixing (4-space to tab inside array blocks)
  * Raw author string parsing into structured tomlkit arrays
  * Merging legacy dictionary-based buildVars.py into modern AST structure
  * Injecting missing global variables (speechDictionaries) into modern buildVars.py
- Exclude `tests/` directory from `ruff` and `pyright` in pyproject.toml to prevent static analysis noise.
- Ensure test files run in isolated temporary environments using `tempfile`.
- Update technical documentation with instructions for running test discovery (`uv run python -m unittest -v`).
Remove redundant module copy from tests directory as unit tests already use the root module.
@abdel792
abdel792 force-pushed the unitTests-syncAddon branch from c290042 to c523648 Compare July 24, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants