vendredi 5 janvier 2018

Tests randomly fails

I'm writing board game and I need following functionality: player rolls two dices, if he rolled doubles (same number on both dice), he gets to roll again, if he rolled doubles again, he goes to jail.

In my Game class it looks like that

void logic::Game::rollTheDice() {
    m_throwsInCurrentTurn++; 
    int firstThrow = m_firstDice.roll();
    int secondThrow = m_secondDice.roll();
    m_totalRollResult += firstThrow + secondThrow;
    if (firstThrow == secondThrow) m_doublesInCurrentTurn++;
}

std::string logic::Game::checkForDoubles() {
    std::string message;
        if (m_doublesInCurrentTurn == 0 && m_throwsInCurrentTurn == 1) {
            m_canThrow = false;
            m_canMove = true;           
        }

        if (m_doublesInCurrentTurn == 1 && m_throwsInCurrentTurn == 1) {
            message = "Doubles! Roll again.";           
            m_canThrow = true;
            m_canMove = false;
        }

        if (m_doublesInCurrentTurn == 1 && m_throwsInCurrentTurn == 2) {            
            m_canThrow = false;
            m_canMove = true;
        }

        if (m_doublesInCurrentTurn == 2 && m_throwsInCurrentTurn == 2) {
            message = "Doubles again! You are going to jail.";
            m_canThrow = false;
            m_canMove = false;
            getActivePlayer().lockInJail();
        }
        return message;
    }

void logic::Game::setInMotion(unsigned number) {
    m_players[m_activePlayer].startMoving(); 
    m_players[m_activePlayer].incrementPosition(number);
}

m_canThrow basicly enables or disables ability to click "Roll the Dice" button, m_canMove decides if player token can start moving, m_players[m_activePlayer] is std::vector<Player>, startMoving() does that,

void logic::Player::startMoving() {
    m_isMoving = true;
} 

needed for token movement, so baiscly not relevant here.

Last function from Game class I need to show you is reset(), used mainly for testing purposes

void logic::Game::reset() {
    m_throwsInCurrentTurn = 0;
    m_doublesInCurrentTurn = 0;
    m_totalRollResult = 0;
}

Now finnaly Unit Test that sometimes goes wrong. Sometimes, I mean completely random, like 1 out of 10-20 times.

//first throw is double, second throw is not
TEST_F(GameTestSuite, shouldFinishAfterSecondRollAndMove) {
    auto game = m_sut.get();

    do {
        if (game.getThrowsInCurrentTurn() == 2) game.reset();
        game.rollTheDice();
        game.checkForDoubles();
        if (game.getThrowsInCurrentTurn() == 1 && game.getDoublesInCurrentTurn() == 1) {
            ASSERT_EQ(game.canThrow(), true);
            ASSERT_EQ(game.canMove(), false);           
        }
    } while (game.getThrowsInCurrentTurn() != 2 && game.getDoublesInCurrentTurn() != 1);

    ASSERT_EQ(game.canThrow(), false);
    ASSERT_EQ(game.canMove(), true);

    game.setInMotion(game.getTotalRollResult());

    ASSERT_EQ(game.getActivePlayer().isMoving(), true);
    ASSERT_EQ(game.getActivePlayer().getPosition(), game.getTotalRollResult());
}

This line exactly, ASSERT_EQ(game.canThrow(), false); sometimes is equal true after do-while loop that should end once m_canThrow is set to false

Aucun commentaire:

Enregistrer un commentaire