Skip to content

Commit

Permalink
test: add ragepotion test (#96)
Browse files Browse the repository at this point in the history
* test: add playmode test

* tset: add rage potion aplib test

* test: rage potion test now also tests damage on enemy

* fix: add GameManager to scene to fix when running multiple tests

* chore: address wall of nits
  • Loading branch information
JoenvandeVorle authored Jun 14, 2024
1 parent 1780441 commit 5a820a0
Show file tree
Hide file tree
Showing 8 changed files with 5,920 additions and 12 deletions.
5,621 changes: 5,621 additions & 0 deletions aplib.net-demo/Assets/Scenes/TestScenes/RagePotionTestScene.unity

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 38 additions & 12 deletions aplib.net-demo/Assets/Scripts/Items/RagePotion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,44 @@ namespace Assets.Scripts.Items
[RequireComponent(typeof(PickupableItem))]
public class RagePotion : Item
{
[SerializeField]
private GameObject _rageEffect;
/// <summary>
/// The percentage increase of the player's damage.
/// </summary>
[field: SerializeField]
public int DamageIncreasePercentage { get; private set; } = 100;

/// <summary>
/// The duration of the rage potion effect in seconds.
/// </summary>
[field: SerializeField]
public float Duration { get; private set; } = 3f;

/// <summary>
/// The visual effect that plays when the player uses the rage potion.
/// </summary>
[SerializeField]
private int _damageIncreasePercentage = 50;
private GameObject _rageEffect;

/// <summary>
/// The concrete damage increase that the player receives from the rage potion.
/// </summary>
private int _damageIncrease;

[SerializeField]
private float _duration = 3; // In seconds

/// <summary>
/// The player object in the scene.
/// </summary>
private GameObject _player;
private Weapon _playerWeapon;

/// <summary>
/// The player's equipment inventory.
/// </summary>
private EquipmentInventory _playerInventory;

protected override void Awake()
{
base.Awake();
_player = GameObject.FindGameObjectWithTag("Player");
_playerWeapon = _player.GetComponentInChildren<Weapon>();
_damageIncrease = _playerWeapon.Damage * _damageIncreasePercentage / 100;
_playerInventory = _player.GetComponentInChildren<EquipmentInventory>();
}

/// <summary>
Expand All @@ -44,14 +62,22 @@ public override void UseItem()

private IEnumerator ActivateRage()
{
_playerWeapon.Damage += _damageIncrease;
Weapon activeWeapon = _playerInventory.CurrentEquipment as Weapon;
if (activeWeapon == null)
{
Debug.LogWarning("Player does not have a weapon equipped!.");
yield break;
}

_damageIncrease = activeWeapon.Damage * DamageIncreasePercentage / 100;
activeWeapon.Damage += _damageIncrease;

// Add player visual effect as child of player
GameObject rageEffect = Instantiate(_rageEffect, _player.transform);

yield return new WaitForSeconds(_duration);
yield return new WaitForSeconds(Duration);

_playerWeapon.Damage -= _damageIncrease;
activeWeapon.Damage -= _damageIncrease;

// Remove player visual effect
Destroy(rageEffect);
Expand Down
157 changes: 157 additions & 0 deletions aplib.net-demo/Assets/Testing/AplibTests/RagePotionAplibTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using Aplib.Core;
using Aplib.Core.Agents;
using Aplib.Core.Belief.Beliefs;
using Aplib.Core.Belief.BeliefSets;
using Aplib.Core.Desire.DesireSets;
using Aplib.Core.Desire.Goals;
using Aplib.Core.Intent.Actions;
using Aplib.Core.Intent.Tactics;
using Aplib.Integrations.Unity;
using Aplib.Integrations.Unity.Actions;
using Assets.Scripts.Items;
using Entities.Weapons;
using NUnit.Framework;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
using static Aplib.Core.Combinators;

namespace Testing.AplibTests
{
public class RagePotionBeliefSet : BeliefSet
{
/// <summary>
/// The player object in the scene.
/// </summary>
public Belief<GameObject, GameObject> Player = new(GameObject.Find("Player"), x => x);

/// <summary>
/// The rage potion in the scene.
/// </summary>
public Belief<GameObject, RagePotion> RagePotion = new(GameObject.Find("RagePotion"), x => x != null ? x.GetComponent<RagePotion>() : null);

/// <summary>
/// The target dummy health in the scene.
/// </summary>
// public Belief<GameObject, GameObject> TargetDummy = new(GameObject.Find("Target Dummy"), x => x);
public MemoryBelief<GameObject, int> TargetDummyHealth = new(GameObject.Find("Target Dummy"), x => x.GetComponentInChildren<HealthComponent>().Health, 60);


/// <summary>
/// The inventory in the scene.
/// </summary>
public Belief<GameObject, Inventory> InventoryObject = new(GameObject.Find("InventoryObject"), x => x.GetComponent<Inventory>());

/// <summary>
/// The player weapon in the scene.
/// </summary>
public Belief<GameObject, Weapon> PlayerWeapon = new(GameObject.Find("Player"), x => x.GetComponentInChildren<EquipmentInventory>().CurrentEquipment as Weapon);

/// <summary>
/// The target position that the player needs to move towards.
/// Find the first Rage Potion in the scene.
/// </summary>
public Belief<GameObject, Vector3> PotionPosition = new(GameObject.Find("RagePotion"), x => x == null ? Vector3.zero : x.transform.position);

public Belief<GameObject, Vector3> EnemyPosition = new(GameObject.Find("Target Dummy"), x => x == null ? Vector3.zero : x.transform.position);

/// <summary>
/// The rage potion in the scene.
/// </summary>
public Belief<GameObject, bool> PotionExists = new(GameObject.Find("RagePotion"), x => x != null && x.activeSelf && x.activeInHierarchy);
}

public class RagePotionAplibTest
{
private int _increasedDamage;
private int _startDamage;

[SetUp]
public void SetUp()
{
Debug.Log($"Starting test {nameof(RagePotionAplibTest)}");
SceneManager.LoadScene("RagePotionTestScene");
}

/// <summary>
/// The player will walk up to a rage potion and use it.
/// Then check if the rage potion doubles the players damage when damaging an entity.
/// </summary>
[UnityTest]
public IEnumerator PerformRagePotionAplibTest()
{
InputManager.Instance.enabled = false;
RagePotionBeliefSet ragePotionBeliefSet = new RagePotionBeliefSet();

// Calculate the expected damage increase
int damageIncreasePercentage = ragePotionBeliefSet.RagePotion.Observation.DamageIncreasePercentage;
_startDamage = ragePotionBeliefSet.PlayerWeapon.Observation.Damage;
_increasedDamage = _startDamage + _startDamage * damageIncreasePercentage / 100;

// Action: Create an action that moves towards the potion
TransformPathfinderAction<RagePotionBeliefSet> moveToPotionAction = new(
objectQuery: beliefSet => beliefSet.Player.Observation.GetComponent<Rigidbody>(),
location: beliefSet => beliefSet.PotionPosition,
heightOffset: 0.3f
);

// Action: Create an action that moves towards the enemy
TransformPathfinderAction<RagePotionBeliefSet> moveToEnemyAction = new(
objectQuery: beliefSet => beliefSet.Player.Observation.GetComponent<Rigidbody>(),
location: beliefSet => beliefSet.EnemyPosition,
heightOffset: 0.3f
);

// Action: Use current inventory item (health potion).
Action<RagePotionBeliefSet> activateInventoryItem = new(b => b.InventoryObject.Observation.ActivateItem());
// Action: Attack the enemy, when at its position
Action<RagePotionBeliefSet> useWeaponAction = new(b => b.PlayerWeapon.Observation.UseWeapon());
PrimitiveTactic<RagePotionBeliefSet> useWeaponTactic = new(useWeaponAction, AtEnemyPositionPredicate);
FirstOfTactic<RagePotionBeliefSet> attackEnemyTactic = new(useWeaponTactic, moveToEnemyAction.Lift());

// Goals: Reach the target position and use the rage potion.
Goal<RagePotionBeliefSet> potionPickedUpGoal = new(moveToPotionAction.Lift(), PotionPickedUpPredicate);
Goal<RagePotionBeliefSet> damageIncreasedGoal = new(activateInventoryItem.Lift(), DamageIncreasedPredicate);
// Goal: The enemy should take increased damage from the player
Goal<RagePotionBeliefSet> enemyTookIncreasedDamageGoal = new(attackEnemyTactic, EnemyTookIncreasedDamagePredicate);

// Desire: Reach the target position and use the rage potion.
DesireSet<RagePotionBeliefSet> desire = Seq(potionPickedUpGoal.Lift(), damageIncreasedGoal.Lift(), enemyTookIncreasedDamageGoal.Lift());

// Create a new agent with the goal.
BdiAgent<RagePotionBeliefSet> agent = new(ragePotionBeliefSet, desire);

AplibRunner runner = new(agent);

// Use the Assert class to test conditions.
// Use yield to skip a frame.
yield return runner.Test();

// Assert that the agent has completed the goal.
Assert.AreEqual(CompletionStatus.Success, agent.Status);
yield break;

bool PotionPickedUpPredicate(RagePotionBeliefSet beliefSet)
{
// The potion is in the player's inventory
bool potionExists = beliefSet.PotionExists;
bool potionInInventory = beliefSet.InventoryObject.Observation.ContainsItem("RagePotion");
return !potionExists && potionInInventory;
}

bool DamageIncreasedPredicate(RagePotionBeliefSet beliefSet)
=> beliefSet.PlayerWeapon.Observation.Damage == _increasedDamage;

bool AtEnemyPositionPredicate(RagePotionBeliefSet beliefSet)
=> Vector3.Distance(beliefSet.Player.Observation.transform.position, beliefSet.EnemyPosition) < 1f;

bool EnemyTookIncreasedDamagePredicate(RagePotionBeliefSet beliefSet)
{
int prevEnemyHealth = beliefSet.TargetDummyHealth.GetMostRecentMemory();
int enemyHealth = beliefSet.TargetDummyHealth.Observation;
return prevEnemyHealth - enemyHealth == _increasedDamage;
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 72 additions & 0 deletions aplib.net-demo/Assets/Testing/PlaymodeTests/RagePotionTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Assets.Scripts.Items;
using Entities.Weapons;
using NUnit.Framework;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;

public class RagePotionTest
{
[SetUp]
public void SetUp()
{
Debug.Log($"Starting test {nameof(RagePotionTest)}");
SceneManager.LoadScene("RagePotionTestScene");
}

/// <summary>
/// Test if the rage potion doubles the damage of the player.
/// </summary>
[UnityTest]
public IEnumerator RagePotionDoublesDamage()
{
// Get the player object
GameObject player = GameObject.Find("Player");
EquipmentInventory equipmentInventory = player.GetComponentInChildren<EquipmentInventory>();
Weapon activeWeapon = (equipmentInventory.CurrentEquipment as Weapon)!;

// Get the rage potion
GameObject ragePotionObj = GameObject.Find("RagePotion");
RagePotion ragePotion = ragePotionObj.GetComponent<RagePotion>();

// Calculate the expected damage increase
int damageIncrease = activeWeapon.Damage * ragePotion.DamageIncreasePercentage / 100;
int expectedDamage = activeWeapon.Damage + damageIncrease;

// Use the rage potion
ragePotion.UseItem();

yield return null;

// Check if the player's damage has increased
Assert.AreEqual(expectedDamage, activeWeapon.Damage);
}

/// <summary>
/// Test if the player's damage returns to normal after the rage potion effect is over.
/// </summary>
[UnityTest]
public IEnumerator ReturnsToNormalAfterTimer()
{
// Get the player object
GameObject player = GameObject.Find("Player");
EquipmentInventory equipmentInventory = player.GetComponentInChildren<EquipmentInventory>();
Weapon activeWeapon = (equipmentInventory.CurrentEquipment as Weapon)!;
int playerDamageBefore = activeWeapon.Damage;

// Get the rage potion
GameObject ragePotionObj = GameObject.Find("RagePotion");
RagePotion ragePotion = ragePotionObj.GetComponent<RagePotion>();

// Use the rage potion
ragePotion.GetComponent<RagePotion>().UseItem();
Debug.Log("Rage potion duration: " + ragePotion.Duration);

// Wait for the timer to finish
yield return new WaitForSeconds(ragePotion.Duration);

// Check if the player's damage has returned to normal
Assert.AreEqual(playerDamageBefore, activeWeapon.Damage);
}
}
11 changes: 11 additions & 0 deletions aplib.net-demo/Assets/Testing/PlaymodeTests/RagePotionTest.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions aplib.net-demo/ProjectSettings/EditorBuildSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,7 @@ EditorBuildSettings:
- enabled: 1
path: Assets/Scenes/LevelGeneration.unity
guid: b0a7e51e6d0f74240b2f471859202058
- enabled: 1
path: Assets/Scenes/TestScenes/RagePotionTestScene.unity
guid: fe6a4c501dcc2d74891b9cfbd950276b
m_configObjects: {}

0 comments on commit 5a820a0

Please sign in to comment.