Tests
Contributor3 min readUpdated
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 CodexLookup's database of items, mounts, pets, recipes, NPCs, rares, quests, zones, dungeons and treasures, with where each comes from (codex build, the Polestar_Codex addon).:
rare {npc, npcName, cls, npcLvl, src, map, x, y, inst}: a unit whoseUnitClassificationisrare,rareeliteorworldboss(srcnameplate,targetormouseover, the player's position), or the creature behind a vignette (srcvignette, the vignette's position,clsonly 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;deniedwhenCanLootUnita 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;qmarks 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 atPLAYER_LEAVING_WORLD) as the entrance.encounter {enc, encName, diff, size, ok, inst, npcs, map, x, y}:ENCOUNTER_END;npcsare the bosses itsencounterUnitStatuslists, else the creatures that died sinceENCOUNTER_START.
data build reads every session's finds together, so counts merge across
sessions (tools/lib/data/recordings.js, createFinds):
- npc
rankfrom the latest classification (rare4,rareelite2,elite1,worldboss3,normal0); levels widenlevel/levelMaxto what was seen; rares and vignette creatures get therarerole. - Drop chance (items
drops, percent, two decimals) = windows holding the item / kills of the npc (slainwithoutdenied, 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;seenkeeps{ 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
chestrole; gathering windows giveherbormine. - 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. instadds toinstances; encounter bosses getencounter; entries and encounters fillinstances.json(entrances clustered within 1.5 map percent, the most used first; encounters with their bosses and wins).- Quest
rewardsfrom 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 stepOne stop in a guide: a title, optional conditions and tip, and at least one goal. change of a leveling
guideOne route, written as a .guide file and compiled to Lua; its id reads like forever/alliance/human/01-elwynn-forest. 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.