Test data format
Every algorithm’s test data is one JSON file in the same shape, with fields named by the same rules. Read this once and every file reads the same way. algorithms.json lists every file.
The file
| Property | Holds |
|---|---|
algorithm | The algorithm's slug, as in its page's address: wmm |
placeholder | Only while the values are made up, saying so. Never test against a file that has it. |
publishedDate | When this file was last changed |
expiresDate | Only when the data behind it runs out, like a magnetic model's last day |
earthModel | The earth the numbers are on: WGS84, or a sphere and its radius |
sources | Where the values come from: each with role, name, by, url and licence |
operations | What can be computed: each with an id, what it gives, and the names of its inputs and outputs |
fields | Every input and output name, with what it means and its range |
tolerances | How close each numeric output must be |
cases | The tests: each with an id, an operation, tags, an input and what's expected |
The file has no version. It changes in place, and an implementation is always checked against the current file.
Naming
A field’s name says what it is and, for a number, its unit. The same name means the same thing in every file.
| Kind | Rule | Like |
|---|---|---|
| Every name | lowerCamelCase English words. No abbreviations but established ones. | eastingInMeters |
| A number with a unit | Ends in In and the unit, spelled out | distanceInMeters, deltaTInSeconds, precisionInDigits |
| A number without a unit | Named for what it is | julianDay, decimalYear, illuminationFraction, pointScale |
| An instant | Ends in Utc. ISO 8601 in UTC with a Z, to the second. | riseUtc "2026-06-21T12:04:00Z" |
| A calendar date | Is or ends in date. YYYY-MM-DD. | publishedDate, date |
| Text for a person | Ends in Text | bearingText "000°" |
| A choice | A lowerCamelCase word from the list in the field's meaning | hemisphere "north", phaseName "waxingCrescent" |
| Yes or no | Starts with is or has | isAlwaysUp |
| A pair of places or bearings | Starts with from and to | fromLatitudeInDegrees |
| Angles | Degrees, except where a field says hours. East and north positive; bearings clockwise from north, 0 to 360. | rightAscensionInHours |
| Operations | lowerCamelCase, a verb or the thing given | toMgrs, events |
| Case ids | kebab-case, starting with where the case came from | noaa-3, edge-svalbard-33x |
null means the thing doesn’t exist, like a sunrise on a day without one. It never means unknown.
Comparing
- Only the fields in
expectedare compared. An implementation may return more. - A number passes when it’s within its tolerance: absolute, in the field’s own unit, written as a decimal string. An instant’s tolerance is in seconds.
- Everything else is compared exactly: text, choices, whole numbers,
true,falseandnull. - A tolerance is never loosened to make an implementation pass. If one is wrong, the file changes.
Cases
Each case’s tags say where its values came from and what it tests.
| Tag | Means |
|---|---|
published | The authority's own published value |
reference | Output of the reference program, kept with the file |
hand | Worked out from a definition, like a compass point's name |
edge | A named edge case |
polar | Near a pole |
invalid | Input that must be refused |
A case expecting refusal has "expected": { "error": "outOfRange" }. The errors are outOfRange, for input outside a field’s range, and invalidInput, for input that can’t be read.
Implementations
An implementation is a public repo that follows one contract, so it can be checked the same way in any language. algorithms-template is a GitHub template with the contract already wired up; algorithms-swift is a worked example.
-
mise installsets up its tools, including the checker,algorithms-check, pinned to a version from this repo’s releases:[tools] "github:gshaw/algorithms" = { version = "0.1.0", exe = "algorithms-check" } -
mise run evaluatereads cases on standard input, one JSON object per line, and writes one result per line in any order. It never seesexpected. It runs once per algorithm, and answersnotImplementedfor an algorithm it doesn’t have.in: {"algorithm":"wmm","id":"noaa-table-1","operation":"field","input":{"latitudeInDegrees":80,…}} out: {"id":"noaa-table-1","output":{"magneticDeclinationInDegrees":1.28,…}} out: {"id":"invalid-after-2030","error":"outOfRange"} out: {"id":"utm-1","error":"notImplemented"} mise run testrunsalgorithms-check, which feeds every published file tomise run evaluate, prints each case’s result and writesconformance.json. It skips placeholder files.-
Its CI runs the check weekly and on every push, and commits
conformance.jsonto the root ofmain, where this site reads it.{ "checker": "0.1.0", "source": "https://algorithms.gshaw.ca/algorithms.json", "results": { "wmm": { "status": "passes", "publishedDate": "2026-09-29", "cases": 135, "passed": 135, "failed": 0, "notImplemented": 0 } } }
An algorithm with every case passing passes. One with a failing case fails. One with any notImplemented case is incomplete. A result against an older publishedDate counts as incomplete until the check runs again.
algorithms-check -h lists its options: -only wmm checks one algorithm, and -source takes a directory of test files for working offline.