Merge pull request '⚙️ Tests pour Game.cs, Reflection, Mock et modif Game.cs' (#91) from tests into dev
continuous-integration/drone/push Build is passing Details

Reviewed-on: #91
Reviewed-by: Remi NEVEU <remi.neveu@etu.uca.fr>
pull/99/head
Lucas DUFLOT 11 months ago
commit cd83fe85ac

@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DataContractPersistence\DataContractPersistence.csproj" />
<ProjectReference Include="..\Models\Models.csproj" />
</ItemGroup>

@ -4,6 +4,8 @@ using Models;
using Models.Events;
using Models.Exceptions;
using Models.Game;
using Models.Interfaces;
using DataContractPersistence;
namespace ConsoleApp;
@ -19,10 +21,11 @@ class Program
string? pseudo = Console.ReadLine();
if (pseudo != null)
{
IPersistence persistence = new DataContractXml();
Player player = new Player(pseudo);
Map map = new Map("background");
Game game = new Game(player, map);
Game game = new Game(persistence);
// Abonnement aux événements
game.GameStarted += OnGameStarted!;
@ -33,7 +36,7 @@ class Program
game.CellChosen += OnCellChosen!;
// Initialisation
game.InitializeGame();
game.InitializeGame(map, player);
}
}

@ -14,12 +14,12 @@ namespace Models.Game
/// <summary>
/// Lowest number on the dice.
/// </summary>
public int NbMin { get; private set; }
public int MinVal { get; private set; }
/// <summary>
/// Highest number on the dice.
/// </summary>
public int NbMax { get; private set; }
public int MaxVal { get; private set; }
/// <summary>
/// Value of the dice.
@ -29,9 +29,9 @@ namespace Models.Game
get => _value;
private set
{
if (value < NbMin || value > NbMax)
if (value < MinVal || value > MaxVal)
{
value = NbMin;
value = MinVal;
}
_value = value;
}
@ -40,13 +40,13 @@ namespace Models.Game
/// <summary>
/// Initializes a new instance of the <see cref="Dice"/> class.
/// </summary>
/// <param name="nbmin">The lowest number on the dice, on which the highest number is set</param>
public Dice(int nbmin)
/// <param name="minval">The lowest number on the dice, on which the highest number is set</param>
public Dice(int minval)
{
if (nbmin < 0) nbmin = 0;
if (nbmin > 1) nbmin = 1;
NbMin = nbmin;
NbMax = nbmin + 5;
if (minval < 0) minval = 0;
if (minval > 1) minval = 1;
MinVal = minval;
MaxVal = minval + 5;
}
/// <summary>
@ -54,13 +54,13 @@ namespace Models.Game
/// </summary>
public Dice()
{
NbMin = 0;
NbMax = 5;
MinVal = 0;
MaxVal = 5;
}
public override string ToString()
{
return $"Ce dé a pour valeur {Value} et est entre {NbMin} et {NbMax}";
return $"Ce dé a pour valeur {Value} et est entre {MinVal} et {MaxVal}";
}
/// <summary>
@ -68,7 +68,7 @@ namespace Models.Game
/// </summary>
public void Roll()
{
Value = new Random().Next(NbMin, NbMax + 1);
Value = new Random().Next(MinVal, MaxVal + 1);
}
/// <summary>

@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -27,14 +28,20 @@ namespace Models.Game
public List<BestScore> BestScores { get; set; }
private bool _isRunning;
public bool IsRunning
{
get => _isRunning;
private set => _isRunning = value;
}
public Player CurrentPlayer { get; private set; }
public Map UsedMap { get; private set; }
private Dice Dice1 { get; }
private Dice Dice2 { get; }
public Dice Dice1 { get; private set; }
public Dice Dice2 { get; private set; }
private int Turn { get; set; }
public int Turn { get; private set; }
public Rules.Rules GameRules { get; }
@ -98,25 +105,10 @@ namespace Models.Game
Games = new List<Game>();
Maps = new List<Map>();
BestScores = new List<BestScore>();
_isRunning = false;
}
/// <summary>
/// Initializes a new instance of the <see cref="Game"/> class.
/// </summary>
/// <param name="player">The player who play the game.</param>
/// <param name="map">The map to be used in the game.</param>
public Game(Player player, Map map)
{
_isRunning = false;
UsedMap = map;
CurrentPlayer = player;
Dice1 = new Dice();
Dice2 = new Dice(1);
Turn = 1;
GameRules = new Rules.Rules();
IsRunning = false;
}
/// <summary>
@ -240,13 +232,30 @@ namespace Models.Game
}
}
}
/// <summary>
/// Initializes the game.
/// </summary>
public void InitializeGame()
public void InitializeGame(Map map, Player player, bool startImmediately = true)
{
UsedMap = map;
CurrentPlayer = player;
Turn = 1;
Dice1 = new Dice();
Dice2 = new Dice(1);
if (startImmediately)
{
StartGame();
}
}
/// <summary>
/// Starts the game.
/// </summary>
private void StartGame()
{
_isRunning = true;
IsRunning = true;
GameStarted?.Invoke(this, new GameStartedEventArgs(CurrentPlayer));
GameLoop();
}
@ -256,7 +265,7 @@ namespace Models.Game
/// </summary>
private void EndGame(int? pts)
{
_isRunning = false;
IsRunning = false;
GameEnded?.Invoke(this, new GameEndedEventArgs(CurrentPlayer, pts));
}
@ -265,7 +274,7 @@ namespace Models.Game
/// </summary>
private void GameLoop()
{
while (_isRunning)
while (IsRunning)
{
if (Turn == 20)
{

@ -209,6 +209,8 @@ namespace Models.Rules
public List<Cell> EveryAdjacentCells(Cell choosenCell, List<Cell> cells)
{
List<Cell> adjacentCells = new List<Cell>();
if (choosenCell == null || cells == null) return adjacentCells;
foreach (var cell in cells)
{
@ -230,7 +232,7 @@ namespace Models.Rules
calculus += zones[i].Count - 1 + zones[i][0].Value;
if (zones[i].Count > 9)
{
calculus += (zones[i].Count - 9) * 5;
calculus += (zones[i].Count - 9) * 5 - (zones[i].Count - 9);
}
}
return calculus;

@ -13,30 +13,30 @@ public class DiceTests
public void Constructor_WithNegativeNbMin_SetsNbMinToZero()
{
Dice dice = new Dice(-1);
Assert.Equal(0, dice.NbMin);
Assert.Equal(0, dice.MinVal);
}
[Fact]
public void Constructor_WithNbMinGreaterThanOne_SetsNbMinToOne()
{
Dice dice = new Dice(2);
Assert.Equal(1, dice.NbMin);
Assert.Equal(1, dice.MinVal);
}
[Fact]
public void Constructor_WithValidNbMin_SetsNbMinAndNbMaxCorrectly()
{
Dice dice = new Dice(1);
Assert.Equal(1, dice.NbMin);
Assert.Equal(6, dice.NbMax);
Assert.Equal(1, dice.MinVal);
Assert.Equal(6, dice.MaxVal);
}
[Fact]
public void DefaultConstructor_SetsNbMinToZeroAndNbMaxToFive()
{
Dice dice = new Dice();
Assert.Equal(0, dice.NbMin);
Assert.Equal(5, dice.NbMax);
Assert.Equal(0, dice.MinVal);
Assert.Equal(5, dice.MaxVal);
}
[Fact]
@ -44,6 +44,6 @@ public class DiceTests
{
Dice dice = new Dice();
dice.Roll();
Assert.True(dice.Value >= dice.NbMin && dice.Value <= dice.NbMax);
Assert.True(dice.Value >= dice.MinVal && dice.Value <= dice.MaxVal);
}
}

@ -0,0 +1,246 @@
using Moq;
using Models.Game;
using Models.Interfaces;
using System.Reflection;
using static System.Type;
namespace Tests;
public class GameTests
{
private readonly Mock<IPersistence> _mockPersistence; // Mocking (faking) the persistence layer to allow for testing without a persistent connection
private readonly Game _game;
public GameTests()
{
_mockPersistence = new Mock<IPersistence>();
_game = new Game(_mockPersistence.Object);
}
private void SetDiceValues(Game game, int value1, int value2)
{
var dice1Field = typeof(Game).GetProperty("Dice1", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
var dice2Field = typeof(Game).GetProperty("Dice2", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (dice1Field != null && dice2Field != null)
{
var dice1 = (Dice)dice1Field?.GetValue(game)!;
var dice2 = (Dice)dice2Field?.GetValue(game)!;
var valueField = typeof(Dice).GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic);
valueField?.SetValue(dice1, value1);
valueField?.SetValue(dice2, value2);
}
}
[Fact]
public void AddPlayer_ShouldAddPlayerToList()
{
var player = new Player();
_game.AddPlayer(player);
Assert.Contains(player, _game.Players);
}
[Fact]
public void AddGame_ShouldAddGameToList()
{
var game = new Game(_mockPersistence.Object);
_game.AddGame(game);
Assert.Contains(game, _game.Games);
}
[Fact]
public void AddMap_ShouldAddMapToList()
{
var map = new Map("test_background.png");
_game.AddMap(map);
Assert.Contains(map, _game.Maps);
}
[Fact]
public void AddBestScore_ShouldAddBestScoreToList()
{
var bestScore = new BestScore(3, 125);
_game.AddBestScore(bestScore);
Assert.Contains(bestScore, _game.BestScores);
}
[Fact]
public void LoadData_ShouldLoadDataFromPersistence()
{
var players = new List<Player> { new Player() };
var games = new List<Game> { new Game(_mockPersistence.Object) };
var maps = new List<Map> { new Map("test_background") };
var bestScores = new List<BestScore> { new BestScore(1, 26) };
_mockPersistence.Setup(p => p.LoadData()).Returns((players, games, maps, bestScores));
_game.LoadData();
Assert.Equal(players, _game.Players);
Assert.Equal(games, _game.Games);
Assert.Equal(maps, _game.Maps);
Assert.Equal(bestScores, _game.BestScores);
}
[Fact]
public void SaveData_ShouldCallPersistenceSaveData()
{
_game.SaveData();
_mockPersistence.Verify(p => p.SaveData(_game.Players, _game.Games, _game.Maps, _game.BestScores), Times.Once); // Times.Once is to verify if the method is called exactly one time
}
[Fact]
public void InitializeGame_ShouldInitializeGameAndNotTriggerEventWhenNotStarted()
{
var player = new Player();
var map = new Map("test_background");
bool eventTriggered = false;
_game.GameStarted += (sender, args) =>
{
eventTriggered = true;
};
_game.InitializeGame(map, player, false);
Assert.False(eventTriggered);
Assert.False(_game.IsRunning);
Assert.Equal(map, _game.UsedMap);
Assert.Equal(player, _game.CurrentPlayer);
}
[Fact]
public void InitializeGame_ShouldInitializeGameAndTriggerEventWhenStarted()
{
var player = new Player();
var map = new Map("test_background");
bool eventTriggered = false;
_game.GameEnded += (sender, args) =>
{
eventTriggered = true;
};
_game.InitializeGame(map, player, true);
Assert.True(eventTriggered);
Assert.False(_game.IsRunning);
Assert.Equal(map, _game.UsedMap);
Assert.Equal(player, _game.CurrentPlayer);
}
[Theory]
[InlineData(Operation.ADDITION, 3, 4, 7)]
[InlineData(Operation.SUBTRACTION, 6, 4, 2)]
[InlineData(Operation.MULTIPLICATION, 2, 3, 6)]
[InlineData(Operation.LOWER, 1, 4, 1)]
[InlineData(Operation.HIGHER, 2, 5, 5)]
public void HandlePlayerOperation_ShouldPerformCorrectOperationAndTriggerEvent(Operation operation, int value1, int value2, int expectedResult)
{
var player = new Player();
var map = new Map("background");
_game.InitializeGame(map, player, false);
bool eventTriggered = false;
int actualResult = 0;
_game.OperationChosen += (sender, args) =>
{
eventTriggered = true;
actualResult = args.Result;
};
SetDiceValues(_game, value1, value2);
_game.HandlePlayerOperation(operation);
Assert.True(eventTriggered);
Assert.Equal(expectedResult, actualResult);
}
[Fact]
public void Game_Initialization_SetsMap()
{
var player = new Player("test_player");
var map = new Map("background");
_game.InitializeGame(map, player);
Assert.Equal(map, _game.UsedMap);
}
[Fact]
public void Game_Initialization_SetsPlayer()
{
var player = new Player("test_player");
var map = new Map("background");
_game.InitializeGame(map, player);
Assert.Equal(player, _game.CurrentPlayer);
}
[Fact]
public void Game_Initialization_SetsDice()
{
Player player = new Player();
Map map = new Map("test_background");
_game.InitializeGame(map, player);
Assert.NotNull(_game.Dice1);
Assert.NotNull(_game.Dice2);
}
[Fact]
public void Game_Initialization_SetsGameRules()
{
var game = new Game(_mockPersistence.Object);
Assert.NotNull(game.GameRules);
}
[Fact]
public void MarkOperationAsChecked_Check_Well()
{
var player = new Player();
var map = new Map("test_background");
_game.InitializeGame(map, player);
// Use of reflection to call private method
var methodInfo = typeof(Game).GetMethod("MarkOperationAsChecked", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo);
var operation = Operation.ADDITION;
methodInfo.Invoke(_game, new object[] { operation });
int operationIndex = (int)operation;
int operationsPerType = 4;
bool isChecked = false;
for (int i = operationIndex * operationsPerType; i < (operationIndex + 1) * operationsPerType; i++)
{
if (_game.UsedMap.OperationGrid[i].IsChecked)
{
isChecked = true;
break;
}
}
Assert.True(isChecked);
}
}

@ -232,4 +232,294 @@ public class RulesTests
rules.IsZoneValidAndAddToZones(cell, map);
Assert.Contains(cell, map.Zones[0]);
}
[Fact]
public void IsValueInZones_ReturnsFalse_WhenCellIsNull()
{
Rules rules = new Rules();
Assert.False(rules.IsValueInZones(null, new List<List<Cell>>()));
}
[Fact]
public void IsValueInZones_ReturnsFalse_WhenZonesAreEmpty()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 1;
Assert.False(rules.IsValueInZones(cell, new List<List<Cell>>()));
}
[Fact]
public void IsValueInZones_ReturnsFalse_WhenNoZoneContainsCellWithSameValue()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 1;
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { new Cell(0, 1) { Value = 2 } },
new List<Cell> { new Cell(1, 0) { Value = 3 } }
};
Assert.False(rules.IsValueInZones(cell, zones));
}
[Fact]
public void IsValueInZones_ReturnsTrue_WhenZoneContainsCellWithSameValue()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 1;
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { new Cell(0, 1) { Value = 1 } },
new List<Cell> { new Cell(1, 0) { Value = 3 } }
};
Assert.True(rules.IsValueInZones(cell, zones));
}
[Fact]
public void IsCellInZone_ReturnsFalse_WhenCellIsNull()
{
Rules rules = new Rules();
Assert.False(rules.IsCellInZone(null, new List<List<Cell>>()));
}
[Fact]
public void IsCellInZone_ReturnsFalse_WhenZonesAreEmpty()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
Assert.False(rules.IsCellInZone(cell, new List<List<Cell>>()));
}
[Fact]
public void IsCellInZone_ReturnsFalse_WhenNoZoneContainsCell()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { new Cell(0, 1) },
new List<Cell> { new Cell(1, 0) }
};
Assert.False(rules.IsCellInZone(cell, zones));
}
[Fact]
public void IsCellInZone_ReturnsTrue_WhenZoneContainsCell()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { new Cell(0, 1) },
new List<Cell> { cell }
};
Assert.True(rules.IsCellInZone(cell, zones));
}
[Fact]
public void AddToZone_DoesNothing_WhenCellIsNull()
{
Rules rules = new Rules();
List<List<Cell>> zones = new List<List<Cell>>();
rules.AddToZone(null, zones);
Assert.Empty(zones);
}
[Fact]
public void AddToZone_DoesNothing_WhenCellValueIsNull()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
List<List<Cell>> zones = new List<List<Cell>>();
rules.AddToZone(cell, zones);
Assert.Empty(zones);
}
[Fact]
public void AddToZone_DoesNothing_WhenCellIsAlreadyInZone()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 1;
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { cell }
};
rules.AddToZone(cell, zones);
Assert.Single(zones[0]); // Verify if the List has still only one element
}
[Fact]
public void AddToZone_AddsCellToExistingZone_WhenCellHasSameValueAsZone()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 1;
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { new Cell(0, 1) { Value = 1 } }
};
rules.AddToZone(cell, zones);
Assert.Contains(cell, zones[0]);
}
[Fact]
public void NewZoneIsCreated_DoesNothing_WhenFirstCellIsNull()
{
Rules rules = new Rules();
Map map = new Map("background");
rules.NewZoneIsCreated(null, new Cell(0, 0), map);
Assert.Empty(map.Zones);
}
[Fact]
public void NewZoneIsCreated_DoesNothing_WhenSecondCellIsNull()
{
Rules rules = new Rules();
Map map = new Map("background");
rules.NewZoneIsCreated(new Cell(0, 0), null, map);
Assert.Empty(map.Zones);
}
[Fact]
public void NewZoneIsCreated_DoesNothing_WhenFirstCellValueIsNull()
{
Rules rules = new Rules();
Map map = new Map("background");
Cell firstCell = new Cell(0, 0);
rules.NewZoneIsCreated(firstCell, new Cell(0, 1), map);
Assert.Empty(map.Zones);
}
[Fact]
public void NewZoneIsCreated_DoesNothing_WhenSecondCellValueIsNull()
{
Rules rules = new Rules();
Map map = new Map("background");
Cell secondCell = new Cell(0, 0);
rules.NewZoneIsCreated(new Cell(0, 1), secondCell, map);
Assert.Empty(map.Zones);
}
[Fact]
public void NewZoneIsCreated_CreatesNewZone_WhenBothCellsAreNotNullAndHaveValues()
{
Rules rules = new Rules();
Map map = new Map("background");
Cell firstCell = new Cell(0, 0);
firstCell.Value = 1;
Cell secondCell = new Cell(0, 1);
secondCell.Value = 1;
rules.NewZoneIsCreated(firstCell, secondCell, map);
Assert.Single(map.Zones);
Assert.Contains(firstCell, map.Zones[0]);
Assert.Contains(secondCell, map.Zones[0]);
}
[Fact]
public void EveryAdjacentCells_ReturnsEmptyList_WhenCellIsNull()
{
Rules rules = new Rules();
List<Cell> cells = new List<Cell> { new Cell(0, 0), new Cell(0, 1) };
Assert.Empty(rules.EveryAdjacentCells(null, cells));
}
[Fact]
public void EveryAdjacentCells_ReturnsEmptyList_WhenCellsAreEmpty()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
Assert.Empty(rules.EveryAdjacentCells(cell, new List<Cell>()));
}
[Fact]
public void EveryAdjacentCells_ReturnsEmptyList_WhenNoAdjacentCells()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
List<Cell> cells = new List<Cell> { new Cell(2, 2), new Cell(3, 3) };
Assert.Empty(rules.EveryAdjacentCells(cell, cells));
}
[Fact]
public void EveryAdjacentCells_ReturnsListWithAdjacentCells_WhenAdjacentCellsExist()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
List<Cell> cells = new List<Cell> { new Cell(0, 1), new Cell(1, 0), new Cell(2, 2) };
List<Cell> result = rules.EveryAdjacentCells(cell, cells);
Assert.Equal(2, result.Count);
Assert.Contains(new Cell(0, 1), result);
Assert.Contains(new Cell(1, 0), result);
}
[Fact]
public void FinalCalculusOfZones_ReturnsZero_WhenZonesAreEmpty()
{
Rules rules = new Rules();
Assert.Equal(0, rules.FinalCalculusOfZones(new List<List<Cell>>()));
}
[Fact]
public void FinalCalculusOfZones_ReturnsCorrectValue_WhenZonesAreNotEmpty()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 1;
Cell cell1 = new Cell(0, 1);
cell1.Value = 1;
Cell cell2 = new Cell(0, 2);
cell2.Value = 1;
Cell uncell = new Cell(0, 0);
uncell.Value = 4;
Cell deuxcell = new Cell(0, 1);
deuxcell.Value = 4;
Cell troiscell = new Cell(0, 2);
troiscell.Value = 4;
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { cell, cell1, cell2 },
new List<Cell> { uncell, deuxcell, troiscell }
};
Assert.Equal(9, rules.FinalCalculusOfZones(zones));
}
[Fact]
public void FinalCalculusOfZones_ReturnsCorrectValue_WhenZoneCountIsGreaterThanNine()
{
Rules rules = new Rules();
Cell cell = new Cell(0, 0);
cell.Value = 5;
Cell cell1 = new Cell(0, 1);
cell1.Value = 5;
Cell cell2 = new Cell(0, 2);
cell2.Value = 5;
Cell cell3 = new Cell(0, 3);
cell3.Value = 5;
Cell cell4 = new Cell(0, 4);
cell4.Value = 5;
Cell cell5 = new Cell(0, 5);
cell5.Value = 5;
Cell cell6 = new Cell(1, 0);
cell6.Value = 5;
Cell cell7 = new Cell(1, 1);
cell7.Value = 5;
Cell cell8 = new Cell(1, 2);
cell8.Value = 5;
Cell cell9 = new Cell(1, 3);
cell9.Value = 5;
Cell cell10 = new Cell(1, 4);
cell10.Value = 5;
List<List<Cell>> zones = new List<List<Cell>>
{
new List<Cell> { cell, cell1, cell2, cell3, cell4, cell5, cell6, cell7, cell8, cell9, cell10 }
};
Assert.Equal(23, rules.FinalCalculusOfZones(zones));
}
}

@ -10,8 +10,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>

Loading…
Cancel
Save