Skip to content

Test Runs

Jared Wright edited this page Aug 10, 2026 · 1 revision

Automated test runs (.dc test)

A GM-only harness, not part of normal play. One command rolls a random five-bot party, levels and gears it, sends it to a dungeon entrance and lets it clear the place on its own. You stay out of the party and watch. Every run records its seed, so a run that hits a bug can be replayed with the exact same party.

It exists to answer "did my change help?" with a number instead of an anecdote — run the same dungeon fifty times and compare success rates. If you would rather drive that from a browser than from chat, see the Test Deck.

Commands

Everything below is SEC_GAMEMASTER.

Command What it does
.dc test list Supported dungeons, their tokens, map ids and default levels (and heroic level, where there is one).
.dc test start <dungeon> [options] Start a run. See Starting a run.
.dc test status Progress of every live run, and of every live plan.
.dc test stop [runId|dungeon|all] Abort runs. Bare stops the single active run; all also stops every plan first, so the scheduler cannot relaunch what you just aborted.
.dc test gear <dungeon> [heroic] The item-level ceilings worth running that dungeon at.
.dc test watch [runId|dungeon|next|off] Ride a live run's camera. See Watching.
.dc test plan start <dungeon> total=N [options] Run the same dungeon N times, up to concurrent at once, then write a summary.
.dc test plan status Progress of each live plan.
.dc test plan stop [planId|all] Stop a plan and its runs.

Everything except watch also works from the worldserver console and from the Test Deck — see Running without a player, below.

Starting a run

.dc test start <dungeon> [heroic] [level=N] [seed=N] [ilvl=N|none] [quality=normal|uncommon|rare|epic|legendary]
.dc test start <dungeon> party=Tank,Heal,Dps1,Dps2,Dps3 [heroic]

<dungeon> is a token from .dc test list (sfk, dm-west, mgt, …) or a raw map id. Wing-split dungeons are separate tokens — dm-east, sm-cath — and run one wing at a time.

Option Effect
heroic Run the heroic version. Only offered for the TBC dungeons that have one; .dc test list shows which.
level=N Level the bots to N instead of the dungeon's recommended level.
seed=N Replay a specific comp. Omitted or 0 rolls a fresh one.
ilvl=N / ilvl=none Cap the item level the bots are geared to (1–400, or no limit).
quality=… Cap the gear quality (normallegendary, or 1–5).
party=… Use five real player characters instead of pool bots, roles positional (tank, healer, then three DPS).

The gear options exist because bots are normally geared to the server-wide AiPlayerbot.AutoGearScoreLimit / AutoGearQualityLimit, so comparing a party in Karazhan-era gear against the same party in Sunwell gear used to mean editing the conf and reloading between runs. A run now carries its own ceiling. .dc test gear <dungeon> lists the ceilings worth using for that dungeon — steps around its own level band, plus the named raid tiers at the level cap.

level=, seed= and the gear options are rejected on a party= run rather than silently ignored: the level comes from the characters, the roster is the comp, and real characters are never relevelled or re-geared.

The party

Five bots — one tank, one healer, three DPS — on five different classes, drawn per run from the role pools and seeded so the same seed always yields the same comp. Tanks come from protection warrior / protection paladin / bear druid; healers from holy and discipline priest, holy paladin, restoration shaman and restoration druid; DPS from every remaining PvE spec. Death knights are excluded, because their level floor breaks low-level dungeons.

Each spec is named by its playerbots premade-spec template (AiPlayerbot.PremadeSpecName.<class>.<n>) and resolved at provisioning time. A tank or healer spec with no matching template fails the run loudly rather than silently rolling a random build.

Plans (batched campaigns)

.dc test plan start <dungeon> [heroic] total=N [concurrent=N] [level=N] [seed=N] [ilvl=N|none] [quality=…]

A plan launches total runs of one dungeon, keeping at most concurrent of them in flight, and appends a summary line when it finishes. This is how you get a success rate. Global ceilings live in the conf (DungeonClear.TestRun.MaxConcurrent, .MaxPlans, .Plan.MaxTotal), with 0 meaning "no limit".

Watching

.dc test watch <runId|dungeon> hides you, binds and teleports you to that run's instance entrance (your body stays out of the party's way — the camera is farsight), and follows its tank on arrival.

  • Running it again for another run hops you straight there; the previous instance is left and unbound for you, so a finished heroic copy does not sit there holding your daily lockout.
  • .dc test watch next hops to the next live run and wraps, so you can tour a whole plan without reading run ids off .dc test status. It stays put when there is nowhere to go.
  • .dc test watch off ends the camera, returns you to where you started, and drops the binds it made.

From a follow camera, a bare .dc spectate steps into the free-flying camera at the bot you were watching; press it again to stop.

watch is the one subcommand with no console form — a camera needs a session to attach to.

Running without a player

The harness is built around an issuing GM: the party bots log in under that player's account and keep them as their playerbots master, which is what holds them on the stock real-player fast path. When a GM types .dc test start in-game, they are it.

A console or Test Deck launch has no such player, so the module logs one dedicated character in headlessly and parks it as the stand-in GM. It creates that character and its account the first time one is needed:

Setting Default Notes
DungeonClear.TestRun.DriverCharacter Dcdriver Resolved by exact, case-sensitive lookup. The module refuses to create a name it could not look up again.
DungeonClear.TestRun.DriverAccount dcdriver Created as a plain player account; the session is elevated, not the account. Must not be a RandomBotAccounts or addclass-pool account, or the bot rotation would log the driver out from under a live run. Set to "" to turn provisioning off and supply the character yourself.

The very first console launch may answer "is logging in — retry in a few seconds" while that happens.

How a run is judged

A run succeeds when every boss is down. Otherwise the first of these to match ends it:

Verdict Trigger
aborted .dc test stop, the GM logging out, or the leader going missing.
party_wiped Every member dead past a 15s grace — long enough for a battle rez or soulstone to un-wipe it.
paused_timeout A pause outlasting DungeonClear.TestRun.PauseGraceS (default 60). A test run never gets the human input a pause waits for.
stalled_timeout A stall outlasting DungeonClear.TestRun.StallGraceS (default 120), giving the stall-recovery ladder time to work.
no_progress No boss or objective progress for DungeonClear.TestRun.NoProgressS (default 600) — the silent-livelock net.
overall_timeout DungeonClear.TestRun.OverallTimeoutS (default 3600).
disabled The run's own disable funnel fired for a non-"all cleared" reason.

Where the results go

All of these are written by relative name, so they land in the worldserver's working directory — which is not necessarily the directory the binary lives in.

File Contents
dc_testruns.jsonl One JSON line per finished run: comp, result, fail reason, boss/status/pull timelines, deaths, pauses, watchdog budgets, and the teardown diagnostic snapshot. Override with DC_TESTRUNS_FILE.
dc_testplans.jsonl One summary line per finished plan. Override with DC_TESTPLANS_FILE.
dc_testrun_live.json Live state of every in-flight run and plan; this is what the Test Deck's Live panel reads.
dc_test_dungeons.json The dungeon catalogue, written shortly after startup.

In the log, each run's lines are bracketed by TESTRUN START and TESTRUN END markers. Note that the log appenders open in truncate mode, so a worldserver restart wipes them — for an older run, the JSONL record and its diagnostic snapshot are all that survive.

Caveats worth knowing

  • Heroic lockouts are real. A heroic run spends the map's daily lockout, and so does parking a watcher in a finished copy — which is why watch off drops its binds on the way out.
  • Bot parties fire no client packets. An area trigger is a client-side volume: nothing server-side notices a unit entering one, so a party of five bots with no game client behind any of them fires no at_* scripts at all, and several boss set-pieces simply never start. A test run closes that gap by relaying the packet itself — but deliberately only for bot-only groups (a human or self-bot in the party is already sending it), and only for scripted, non-teleport triggers (relaying the instance exit would end the run by walking past it). Outside that scope the gap is still there, which is why several encounters carry an explicit event to start them (see Scripted Dungeon Events). It remains the first thing to suspect when a set-piece is skipped in a test run but works when you play it yourself.
  • A global instance reset ends every run at once. If a whole batch fails within the same second with the party standing at a graveyard, that is the server's scheduled reset, not your change.

Clone this wiki locally