Development & Contribution Guide

This document outlines the internal development workflow, test commands, and E2E testing policies for contributors working on xlsxrb.

Test Commands

To run the different tiers of our testing strategy:

  1. Unit Tests: bash bundle exec rake test:unit

  2. Contract Tests: bash bundle exec rake test:contract

  3. Property-Based Tests (PBT): bash bundle exec rake test:pbt

  4. Memory & Performance Tests: bash bundle exec rake test:perf

  5. Interoperability (E2E) Tests: Requires .NET SDK to be installed (pre-configured in Dev Container). bash bundle exec rake test:e2e

  6. Visual Regression Tests (VRT): Requires LibreOffice, ImageMagick, and poppler-utils. bash bundle exec rake test:visual

  7. Run All Tests: bash bundle exec rake test


Development Workflow

High-level API expansion follows the Facade rules documented in ARCHITECTURE.md. In short: if a low-level writer feature is stable, the default expectation is that it should eventually be exposed through the high-level DSL as well, with consistent naming, both streaming and in-memory coverage, backward-compatible options/block forms where practical, and matching Facade-level tests.

To ensure systematic progress, reliable round-trip compatibility, and strict adherence to the ECMA-376 specification, we follow this iterative development cycle for each new feature:

  1. Select a Feature: Choose a specific element or behavior from the specification to implement.

  2. Writer Unit Tests: Write unit tests for the Writer component targeting this feature.

  3. Writer Implementation: Implement the Writer functionality.

  4. Run Writer Tests: Execute the Writer unit tests. If they fail, return to step 3.

  5. Writer E2E & Validation: Test the Writer’s generated XLSX file using the Open XML SDK. This includes structural validation using OpenXmlValidator. If the test or validation fails, return to step 2.

  6. Reader Unit Tests: Write unit tests for the Reader component. Crucially, include round-trip tests to ensure the Reader can accurately parse the output of your Writer.

  7. Reader Implementation: Implement the Reader functionality.

  8. Run Reader Tests: Execute the Reader unit tests. If they fail, return to step 6 or 7. If the round-trip test reveals a structural flaw in the Writer’s output, return all the way back to step 2.

  9. Reader E2E: Verify that the Reader can successfully parse a valid XLSX file generated by the Open XML SDK that includes the new feature. If it fails, return to step 6 or 7.

  10. Full Test Suite: Run the entire test suite (rake test). If any tests fail, trace back to the appropriate step.

  11. Commit: Commit the changes. The commit message must clearly describe the specific feature implemented in this cycle.

  12. Next Feature: Proceed to the next feature and return to step 1.


E2E Policy

E2E tests are required for every new feature. Omitting them is the exception, not the rule, and requires explicit justification.

A strong signal that E2E should not be omitted: if you are adding a new XML element, a new attribute on a top-level structure, or a new public API parameter, E2E is expected.

Omission is only acceptable when all of the following hold:

  1. The change adds a minor attribute to an XML structure that is already exercised end-to-end by an existing E2E scenario for the same element.

  2. No new XML element or branch is introduced.

  3. Unit tests and round-trip tests fully cover the new behaviour.

  4. rake test passes with Open XML SDK validation included.

  5. The commit message explicitly names the existing E2E scenario that provides coverage and states why a new scenario adds no value.


Development via Dev Container

The project is pre-configured with a Dev Container to simplify local environment setup (installing .NET, LibreOffice, ImageMagick, and Noto fonts).

VS Code (GUI)

You can open this repository in VS Code and select “Dev Containers: Reopen in Container” from the Command Palette.

Terminal (Devcontainer CLI)

If you prefer to use the terminal instead of VS Code, you can run the devcontainer using the official @devcontainers/cli:

  1. Install the CLI on your host machine (if not already installed): bash npm install -g @devcontainers/cli

  2. Use the helper script bin/devcontainer to start and interact with the container:

  3. Interactive shell (Automatically shares your host’s Git/AI tool configs as read-only): bash bin/devcontainer

  4. Run commands directly: bash bin/devcontainer rake test

Customizing with Personal Overrides (e.g., Dotfiles, API Keys, Shell History)

The bin/devcontainer script dynamically parses a personal configuration patch and maps it to devcontainer CLI flags on startup. This is a workaround for a specification limit of devcontainer CLI’s --override-config flag, which acts as a complete replacement of the configuration rather than a partial merge, wiping out base configurations like build settings.

To configure this, create a JSON (or JSONC) file at ${XDG_CONFIG_HOME:-~/.config}/devcontainer/override.jsonc (or override.json) on your host machine.

Example: Persisting histories, forwarding API keys, and Auto-installing Dotfiles

{
  "mounts": [
    // Volume for general persistent directories (e.g., Claude Code history in ~/.local/share/claude)
    "type=volume,source=xlsxrb-local-share,target=/home/vscode/.local/share"
  ],
  "containerEnv": {
    // Explicitly forward API keys from your host shell to the container environment
    "OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}",
    "ANTHROPIC_API_KEY": "${localEnv:ANTHROPIC_API_KEY}",
    "GEMINI_API_KEY": "${localEnv:GEMINI_API_KEY}"
  },
  "dotfiles": {
    "repository": "https://github.com/<your-github-username>/dotfiles.git",
    "targetPath": "~/dotfiles",
    "installCommand": "install.sh"
  }
}

You can also use a custom file path by exporting the DEVCONTAINER_OVERRIDE_CONFIG environment variable in your host shell:

export DEVCONTAINER_OVERRIDE_CONFIG="/path/to/your/custom-override.json"