Skip to content

Commit

Permalink
Merge pull request #56 from Haraj-backend/chore/increase-coverage
Browse files Browse the repository at this point in the history
Chore: Increase Test Coverage
  • Loading branch information
riandyrn committed Jul 21, 2023
2 parents 067bc8c + 04cedb3 commit 709e794
Show file tree
Hide file tree
Showing 10 changed files with 427 additions and 160 deletions.
11 changes: 2 additions & 9 deletions internal/core/entity/battle.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package entity

import (
"errors"
"fmt"
"math/rand"
"time"

Expand All @@ -27,10 +26,7 @@ func (b *Battle) PartnerAttack() error {
return ErrInvalidState
}
// inflict damage to enemy
damage, err := b.Enemy.InflictDamage(*b.Partner)
if err != nil {
return fmt.Errorf("unable to inflict damage to enemy due: %w", err)
}
damage := b.Enemy.InflictDamage(*b.Partner)
// set enemy last damage
b.LastDamage.Enemy = damage
// set battle state accordingly
Expand Down Expand Up @@ -63,10 +59,7 @@ func (b *Battle) EnemyAttack() error {
return ErrInvalidState
}
// inflict damage to partner
damage, err := b.Partner.InflictDamage(*b.Enemy)
if err != nil {
return fmt.Errorf("unable to inflict damage to partner due: %w", err)
}
damage := b.Partner.InflictDamage(*b.Enemy)
// set partner last damage
b.LastDamage.Partner = damage
// set battle state accordingly
Expand Down
55 changes: 41 additions & 14 deletions internal/core/entity/battle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ package entity_test

import (
"fmt"
"math"
"testing"
"time"

"github.com/Haraj-backend/hex-monscape/internal/core/entity"
"github.com/Haraj-backend/hex-monscape/internal/core/testutil"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewBattle(t *testing.T) {
// define function for validating battle
validateBattle := func(t *testing.T, battle entity.Battle, cfg entity.BattleConfig) {
assert.NotEmpty(t, battle.GameID, "GameID is empty")
assert.NotEmpty(t, battle.Partner, "Partner is empty")
assert.NotEmpty(t, battle.Enemy, "Enemy is empty")
require.NotEmpty(t, battle.GameID, "GameID is empty")
require.NotEmpty(t, battle.Partner, "Partner is empty")
require.NotEmpty(t, battle.Enemy, "Enemy is empty")
}
// define test cases
testCases := []struct {
Expand All @@ -43,7 +44,7 @@ func TestNewBattle(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
battle, err := entity.NewBattle(testCase.Config)
assert.Equal(t, testCase.IsError, (err != nil), "unexpected error")
require.Equal(t, testCase.IsError, (err != nil), "unexpected error")
if battle == nil {
return
}
Expand Down Expand Up @@ -118,14 +119,27 @@ func TestPartnerAttack(t *testing.T) {

battle.State = testCase.State
err := battle.PartnerAttack()
assert.Equal(t, testCase.IsError, (err != nil), "unexpected error")
require.Equal(t, testCase.IsError, (err != nil), "unexpected error")
if !testCase.IsError {
assert.Equal(t, battle.Enemy.BattleStats.Health, testCase.ExpectedEnemyHealth, "enemy health is not valid")
require.Equal(t, battle.Enemy.BattleStats.Health, testCase.ExpectedEnemyHealth, "enemy health is not valid")
}
})
}
}

func TestPartnerAttackWin(t *testing.T) {
battle := initNewBattle()
// set partner attack to very high number so that enemy will be dead
battle.Partner.BattleStats.Attack = math.MaxInt
// set battle state to partner attack
battle.State = entity.StatePartnerTurn
// execute partner attack, enemy should be dead
err := battle.PartnerAttack()
require.NoError(t, err)
// validate battle state
require.Equal(t, entity.StateWin, battle.State)
}

func TestPartnerSurrender(t *testing.T) {
battle := initNewBattle()
// define test cases
Expand Down Expand Up @@ -155,9 +169,9 @@ func TestPartnerSurrender(t *testing.T) {
t.Run(testCase.Name, func(t *testing.T) {
battle.State = testCase.State
err := battle.PartnerSurrender()
assert.Equal(t, testCase.IsError, (err != nil), "unexpected error")
require.Equal(t, testCase.IsError, (err != nil), "unexpected error")
if !testCase.IsError {
assert.Equal(t, entity.StateLose, battle.State)
require.Equal(t, entity.StateLose, battle.State)
}
})
}
Expand Down Expand Up @@ -235,14 +249,27 @@ func TestEnemyAttack(t *testing.T) {
})
battle.State = testCase.State
err := battle.EnemyAttack()
assert.Equal(t, testCase.IsError, (err != nil), "unexpected error")
require.Equal(t, testCase.IsError, (err != nil), "unexpected error")
if !testCase.IsError {
assert.Equal(t, battle.Partner.BattleStats.Health, testCase.ExpectedPartnerHealth, "partner health is not valid")
require.Equal(t, battle.Partner.BattleStats.Health, testCase.ExpectedPartnerHealth, "partner health is not valid")
}
})
}
}

func TestEnemyAttackWin(t *testing.T) {
battle := initNewBattle()
// set enemy attack to very high number so that partner will be dead
battle.Enemy.BattleStats.Attack = math.MaxInt
// set battle state to enemy attack
battle.State = entity.StateEnemyTurn
// execute enemy attack, partner should be dead
err := battle.EnemyAttack()
require.NoError(t, err)
// validate battle state
require.Equal(t, entity.StateLose, battle.State)
}

func TestIsEnded(t *testing.T) {
battle := initNewBattle()
// define test cases
Expand Down Expand Up @@ -283,7 +310,7 @@ func TestIsEnded(t *testing.T) {
t.Run(testCase.Name, func(t *testing.T) {
battle.State = testCase.State
actual := battle.IsEnded()
assert.Equal(t, testCase.Expected, actual, "unexpected dead")
require.Equal(t, testCase.Expected, actual, "unexpected dead")
})
}
}
Expand Down Expand Up @@ -383,9 +410,9 @@ func TestDecideTurn(t *testing.T) {
})
battle.State = testCase.State
state, err := battle.DecideTurn()
assert.Equal(t, testCase.IsError, (err != nil), "unexpected error")
require.Equal(t, testCase.IsError, (err != nil), "unexpected error")
if !testCase.IsError {
assert.Equal(t, testCase.ExpectedState, state, "expected state is not valid")
require.Equal(t, testCase.ExpectedState, state, "expected state is not valid")
}
})
}
Expand Down
9 changes: 5 additions & 4 deletions internal/core/entity/monster.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package entity

const minDamage = 5
const MinDamage = 5

type Monster struct {
ID string
Expand All @@ -21,10 +21,11 @@ func (p Monster) IsDead() bool {

// InflictDamage is used for inflicting damage to self based
// on given enemy. Returned the damage amount.
func (p *Monster) InflictDamage(enemy Monster) (int, error) {
dmg := max(enemy.BattleStats.Attack-p.BattleStats.Defense, minDamage)
func (p *Monster) InflictDamage(enemy Monster) int {
dmg := max(enemy.BattleStats.Attack-p.BattleStats.Defense, MinDamage)
p.BattleStats.Health -= dmg
return dmg, nil

return dmg
}

type BattleStats struct {
Expand Down
95 changes: 73 additions & 22 deletions internal/core/entity/monster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package entity_test
import (
"fmt"
"testing"
"time"

"github.com/Haraj-backend/hex-monscape/internal/core/entity"
"github.com/Haraj-backend/hex-monscape/internal/core/testutil"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestIsDead(t *testing.T) {
Expand All @@ -21,47 +21,47 @@ func TestIsDead(t *testing.T) {
Name: "Monster is Not Dead",
Monster: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("monster_%v", time.Now().Unix()),
Name: generateMonsterName(false),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 100,
Defense: 100,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
Expected: false,
},
{
Name: "Monster Has 0 Health",
Monster: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("monster_%v", time.Now().Unix()),
Name: generateMonsterName(false),
BattleStats: entity.BattleStats{
Health: 0,
MaxHealth: 100,
Attack: 100,
Defense: 100,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
Expected: true,
},
{
Name: "Monster Has Negative Health",
Monster: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("monster_%v", time.Now().Unix()),
Name: generateMonsterName(false),
BattleStats: entity.BattleStats{
Health: -100,
MaxHealth: 100,
Attack: 100,
Defense: 100,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
Expected: true,
},
Expand All @@ -71,7 +71,7 @@ func TestIsDead(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
actual := testCase.Monster.IsDead()
assert.Equal(t, testCase.Expected, actual, "unexpected dead")
require.Equal(t, testCase.Expected, actual, "unexpected dead")
})
}
}
Expand All @@ -88,68 +88,119 @@ func TestInflictDamage(t *testing.T) {
Name: "Monster Get Zero Damage",
Monster: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("monster_%v", time.Now().Unix()),
Name: generateMonsterName(false),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 100,
Defense: 0,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
Enemy: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("enemy_%v", time.Now().Unix()),
Name: generateMonsterName(true),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 100,
Defense: 100,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
ExpectedHealthAmount: 0,
},
{
Name: "Monster Get 50 Damage",
Monster: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("monster_%v", time.Now().Unix()),
Name: generateMonsterName(false),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 100,
Defense: 50,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
Enemy: entity.Monster{
ID: uuid.NewString(),
Name: fmt.Sprintf("enemy_%v", time.Now().Unix()),
Name: generateMonsterName(true),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 100,
Defense: 100,
Speed: 100,
},
AvatarURL: fmt.Sprintf("https://example.com/%v", time.Now().Unix()),
AvatarURL: generateAvatarURL(),
},
ExpectedHealthAmount: 50,
},
{
Name: "Enemy Attack is Lower Than Monster Defense",
Monster: entity.Monster{
ID: uuid.NewString(),
Name: generateMonsterName(false),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 100,
Defense: 100,
Speed: 100,
},
AvatarURL: generateAvatarURL(),
},
Enemy: entity.Monster{
ID: uuid.NewString(),
Name: generateMonsterName(true),
BattleStats: entity.BattleStats{
Health: 100,
MaxHealth: 100,
Attack: 10,
Defense: 100,
Speed: 100,
},
AvatarURL: generateAvatarURL(),
},
ExpectedHealthAmount: 100 - entity.MinDamage,
},
}

// execute test cases
for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
_, err := testCase.Monster.InflictDamage(testCase.Enemy)
if err != nil {
t.Errorf("unable to inflict damage, due: %v", err)
}
assert.Equal(t, testCase.ExpectedHealthAmount, testCase.Monster.BattleStats.Health, "unexpected health amount")
testCase.Monster.InflictDamage(testCase.Enemy)
require.Equal(t, testCase.ExpectedHealthAmount, testCase.Monster.BattleStats.Health, "unexpected health amount")
})
}
}

func TestResetBattleStats(t *testing.T) {
// create new monster
m := testutil.NewTestMonster()

// set the monster health to 0
m.BattleStats.Health = 0

// reset the battle stats
m.ResetBattleStats()

// the monster health should be equal to max health
require.Equal(t, m.BattleStats.MaxHealth, m.BattleStats.Health, "unexpected health amount")
}

func generateMonsterName(isEnemy bool) string {
prefix := "monster"
if isEnemy {
prefix = "enemy"
}
return fmt.Sprintf("%v_%v", prefix, uuid.NewString())
}

func generateAvatarURL() string {
return fmt.Sprintf("https://example.com/%v.jpg", uuid.NewString())
}
Loading

0 comments on commit 709e794

Please sign in to comment.