vendredi 26 février 2016

How to automate unit testing of object state?

I have this serializable class which is my class for persisting game data.

[Serializable]
class GameData
{
    public float experience = Helper.DEFAULT_EXPERIENCE;
    public float score = Helper.DEFAULT_SCORE;
    public float winPercent = Helper.DEFAULT_WIN_PERCENT;
    public int tasksSolved = Helper.DEFAULT_NUM_OF_TASKS_SOLVED;
    public int correct = Helper.DEFAULT_NUM_OF_CORRECT;
    public int additions = Helper.DEFAULT_NUM_OF_ADDITIONS;
    public int subtractions = Helper.DEFAULT_NUM_OF_SUBTRACTIONS;
    public int multiplications = Helper.DEFAULT_NUM_OF_MULTIPLICATIONS;
    public int divisions = Helper.DEFAULT_NUM_OF_DIVISIONS;
    public int minRange = Helper.DEFAULT_MIN_RANGE;
    public int maxRange = Helper.DEFAULT_MAX_RANGE;
    public int longestChain = Helper.DEFAULT_LONGEST_CHAIN;
    public int overallTimeInSeconds = Helper.DEFAULT_OVERALL_TIME_IN_SECONDS;
    public int longestTaskInSeconds = Helper.DEFAULT_LONGEST_TASK_IN_SECONDS;
    public int difficulty = Helper.DEFAULT_DIFFICULTY;

    public bool useAddition = Helper.DEFAULT_USE_ADDITION;
    public bool useSubtraction = Helper.DEFAULT_USE_MULTIPLICATION;
    public bool useMultiplication = Helper.DEFAULT_USE_MULTIPLICATION;
    public bool useDivision = Helper.DEFAULT_USE_DIVISION;
    public bool useIncrementalRange = Helper.DEFAULT_USE_INCREMENTAL_RANGE;
    public bool gameStateDirty = Helper.DEFAULT_GAME_STATE_DIRTY;
    public bool gameIsNormal = Helper.DEFAULT_GAME_IS_NORMAL;
    public bool operandsSign = Helper.DEFAULT_OPERANDS_SIGN;
}

The class that utilizes this serializable class looks like this:

using UnityEngine;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public class SaveLoadGameData : MonoBehaviour
{
    public static SaveLoadGameData gameState;

    void Awake () {}

    public void init () {}

    public void SaveForWeb () {}

    public void SaveForX86 () {}

    public void Load () {}

    public void UpdateGameState () {}

    public void ResetGameState () {}
}

As you can see GameData class has ton of stuff and creating test for each function inside SaveLoadGameData class is long and boring process. I have to create a fake object for each property inside GameData and test the functionality of the functions in SaveLoadGameData do they do what they are supposed to do.

Note: This is Unity3D 5 code and testing MonoBehaviors with stubs and mocks is almost immposible. Therefore I created helper function that creates fake object:

SaveLoadGameData saveLoadObject;
GameObject gameStateObject;

SaveLoadGameData CreateFakeSaveLoadObject ()
{
    gameStateObject = new GameObject();
    saveLoadObject = gameStateObject.AddComponent<SaveLoadGameData>();
    saveLoadObject.init();

    saveLoadObject.experience = Arg.Is<float>(x => x > 0);
    saveLoadObject.score = Arg.Is<float>(x => x > 0);
    saveLoadObject.winPercent = 75;
    saveLoadObject.tasksSolved = 40;
    saveLoadObject.correct = 30;
    saveLoadObject.additions = 10;
    saveLoadObject.subtractions = 10;
    saveLoadObject.multiplications = 10;
    saveLoadObject.divisions = 10;
    saveLoadObject.minRange = 2;
    saveLoadObject.maxRange = 12;
    saveLoadObject.longestChain = Arg.Is<int>(x => x > 1);
    saveLoadObject.overallTimeInSeconds = Arg.Is<int>(x => x > 3);
    saveLoadObject.longestTaskInSeconds = Arg.Is<int>(x => x > 5);
    saveLoadObject.difficulty = Helper.HARD_DIFFICULTY;

    saveLoadObject.useAddition = false;
    saveLoadObject.useSubtraction = false;
    saveLoadObject.useMultiplication = false;
    saveLoadObject.useDivision = false;
    saveLoadObject.useIncrementalRange = true;
    saveLoadObject.gameStateDirty = true;
    saveLoadObject.gameIsNormal = false;
    saveLoadObject.operandsSign = true;

    return saveLoadObject;
}

How would you automate this process?

Yes two asserts inside one test is a bad practice but what would you do instead?

Aucun commentaire:

Enregistrer un commentaire