Tests and Golden Paths
Goal: read tests as documentation. Use them to learn the API contracts, the expected outputs, and the ways the team has frozen behavior. Reading time: 45 minutes. You don’t write tests in this chapter. You learn to consume them.
1. The test framework — Flit
Flux uses a custom test framework called Flit, not NUnit or xUnit. The project is Test\Flux.Test.csproj (169 .cs files). Conventions:
-
Namespace:
namespace Flit;(file-scoped). -
Attributes:
-
[TestFixture (id, description, Module = "...", Subsystem = "...")]on classes. -
[Test (id, description)]on methods.
-
-
Assertions:
Assert.AreTextFilesEqual,Assert.True,Assert.False, plus extension methods like.Is (EResult.OK). -
Fixtures: standard
BendMachine.Get (13)style — fixtures are real domain objects loaded fromX:\TDataandX:\Data.
A canonical fixture (from Test\Bend\BasicBendAuto.cs):
namespace Flit;
#nullable enable
[TestFixture (4, "Basic bend auto-tooler tests", Module = "Bend", Subsystem = "AutoTool")]
class BasicBendAuto {
[Test (82, "Tooling basic part: Bend_04.geo")]
void Test1 () => Test ("Bend/Auto/Bend_04.geo");
public static Part Test (string file, int idMachine = 13, /* ... */) {
Part part = FX.LoadTestPart (file);
if (part.Model == null) part.DoFoldTo3D ().Is (EResult.OK);
BendTech.Make (part, BendMachine.Get (idMachine)).Is (EResult.OK);
var tech = part.BendTech;
// ...
BendTooler.Process (part.BendTech, flags);
CheckDump (tech, outfile);
return part;
}
public static void CheckDump (BendTech tech, string refFile) {
string file = FX.TmpTestFile;
using (StreamWriter sw = new (file)) tech.Dump (sw);
Assert.AreTextFilesEqual (refFile, file);
}
}
Test IDs
Test IDs (82, 84, 85, …) are globally unique and stable across the entire test suite. An ID conflict during merge is a real conflict. A test that disappears keeps its ID retired.
2. Test categories
Flux has roughly four categories of tests, all in the same project:
| Category | What they assert | Example file |
|---|---|---|
Pure unit |
A small algorithm, often in |
|
Integration |
A whole subsystem flow with real fixtures |
|
Golden-file |
A |
most of |
Regression bundles |
Year-grouped fixes (one file per year) |
|
The line between integration and golden-file is often thin — most integration tests in Bend / Fold are golden-file tests because the easiest assertion is "the auto-tooler still produces the same setup as last week".
3. The golden-file pattern (most common)
How it works
-
A test loads a
.geo(or.dxf,.fx) input fromX:\TData\<domain>\<area>\…. -
The subsystem’s
Make+ auto-router runs to completion. -
The resulting tech is asked to
Dump (TextWriter). -
The output is compared to a
.txtfile next to the input.
The .txt file is the golden. It is checked in. When the auto-tooler legitimately produces different output, the golden is regenerated and the diff is reviewed.
Why this pattern works
-
The dump format is hand-readable, so a diff in a PR is reviewable.
-
It captures dozens of decisions per file (sequence, tools, BG positions, BA placement, Z transitions) in a compact form.
-
A regression in any of those decisions changes the golden — which makes accidental drift impossible to ship.
Why this pattern hurts
-
Brittle. A cosmetic change to
Dumpcascades to dozens of.txtfiles. -
Coupling. The dump format is the test contract — change it, change everything.
-
Hidden semantics. The
.txtis a record, not an explanation. Some tests are reverse-engineered from "this is what the engine used to do".
How to read a golden file
Open X:\TData\Bend\Auto\Bend_04.txt. You’ll see machine setup info, a list of tool mounts with X positions, and bend-specific lines per op. Match each line back to the Dump method in the relevant tech (BendSetup.Dump, BendTech.Dump).
4. The yearly regression bundles
In Test\Bend\ you’ll see Bend2017.cs … Bend2025.cs. Each file is a layer of fixes from that year, captured as named regression cases. New cases land in the current year file.
[Test (1128, "P10976: Part requires 2 setups, with punches mounted in opposite flips")]
void Test13 () { ... }
[Test (1129, "Case 10939: One bend not possible (23.16)")]
void Test14 () => BasicBendAuto3D.Test ("Fold/Accept5/23.16.fx", 13, "Bend/Auto3/23.16.txt");
Patterns to notice:
-
Cases reference internal issue numbers (
P10976,Case 10939). Useful for cross-referencing. -
A regression test typically just runs the standard helper with a specific input and a specific golden — no re-implementation of logic.
5. Test data layout
X:\TData\ ├── 2D\ inputs for 2D drawing tests ├── 3D\ inputs for 3D model tests ├── Base\ Flux.Base level (Geometry / Math / Sys / IO) ├── Bend\ press-brake inputs (.geo, .dxf, .fx) + golden .txt │ ├── Auto\ auto-tooling fixtures │ ├── Auto3\ extended fixtures (often 3D-input) │ ├── ... ├── Cell\ BCell fixtures ├── Cell7K\ 7000-series cell variants ├── Cut\ flat-cut fixtures ├── Dwg\ drawing fixtures ├── Fanuc\ Fanuc-related (BCell controller) ├── Fold\ panel-bender fixtures ├── IO\ IO format fixtures ├── Laser\ laser fixtures ├── Lib\ tool-library fixtures ├── Nest\ nesting fixtures ├── OEM\ OEM-specific fixtures ├── Punch\ punch fixtures ├── Sys\ system-level ├── System\ (separate from Sys — historical split) └── Tmp\ scratch (test outputs go here transiently)
X:\TDATA is a separate clone of test data; the env var FLUXTESTDATA should point to it.
6. Reading a test in five steps
For any test you want to understand, do this:
-
Read the
[TestFixture]line — Module + Subsystem tell you the area. -
Read the
[Test]description — usually a one-line summary of the scenario. -
Find the helper — the test body is usually a one-liner calling a static helper.
-
Read the helper’s
Testmethod — that’s where the actual workflow runs (Make,Process,CheckDump). -
Open the input + golden — match dump-line to a model property by reading either
BendSetup.Dumpor the tech’sDump.
This is the same workflow you’d use when writing a new test. So reading tests is also rehearsal for writing them.
7. Useful helpers (FX and friends)
| Helper | What it does | Where used |
|---|---|---|
|
Loads |
every fixture |
|
Resolves a path under |
golden-file paths |
|
A scratch path for test output |
dump comparisons |
|
True while running under Flit |
conditionals in production code |
|
Mirror flag inside Flux.Base |
conditionals in low-level code |
|
Loads machine 13 / 99 / etc. |
every Bend test |
|
Loads tool catalog 1 |
inventory setup |
|
Diff-aware text compare |
golden assertions |
8. Running tests — what you actually do
Day-1 caveat. This section describes the intended flow. The exact runner UI evolves; ask your buddy on day 1 for the current command.
The Flit runner is the Flux.Test.exe (built from Test\Flux.Test.csproj). It supports:
-
Console mode for headless / CI runs.
-
A GUI runner for interactive use, including coverage.
Test scope filters are typically by Module, Subsystem, or by a list of test IDs. A typical workflow:
-
Run the smallest meaningful subset while iterating (e.g.
Module=Bend,Subsystem=AutoTool). -
Run the whole suite before opening a PR.
Test inputs come from X:\TData (env var FLUXTESTDATA); make sure that subst drive is mounted and pointing at a fresh clone.
9. Debugging a failing test, read-only
Even if you can’t write code yet, here’s how to debug a failing test in a way that explains the failure:
-
Find the diff.
Assert.AreTextFilesEqualshould print a diff (line-by-line). The first changed line is your scent. -
Match the diff to a
Dumpline. OpenBendSetup.Dump(or the tech’sDump) and trace which property emits that line. -
Set a breakpoint at the property in the production code. Run the test under the debugger.
-
Inspect the difference. Did the value change? Did the calling order change? Did a new code path activate?
-
Compare to git history.
git log -p <file>on the property’s class will often surface the responsible change.
You don’t need to fix it — but at this point you can describe the failure and the suspected cause, which is the deliverable.
10. Five hand-picked tests to read first
| File | Why |
|---|---|
|
Canonical golden-file pattern. Read first. |
|
A grab-bag of historical bugs — entertaining and instructive. |
|
Heavy back-gauge tests (~31 KB). Shows BG-placer flows. |
|
Pure unit tests in Flux.Base — useful for |
|
DXF / GEO reader-writer round-trips. Good for IO understanding. |
11. The seven test "smells" — diagnostics for stale tests
When tests are failing in unexpected ways, look for:
| Smell | What it usually means |
|---|---|
Many goldens change for a small code change |
The dump format changed (review intent). |
One golden changes that no one expected |
Hidden coupling — the property under test feeds the dump indirectly. |
Tests that are skipped ( |
Quarantined work; ask your buddy. |
|
A code path bypassed during tests; understand why before changing. |
Hard-coded machine IDs (13, 99) |
Standard test machines; touching their |
Random-seeded behavior |
Determinism violation; investigate. |
Input fixture missing |
Fresh clone of |
12. Self-check
-
What does
Assert.AreTextFilesEqualdo? (§7) -
Why are most Bend tests golden-file tests rather than direct-property checks? (§3)
-
Where do test IDs come from, and why do they matter? (§1)
-
What does the
Bend2025.csfile mean? (§4) -
If
BendSetup.Dumpchanges its format, what else needs to change? (§3, §11) -
Where is the .geo fixture file
Bend_04.geostored? (§5)
13. If you take just one thing from this chapter
In Flux, tests are documentation. The
.txtgolden files are the most precise spec we have for many subsystems. Read them. When in doubt, the golden is the truth.
Last updated: 2026-05-04. Verified against Test\Bend\BasicBendAuto.cs, Test\Flux.Test.csproj, and the Test\Bend\ inventory.