Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, multi-stitch, pull compensation, machine constraints) #41

Closed
opened 2026-06-22 16:23:20 +00:00 by Mark · 1 comment
Owner

Tests for the actual EmbroideryPipeline.process() path

Context

The pytest suite (tests/test_main.py) has 3 import-time smoke tests.
None exercise EmbroideryPipeline.process() end-to-end. This means
the 5-stage pipeline, the new PES/EXP/JEF generators, the underlay
generator, the pull compensation, the path optimizer, and the thread
manager are all untested at the integration level.

Goal

Add tests/test_pipeline_e2e.py with a focused set of end-to-end tests
that lock the pipeline's externally-observable behavior. Each test is
a single, shippable unit of work that catches a real regression.

Decomposition

Six test scenarios, each a distinct phase. They can be developed and
shipped in any order, but the order below is the natural dependency
order (simpler tests first, machine constraints last).

P1: SVG → DST round trip

The core happy path. The original MVP that issue #2 (DST fallback
produces corrupt files) regressed. This test would have caught it.

Files:

  • New: tests/test_pipeline_e2e.py (test file)
  • New: data/test_fixtures/simple_square.svg (a known SVG)

Acceptance:

  • process(simple_square.svg, output_format="dst") produces a valid
    DST file (header check: starts with the correct DST magic; stitch
    count in the expected range; no truncated bytes).
  • The test runs in CI on every PR.

Why first: if this fails, the basic pipeline is broken and all
other tests are noise. Land this first to establish the test infra
works.


P2: SVG → PES round trip

Issue #11 ("PES/EXP/JEF advertised but not implemented") was closed
as fixed. This test locks the fix.

Files:

  • Modify: tests/test_pipeline_e2e.py
  • New: data/test_fixtures/pes_header_check.py (helper for PES magic
    byte validation)

Acceptance:

  • process(simple_square.svg, output_format="pes") produces a valid
    PES file.
  • The PES header contains the correct version (PES0001) and the
    expected number of color changes.
  • The test runs in CI.

Depends on: P1 (test infra).


P3: Raster → DST round trip

Tests the raster converter path (not the SVG path). The HTTP service
ingests rasters (PNG/JPG), so this is the path ThreadCraft exercises
most often.

Files:

  • Modify: tests/test_pipeline_e2e.py
  • New: data/test_fixtures/simple_square.png (a known raster)

Acceptance:

  • process(simple_square.png, output_format="dst") produces a valid
    DST.
  • The raster-to-SVG conversion happened (verified by checking that
    the pipeline stages were exercised, per issue #35).

Depends on: P1, P2.


P4: Multi-stitch-type classification

A more complex SVG with multiple shape types should produce a stitch
run with the expected mix of satin, fill, and running stitches.

Files:

  • Modify: tests/test_pipeline_e2e.py
  • New: data/test_fixtures/mixed_stitches.svg (an SVG with at least
    one satin shape, one fill region, and one running outline)

Acceptance:

  • The output contains stitch objects tagged as satin, fill, and
    running (in any order, but each must be present).
  • The classification matches the SVG shape characteristics (a narrow
    rectangle → satin, a large filled circle → fill, a thin line →
    running).

Depends on: P1, P2, P3 (full pipeline exercise).


P5: Pull compensation toggle

Pull compensation (src/post_processing/pull_compensation.py) is a
2.1 KB module that adjusts stitch positions to account for fabric
pull. It's on by default and should produce different output when
toggled.

Files:

  • Modify: tests/test_pipeline_e2e.py

Acceptance:

  • The same SVG processed with pull compensation on vs off produces
    two DST files that differ in at least one stitch position
    (asserted by byte-comparing the stitch sections, not the headers).

Depends on: P1 (test infra).


P6: Machine profile constraint (PR-10)

End-to-end test that machine constraints are actually enforced. Uses
the PR-10 profile from issue #36.

Files:

  • Modify: tests/test_pipeline_e2e.py
  • New: data/test_fixtures/oversized.svg (a design that exceeds the
    PR-10 hoop)

Acceptance:

  • process(oversized.svg, machine_profile="brother_pr10") either:
    (a) rejects with a clear error, or (b) scales to fit, depending on
    the pipeline's policy. The test asserts on whichever behavior the
    pipeline implements; whichever it is, the test exists and pins the
    behavior so it doesn't silently change.
  • A design within the hoop passes through unchanged.
  • Max thread count constraint: a design with 50 colors, with the
    PR-10 profile (10 threads), produces output with ≤ 10 distinct
    colors.

Depends on: P1, issue #36 (PR-10 profile exists).

Cross-cutting

  • All tests use snapshot + tolerance, not byte-exact matches
    (raster output is sensitive to numpy/scipy version pins; the
    pipeline is deterministic in shape but the bytes can shift).
  • Tests are run by CI on every PR. Local dev can skip them with
    pytest -m "not e2e" for fast iteration.
  • Total runtime target: < 60 seconds for the full e2e suite. If it
    exceeds that, the slowest test gets a pytest.mark.slow and CI
    runs it in a separate job.
# Tests for the actual EmbroideryPipeline.process() path ## Context The pytest suite (`tests/test_main.py`) has 3 import-time smoke tests. **None exercise `EmbroideryPipeline.process()` end-to-end.** This means the 5-stage pipeline, the new PES/EXP/JEF generators, the underlay generator, the pull compensation, the path optimizer, and the thread manager are all untested at the integration level. ## Goal Add `tests/test_pipeline_e2e.py` with a focused set of end-to-end tests that lock the pipeline's externally-observable behavior. Each test is a single, shippable unit of work that catches a real regression. ## Decomposition Six test scenarios, each a distinct phase. They can be developed and shipped in any order, but the order below is the natural dependency order (simpler tests first, machine constraints last). ### P1: SVG → DST round trip The core happy path. The original MVP that issue #2 (DST fallback produces corrupt files) regressed. This test would have caught it. **Files:** - New: `tests/test_pipeline_e2e.py` (test file) - New: `data/test_fixtures/simple_square.svg` (a known SVG) **Acceptance:** - `process(simple_square.svg, output_format="dst")` produces a valid DST file (header check: starts with the correct DST magic; stitch count in the expected range; no truncated bytes). - The test runs in CI on every PR. **Why first:** if this fails, the basic pipeline is broken and all other tests are noise. Land this first to establish the test infra works. --- ### P2: SVG → PES round trip Issue #11 ("PES/EXP/JEF advertised but not implemented") was closed as fixed. This test locks the fix. **Files:** - Modify: `tests/test_pipeline_e2e.py` - New: `data/test_fixtures/pes_header_check.py` (helper for PES magic byte validation) **Acceptance:** - `process(simple_square.svg, output_format="pes")` produces a valid PES file. - The PES header contains the correct version (PES0001) and the expected number of color changes. - The test runs in CI. **Depends on:** P1 (test infra). --- ### P3: Raster → DST round trip Tests the raster converter path (not the SVG path). The HTTP service ingests rasters (PNG/JPG), so this is the path ThreadCraft exercises most often. **Files:** - Modify: `tests/test_pipeline_e2e.py` - New: `data/test_fixtures/simple_square.png` (a known raster) **Acceptance:** - `process(simple_square.png, output_format="dst")` produces a valid DST. - The raster-to-SVG conversion happened (verified by checking that the pipeline stages were exercised, per issue #35). **Depends on:** P1, P2. --- ### P4: Multi-stitch-type classification A more complex SVG with multiple shape types should produce a stitch run with the expected mix of satin, fill, and running stitches. **Files:** - Modify: `tests/test_pipeline_e2e.py` - New: `data/test_fixtures/mixed_stitches.svg` (an SVG with at least one satin shape, one fill region, and one running outline) **Acceptance:** - The output contains stitch objects tagged as `satin`, `fill`, and `running` (in any order, but each must be present). - The classification matches the SVG shape characteristics (a narrow rectangle → satin, a large filled circle → fill, a thin line → running). **Depends on:** P1, P2, P3 (full pipeline exercise). --- ### P5: Pull compensation toggle Pull compensation (`src/post_processing/pull_compensation.py`) is a 2.1 KB module that adjusts stitch positions to account for fabric pull. It's on by default and should produce different output when toggled. **Files:** - Modify: `tests/test_pipeline_e2e.py` **Acceptance:** - The same SVG processed with pull compensation on vs off produces two DST files that differ in at least one stitch position (asserted by byte-comparing the stitch sections, not the headers). **Depends on:** P1 (test infra). --- ### P6: Machine profile constraint (PR-10) End-to-end test that machine constraints are actually enforced. Uses the PR-10 profile from issue #36. **Files:** - Modify: `tests/test_pipeline_e2e.py` - New: `data/test_fixtures/oversized.svg` (a design that exceeds the PR-10 hoop) **Acceptance:** - `process(oversized.svg, machine_profile="brother_pr10")` either: (a) rejects with a clear error, or (b) scales to fit, depending on the pipeline's policy. The test asserts on whichever behavior the pipeline implements; whichever it is, the test exists and pins the behavior so it doesn't silently change. - A design within the hoop passes through unchanged. - Max thread count constraint: a design with 50 colors, with the PR-10 profile (10 threads), produces output with ≤ 10 distinct colors. **Depends on:** P1, issue #36 (PR-10 profile exists). ## Cross-cutting - All tests use **snapshot + tolerance**, not byte-exact matches (raster output is sensitive to numpy/scipy version pins; the pipeline is deterministic in shape but the bytes can shift). - Tests are run by CI on every PR. Local dev can skip them with `pytest -m "not e2e"` for fast iteration. - Total runtime target: < 60 seconds for the full e2e suite. If it exceeds that, the slowest test gets a `pytest.mark.slow` and CI runs it in a separate job.
Mark changed title from Tests don't exercise the actual EmbroideryPipeline.process() path to Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, multi-stitch, pull compensation, machine constraints) 2026-06-22 16:30:53 +00:00
Author
Owner

This issue has been decomposed into the following sub-issues:

# Title Phase Scope
#63 Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, The core happy path. The original MVP that issue #2 (DST fallback produces corru
#64 Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, Issue #11 ("PES/EXP/JEF advertised but not implemented") was closed as fixed. Th
#65 Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, Tests the raster converter path (not the SVG path). The HTTP service ingests ras
#66 Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, A more complex SVG with multiple shape types should produce a stitch run with th
#67 Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, Pull compensation (src/post_processing/pull_compensation.py) is a 2.1 KB modul
#68 Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, End-to-end test that machine constraints are actually enforced. Uses the PR-10 p

Each sub-issue has been labeled with triage-approved and is ready for queue routing.

This issue has been decomposed into the following sub-issues: | # | Title | Phase Scope | |---|-------|-------------| | #63 | Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, | The core happy path. The original MVP that issue #2 (DST fallback produces corru | | #64 | Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, | Issue #11 ("PES/EXP/JEF advertised but not implemented") was closed as fixed. Th | | #65 | Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, | Tests the raster converter path (not the SVG path). The HTTP service ingests ras | | #66 | Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, | A more complex SVG with multiple shape types should produce a stitch run with th | | #67 | Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, | Pull compensation (`src/post_processing/pull_compensation.py`) is a 2.1 KB modul | | #68 | Decompose: End-to-end pipeline tests (SVG/DST, PES, raster, | End-to-end test that machine constraints are actually enforced. Uses the PR-10 p | Each sub-issue has been labeled with `triage-approved` and is ready for queue routing.
Mark closed this issue 2026-06-22 16:31:47 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/easystitch#41
No description provided.