Tests

Contributor3 min readUpdated

In short

How the tests run, and the performance budgets they hold the addon to.

Layers, stubs, helpers and the tests that need local data: tests/README.md.

npm test = node --test "tests/**/*.test.js". Lua runs under real lua5.1 through tests/helpers/lua.js, which loads tests/lua/wow_stub.lua and then the addon files listed by the TOC/XML manifests. Extend the stub per module in tests/lua/stub_<module>.lua; wow_stub.lua holds only the generic client pieces every module shares. Keep tests deterministic and behavioural.

Read the rest of this section596 words

Performance is tested, not assumed. tests/perf.test.js loads the whole addon with every module on and the local data packs, and holds these budgets of addon CPU time (event handlers, message listeners, OnUpdate scripts, timers): a accept/turnin also carry the quest frame's rewards when it shows any: items and choices (item ids, GetQuestItemInfo) and rewardMoney.

Finds (Finds.lua), for what the client tables cannot give the Codex:

  • rare {npc, npcName, cls, npcLvl, src, map, x, y, inst}: a unit whose UnitClassification is rare, rareelite or worldboss (src nameplate, target or mouseover, the player's position), or the creature behind a vignette (src vignette, the vignette's position, cls only when the unit was seen). Once per npc per 50 yards per session.
  • treasure {object, objName, src, map, x, y}: the game object behind a vignette, de-duplicated the same way.
  • slain {npc, npcName, cls, npcLvl, map, x, y, inst, diff, denied?}: a creature the player or pet killed (PARTY_KILL), or whose corpse the player looted; denied when CanLootUnit a second later says it has loot the player may not take (tapped, round-robin).
  • drop {npc|object, npcName, items: [ { item, n, q? } ], gather?, inst, diff, map, x, y}: one loot window per source (GetLootSourceInfo, else the dead target), each corpse or object once per session; q marks quest items, gather (herb, mine, skin) a window a gathering cast opened. Fishing is left out.
  • enter {inst, instName, instType, diff, map, x, y}: zoning into a dungeon or raid (GetInstanceInfo), with the last outdoor position (taken at PLAYER_LEAVING_WORLD) as the entrance.
  • encounter {enc, encName, diff, size, ok, inst, npcs, map, x, y}: ENCOUNTER_END; npcs are the bosses its encounterUnitStatus lists, else the creatures that died since ENCOUNTER_START.

data build reads every session's finds together, so counts merge across sessions (tools/lib/data/recordings.js, createFinds):

  • npc rank from the latest classification (rare 4, rareelite 2, elite 1, worldboss 3, normal 0); levels widen level/levelMax to what was seen; rares and vignette creatures get the rare role.
  • Drop chance (items drops, percent, two decimals) = windows holding the item / kills of the npc (slain without denied, never fewer than its windows); for objects, windows holding it / windows opened. From 10 kills or opens up it replaces the Era quest database's or the community quest database's chance, below that it only fills a missing or unknown (null) one; seen keeps { n, of } either way. Skinning windows are no drops.
  • An object whose window held a non-quest item, or seen behind a vignette, gets the chest role; gathering windows give herb or mine.
  • Sighting and opening positions join the entity's spawns: a map without spawns gets them as "l", a live-frame map takes them in, and so does an Era map whose frame Forever kept (meta.liveFrameMaps). Kill positions only fill a map without spawns.
  • inst adds to instances; encounter bosses get encounter; entries and encounters fill instances.json (entrances clustered within 1.5 map percent, the most used first; encounters with their bosses and wins).
  • Quest rewards from the frames, a turn-in's over an accept's.

meta.counts gives recordedKills, recordedLoots, recordedSightings, recordedDropChances, recordedTreasures, recordedInstances and recordedEncounters. burst of 50 QUEST_LOG_UPDATE and 50 BAG_UPDATE in one frame under 4 ms, a walking frame under 1 ms, SetGuide and every step change of a leveling guide under 8 ms (with what they schedule), and a gathering guide played to the end in under 15 s. When one fails, node tests/helpers/profile.js <guide> [race] [class] --packs [--sample=1000] plays a guide with every handler timed by module (tests/lua/profile.lua) and, with --sample, a stack sampler for the functions and lines that cost the time.

Was this page helpful?

Start with, or act

  • PlayersInstall and first run
  • PlayersCommunity guides
  • PlayersFAQ
  • Guide authorsWriting a community guide
  • Guide authorsGuide format cheatsheet
  • ContributorsContributing
  • ActionCopy the AddOns folder (Windows)C:\Program Files (x86)\World of Warcraft\_classic_beta_\Interface\AddOns
  • ActionCopy the AddOns folder (macOS)/Applications/World of Warcraft/_classic_beta_/Interface/AddOns
  • ActionFind an optionEvery setting with its default; type its name here to jump to it.
  • ActionEvery slash command