mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-03 12:54:43 +07:00
Unit tests for Battle.kt (#10127)
* ✨ add testing helper function to create the barbarian civilization * add tests for Battle class * add more tests for Battle class * ♻️ let compiler infer types * add helper test methods to create unit with uniques * use unit with unique explicitly created to loose tests from specific ruleset * add even more tests for Battle
This commit is contained in:
parent
bdd3af9a43
commit
fba3198887
@ -146,8 +146,7 @@ class BattleDamageTest {
|
||||
// given
|
||||
val defenderTile = testGame.getTile(Vector2.Zero)
|
||||
testGame.setTileFeatures(defenderTile.position, Constants.hill)
|
||||
defenderCiv.resourceStockpiles.add("Horses", 1) // no resource penalty
|
||||
val defenderUnit = testGame.addUnit("Horseman", defenderCiv, defenderTile)
|
||||
val defenderUnit = testGame.addDefaultMeleeUnitWithUniques(defenderCiv, defenderTile, "No defensive terrain bonus")
|
||||
|
||||
// when
|
||||
val defenceModifiers = BattleDamage.getDefenceModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defenderUnit), defaultAttackerTile)
|
||||
|
341
tests/src/com/unciv/logic/battle/BattleTest.kt
Normal file
341
tests/src/com/unciv/logic/battle/BattleTest.kt
Normal file
@ -0,0 +1,341 @@
|
||||
package com.unciv.logic.battle
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import com.unciv.testing.TestGame
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(GdxTestRunner::class)
|
||||
class BattleTest {
|
||||
private lateinit var attackerCiv: Civilization
|
||||
private lateinit var defenderCiv: Civilization
|
||||
|
||||
private lateinit var defaultAttackerUnit: MapUnit
|
||||
private lateinit var defaultDefenderUnit: MapUnit
|
||||
|
||||
private val testGame = TestGame()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
testGame.makeHexagonalMap(4)
|
||||
attackerCiv = testGame.addCiv()
|
||||
defenderCiv = testGame.addCiv()
|
||||
|
||||
defaultAttackerUnit = testGame.addUnit("Warrior", attackerCiv, testGame.getTile(Vector2.X))
|
||||
defaultAttackerUnit.currentMovement = 2f
|
||||
defaultDefenderUnit = testGame.addUnit("Warrior", defenderCiv, testGame.getTile(Vector2.Zero))
|
||||
defaultDefenderUnit.currentMovement = 2f
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `defender should withdraw from melee attack if has the unique to do so`() {
|
||||
val defenderUnit = testGame.addDefaultMeleeUnitWithUniques(attackerCiv, testGame.getTile(Vector2.Y), "May withdraw before melee ([100]%)")
|
||||
defenderUnit.currentMovement = 2f
|
||||
|
||||
// when
|
||||
val damageDealt = Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defenderUnit))
|
||||
|
||||
// thenvi
|
||||
assertEquals(0, damageDealt.attackerDealt)
|
||||
assertEquals(0, damageDealt.defenderDealt)
|
||||
assertFalse(defenderUnit.getTile().position == Vector2.Y) // defender moves away
|
||||
assertEquals(Vector2.X, defaultAttackerUnit.getTile().position) // attacker didn't move
|
||||
assertEquals(0f, defaultAttackerUnit.currentMovement) // warriors cannot move anymore after attacking
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `both defender and attacker should do damage when are melee`() {
|
||||
// when
|
||||
val damageDealt = Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(31, damageDealt.attackerDealt)
|
||||
assertEquals(31, damageDealt.defenderDealt)
|
||||
assertEquals(69, defaultAttackerUnit.health)
|
||||
assertEquals(69, defaultDefenderUnit.health)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `only attacker should do damage when he's ranged`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addUnit("Archer", attackerCiv, testGame.getTile(Vector2.Y))
|
||||
|
||||
// when
|
||||
val damageDealt = Battle.attack(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(28, damageDealt.attackerDealt)
|
||||
assertEquals(0, damageDealt.defenderDealt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should move to enemy position when melee killing`() {
|
||||
// given
|
||||
defaultDefenderUnit.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(Vector2.Zero, defaultAttackerUnit.getTile().position)
|
||||
assertTrue(defaultDefenderUnit.isDestroyed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should stay in original position when ranged killing`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addUnit("Archer", attackerCiv, testGame.getTile(Vector2.Y))
|
||||
defaultDefenderUnit.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(Vector2.Y, attackerUnit.getTile().position)
|
||||
assertTrue(defaultDefenderUnit.isDestroyed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `both attacker and defender should earn XP`() {
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(5, defaultAttackerUnit.promotions.XP)
|
||||
assertEquals(4, defaultDefenderUnit.promotions.XP)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should earn XP when fighting barbarian and below XP cap`() {
|
||||
// given
|
||||
val barbarianCiv = testGame.addBarbarianCiv()
|
||||
val barbarianUnit = testGame.addUnit("Brute", barbarianCiv, testGame.getTile(Vector2.Y))
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(barbarianUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(5, barbarianUnit.promotions.XP)
|
||||
assertEquals(4, defaultDefenderUnit.promotions.XP)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not earn XP when fighting barbarian if exceeding XP cap`() {
|
||||
// given
|
||||
val barbarianCiv = testGame.addBarbarianCiv()
|
||||
val barbarianUnit = testGame.addUnit("Brute", barbarianCiv, testGame.getTile(Vector2.Y))
|
||||
defaultDefenderUnit.promotions.XP = 35
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(barbarianUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(5, barbarianUnit.promotions.XP)
|
||||
assertEquals(35, defaultDefenderUnit.promotions.XP)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `attacker should expend all movement points to attack without uniques`() {
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(0f, defaultAttackerUnit.currentMovement)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `attacker should still have movement points left with 'additional attack per turn' unique`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addDefaultMeleeUnitWithUniques(attackerCiv, testGame.getTile(Vector2.Y), "[1] additional attacks per turn")
|
||||
attackerUnit.currentMovement = 2f
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(1f, attackerUnit.currentMovement)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `attacker should still have movement points left with 'can move after attacking' unique`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addDefaultMeleeUnitWithUniques(attackerCiv, testGame.getTile(Vector2.Y), "Can move after attacking")
|
||||
attackerUnit.currentMovement = 2f
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(1f, attackerUnit.currentMovement)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should capture civilian`() {
|
||||
// given
|
||||
val defenderUnit = testGame.addUnit("Worker", defenderCiv, testGame.getTile(Vector2(2f, 0f)))
|
||||
|
||||
// when
|
||||
val attack = Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(0, attack.attackerDealt)
|
||||
assertEquals(0, attack.defenderDealt)
|
||||
assertEquals(Vector2(2f, 0f), defaultAttackerUnit.getTile().position)
|
||||
assertEquals(attackerCiv, defaultAttackerUnit.getTile().civilianUnit!!.civ) // captured unit
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should transform settler into worker upon capture`() {
|
||||
// given
|
||||
val defenderUnit = testGame.addUnit("Settler", defenderCiv, testGame.getTile(Vector2(2f, 0f)))
|
||||
|
||||
// when
|
||||
val attack = Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(0, attack.attackerDealt)
|
||||
assertEquals(0, attack.defenderDealt)
|
||||
assertEquals(Vector2(2f, 0f), defaultAttackerUnit.getTile().position)
|
||||
assertEquals(attackerCiv, defaultAttackerUnit.getTile().civilianUnit!!.civ) // captured unit
|
||||
assertEquals("Worker", defaultAttackerUnit.getTile().civilianUnit!!.baseUnit.name)
|
||||
}
|
||||
@Test
|
||||
fun `should earn Great General from combat`() {
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(5, attackerCiv.greatPeople.greatGeneralPoints)
|
||||
assertEquals(4, defenderCiv.greatPeople.greatGeneralPoints)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not earn Great General from combat against barbarians`() {
|
||||
// given
|
||||
val barbarianCiv = testGame.addBarbarianCiv()
|
||||
val barbarianUnit = testGame.addUnit("Brute", barbarianCiv, testGame.getTile(Vector2.Y))
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(barbarianUnit))
|
||||
|
||||
// then
|
||||
assertEquals(0, attackerCiv.greatPeople.greatGeneralPoints)
|
||||
assertEquals(0, barbarianCiv.greatPeople.greatGeneralPoints)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should earn more Great General Points from uniques`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addDefaultMeleeUnitWithUniques(attackerCiv, testGame.getTile(Vector2.Y), "[Great General] is earned [100]% faster")
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(10, attackerCiv.greatPeople.greatGeneralPoints)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should conquer city when defeated and melee attacked`() {
|
||||
// given
|
||||
val defenderCity = testGame.addCity(defenderCiv, testGame.getTile(Vector2.Y), initialPopulation = 1)
|
||||
defenderCity.health = 1
|
||||
|
||||
testGame.gameInfo.currentPlayerCiv = testGame.addCiv() // otherwise test crashes when puppetying city
|
||||
testGame.gameInfo.currentPlayer = testGame.gameInfo.currentPlayerCiv.civName
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), CityCombatant(defenderCity))
|
||||
|
||||
// then
|
||||
assertEquals(attackerCiv, defenderCity.civ)
|
||||
assertEquals(defenderCiv.civName, defenderCity.previousOwner)
|
||||
assertEquals(defenderCiv.civName, defenderCity.foundingCiv)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not conquer city when defeated and ranged attacked`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addUnit("Archer", attackerCiv, testGame.getTile(Vector2(0f, 2f)))
|
||||
val defenderCity = testGame.addCity(defenderCiv, testGame.getTile(Vector2.Y), initialPopulation = 1)
|
||||
defenderCity.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), CityCombatant(defenderCity))
|
||||
|
||||
// then
|
||||
assertEquals(defenderCiv, defenderCity.civ)
|
||||
assertEquals(1, defenderCity.health)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not conquer city when unit has 'unable to capture cities' unique`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addDefaultMeleeUnitWithUniques(attackerCiv, testGame.getTile(Vector2(0f, 2f)), "Unable to capture cities")
|
||||
val defenderCity = testGame.addCity(defenderCiv, testGame.getTile(Vector2.Y), initialPopulation = 1)
|
||||
defenderCity.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), CityCombatant(defenderCity))
|
||||
|
||||
// then
|
||||
assertEquals(defenderCiv, defenderCity.civ)
|
||||
assertEquals(1, defenderCity.health)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not gain XP when attacking defeated city`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addUnit("Archer", attackerCiv, testGame.getTile(Vector2(0f, 2f)))
|
||||
val defenderCity = testGame.addCity(defenderCiv, testGame.getTile(Vector2.Y), initialPopulation = 1)
|
||||
defenderCity.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), CityCombatant(defenderCity))
|
||||
|
||||
// then
|
||||
assertEquals(0, attackerUnit.promotions.XP)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should earn prizes when defeating units`() {
|
||||
// given
|
||||
val attackerPolicy = testGame.createPolicy(
|
||||
"Earn [100]% of killed [Military] unit's [Strength] as [Culture]",
|
||||
"Earn [100]% of killed [Military] unit's [Strength] as [Gold]"
|
||||
)
|
||||
attackerCiv.policies.adopt(attackerPolicy, true)
|
||||
|
||||
defaultDefenderUnit.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(8, attackerCiv.gold)
|
||||
assertEquals(8, attackerCiv.policies.storedCulture)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should heal when defeating units if has unique`() {
|
||||
// given
|
||||
val attackerUnit = testGame.addDefaultRangedUnitWithUniques(attackerCiv, testGame.getTile(Vector2.Y), "Heals [10] damage if it kills a unit")
|
||||
attackerUnit.health = 90
|
||||
attackerUnit.currentMovement = 2f
|
||||
|
||||
defaultDefenderUnit.health = 1
|
||||
|
||||
// when
|
||||
Battle.attack(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit))
|
||||
|
||||
// then
|
||||
assertEquals(100, attackerUnit.health)
|
||||
}
|
||||
}
|
@ -340,14 +340,9 @@ class TargetHelperTest {
|
||||
@Test
|
||||
fun `should get no attackable tiles when has cannot attack unique`() {
|
||||
// given
|
||||
val attackerTile = testGame.setTileTerrain(Vector2.Zero, Constants.ocean)
|
||||
val defenderTile = testGame.setTileTerrain(Vector2(1f, 1f), Constants.ocean)
|
||||
|
||||
val attackerUnit = testGame.addUnit("Carrier", attackerCiv, attackerTile)
|
||||
val attackerUnit = testGame.addDefaultMeleeUnitWithUniques(attackerCiv, testGame.getTile(Vector2.Zero), "Cannot attack")
|
||||
attackerUnit.currentMovement = 2f
|
||||
testGame.addUnit("Destroyer", defenderCiv, defenderTile)
|
||||
|
||||
|
||||
testGame.addUnit("Warrior", defenderCiv, testGame.getTile(Vector2.X))
|
||||
|
||||
// when
|
||||
val attackableEnemies = TargetHelper.getAttackableEnemies(attackerUnit, attackerUnit.movement.getDistanceToTiles())
|
||||
|
@ -33,7 +33,7 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
public class GdxTestRunner extends BlockJUnit4ClassRunner implements ApplicationListener {
|
||||
|
||||
private final Map<FrameworkMethod, RunNotifier> invokeInRender = new HashMap<FrameworkMethod, RunNotifier>();
|
||||
private final Map<FrameworkMethod, RunNotifier> invokeInRender = new HashMap<>();
|
||||
|
||||
public GdxTestRunner(Class<?> klass) throws InitializationError {
|
||||
super(klass);
|
||||
|
@ -45,6 +45,7 @@ class TestGame {
|
||||
UncivGame.Current = UncivGame()
|
||||
// And the settings can be reached for the locale used in .tr()
|
||||
UncivGame.Current.settings = GameSettings()
|
||||
UncivGame.Current.gameInfo = gameInfo
|
||||
|
||||
// Create a new ruleset we can easily edit, and set the important variables of gameInfo
|
||||
RulesetCache.loadRulesets(noMods = true)
|
||||
@ -144,6 +145,16 @@ class TestGame {
|
||||
return civInfo
|
||||
}
|
||||
|
||||
fun addBarbarianCiv() : Civilization {
|
||||
val barbarianCivilization = Civilization(Constants.barbarians)
|
||||
val nation = Nation()
|
||||
nation.name = Constants.barbarians
|
||||
barbarianCivilization.nation = nation
|
||||
barbarianCivilization.gameInfo = gameInfo
|
||||
gameInfo.civilizations.add(barbarianCivilization)
|
||||
return barbarianCivilization
|
||||
}
|
||||
|
||||
fun addCity(
|
||||
civInfo: Civilization,
|
||||
tile: Tile,
|
||||
@ -202,6 +213,22 @@ class TestGame {
|
||||
return obj
|
||||
}
|
||||
|
||||
fun addDefaultMeleeUnitWithUniques(civInfo: Civilization, tile: Tile, vararg uniques: String) : MapUnit {
|
||||
val createBaseUnit = createBaseUnit("Sword", *uniques)
|
||||
createBaseUnit.movement = 2
|
||||
createBaseUnit.strength = 8
|
||||
return this.addUnit(createBaseUnit.name, civInfo, tile)
|
||||
}
|
||||
|
||||
fun addDefaultRangedUnitWithUniques(civInfo: Civilization, tile: Tile, vararg uniques: String) : MapUnit {
|
||||
val createBaseUnit = createBaseUnit("Archery", *uniques)
|
||||
createBaseUnit.movement = 2
|
||||
createBaseUnit.strength = 5
|
||||
createBaseUnit.rangedStrength = 7
|
||||
createBaseUnit.range = 2
|
||||
return this.addUnit(createBaseUnit.name, civInfo, tile)
|
||||
}
|
||||
|
||||
fun createBaseUnit(unitType: String = createUnitType().name, vararg uniques: String) =
|
||||
createRulesetObject(ruleset.units, *uniques) {
|
||||
val baseUnit = BaseUnit()
|
||||
|
Loading…
Reference in New Issue
Block a user