Skip to content

Commit

Permalink
Create interaction test harness. (#27643)
Browse files Browse the repository at this point in the history
* Create interaction test harness.

* retrofit tests, add janicart attack chain tests

* extract puppeteer to separate file

* move puppeteer creation to constructor
  • Loading branch information
warriorstar-orion authored Dec 23, 2024
1 parent 5c549ad commit 33eaf8a
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
68 changes: 68 additions & 0 deletions code/tests/_game_test_puppeteer.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* A testing object used to control mobs in game tests.
*
* Puppeteers provide an easy way to create mobs and objects,
* perform interactions in the same way that a player would,
* and check the state of the mob during tests.
*/
/datum/test_puppeteer
var/mob/living/carbon/puppet
var/datum/game_test/origin_test

/datum/test_puppeteer/New(datum/game_test/origin_test_, carbon_type = /mob/living/carbon/human, turf/initial_location)
if(!ispath(carbon_type, /mob/living/carbon/human))
origin_test.Fail("unexpected puppeteer carbon type [carbon_type]", __FILE__, __LINE__)

if(!initial_location)
initial_location = locate(179, 136, 1) // Center of admin testing area
origin_test = origin_test_
puppet = origin_test.allocate(carbon_type, initial_location)
var/datum/mind/new_mind = new("interaction_test_[puppet.UID()]")
new_mind.transfer_to(puppet)

/datum/test_puppeteer/proc/spawn_puppet_nearby(carbon_type = /mob/living/carbon/human)
for(var/turf/T in RANGE_TURFS(1, puppet.loc))
if(!is_blocked_turf(T, exclude_mobs = FALSE))
return new/datum/test_puppeteer(origin_test, carbon_type, T)

origin_test.Fail("could not spawn puppeteer near [src]")

/datum/test_puppeteer/proc/spawn_obj_in_hand(obj_type)
var/obj/new_obj = origin_test.allocate(obj_type, null)
if(puppet.put_in_hands(new_obj))
return new_obj

origin_test.Fail("could not spawn obj [obj_type] in hand of [puppet]")

/datum/test_puppeteer/proc/spawn_obj_nearby(obj_type)
for(var/turf/T in RANGE_TURFS(1, puppet.loc))
if(!is_blocked_turf(T, exclude_mobs = FALSE))
return origin_test.allocate(obj_type, T)

origin_test.Fail("could not spawn obj [obj_type] near [src]")

/datum/test_puppeteer/proc/click_on(target, params)
var/datum/test_puppeteer/puppet_target = target
sleep(max(puppet.next_click, puppet.next_move) - world.time + 1)
if(istype(puppet_target))
puppet.ClickOn(puppet_target.puppet, params)
return

puppet.ClickOn(target, params)

/datum/test_puppeteer/proc/spawn_mob_nearby(mob_type)
for(var/turf/T in RANGE_TURFS(1, puppet))
if(!is_blocked_turf(T, exclude_mobs = FALSE))
var/mob/new_mob = origin_test.allocate(mob_type, T)
return new_mob

/datum/test_puppeteer/proc/check_attack_log(snippet)
for(var/log_text in puppet.attack_log_old)
if(findtextEx(log_text, snippet))
return TRUE

/datum/test_puppeteer/proc/set_intent(new_intent)
puppet.a_intent_change(new_intent)

/datum/test_puppeteer/proc/rejuvenate()
puppet.rejuvenate()
17 changes: 17 additions & 0 deletions code/tests/attack_chain/test_attack_chain_cult_dagger.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/datum/game_test/attack_chain_cult_dagger/Run()
var/datum/test_puppeteer/cultist = new(src)
var/datum/test_puppeteer/target = cultist.spawn_puppet_nearby()

cultist.puppet.mind.add_antag_datum(/datum/antagonist/cultist)
cultist.spawn_obj_in_hand(/obj/item/melee/cultblade/dagger)
cultist.set_intent("harm")
cultist.click_on(target)

TEST_ASSERT(target.check_attack_log("Attacked with ritual dagger"), "non-cultist missing dagger attack log")
TEST_ASSERT_NOTEQUAL(target.puppet.health, target.puppet.getMaxHealth(), "cultist attacking non-cultist with dagger caused no damage")

target.rejuvenate()
target.puppet.mind.add_antag_datum(/datum/antagonist/cultist)

cultist.click_on(target)
TEST_ASSERT_EQUAL(target.puppet.health, target.puppet.getMaxHealth(), "cultist attacking cultist with dagger caused damage")
26 changes: 26 additions & 0 deletions code/tests/attack_chain/test_attack_chain_vehicles.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/datum/game_test/attack_chain_vehicles/Run()
var/datum/test_puppeteer/player = new(src)
var/obj/item/key/janitor/janicart_key = player.spawn_obj_in_hand(/obj/item/key/janitor)
var/obj/vehicle/janicart/janicart = player.spawn_obj_nearby(/obj/vehicle/janicart)

player.click_on(janicart)
TEST_ASSERT_EQUAL(janicart.inserted_key, janicart_key, "did not find janicart key in vehicle")

var/move_delay = janicart.vehicle_move_delay
player.spawn_obj_in_hand(/obj/item/borg/upgrade/vtec)
player.click_on(janicart)
TEST_ASSERT(janicart.vehicle_move_delay < move_delay, "VTEC upgrade not applied properly")

TEST_ASSERT_NULL(janicart.mybag, "unexpected trash bag on janicart")
var/obj/item/storage/bag/trash/bag = player.spawn_obj_in_hand(/obj/item/storage/bag/trash)
player.click_on(janicart)
TEST_ASSERT_EQUAL(janicart.mybag, bag, "trash bag not attached to janicart")

var/obj/item/kitchen/knife/knife = player.spawn_obj_in_hand(/obj/item/kitchen/knife)
player.set_intent("harm")
player.click_on(janicart)
TEST_ASSERT(janicart.obj_integrity < janicart.max_integrity, "knife attack not performed")

player.set_intent("help")
player.click_on(janicart)
TEST_ASSERT(knife in bag, "knife not placed in trash bag")
3 changes: 3 additions & 0 deletions code/tests/game_tests.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
//Keep this sorted alphabetically

#ifdef GAME_TESTS
#include "_game_test_puppeteer.dm"
#include "_game_test.dm"
#include "atmos\test_ventcrawl.dm"
#include "attack_chain\test_attack_chain_cult_dagger.dm"
#include "attack_chain\test_attack_chain_vehicles.dm"
#include "games\test_cards.dm"
#include "jobs\test_job_globals.dm"
#include "test_aicard_icons.dm"
Expand Down
10 changes: 9 additions & 1 deletion code/tests/test_runner.dm
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,15 @@

if(!test.succeeded)
failed_any_test = TRUE
test_logs[I] += test.fail_reasons
for(var/fail_reason in test.fail_reasons)
if(islist(fail_reason))
var/text = fail_reason[1]
var/file = fail_reason[2]
var/line = fail_reason[3]

test_logs[I] += "[file]:[line]: [text]"
else
test_logs[I] += fail_reason

qdel(test)

Expand Down

0 comments on commit 33eaf8a

Please sign in to comment.