dimanche 27 novembre 2016

Tic-tac-toe script testing issue in python

I've lately begun my adventure with coding in Python and had to write a script reporting match result in tic tac toe depending on the state of the matrix. So I've done it and it seems to work just fine, here is the code(in tic_tac_toe.py file):

possibleChars = ['X', 'O']
matrixSize = 0
sets = []
finalWinner = []


def state(board):


count = 0
    for line in board:
        whoWins(possibleChars, line, getColumn(board, count))
        count += 1
    whoWins(possibleChars, diagonals = getDiagonals(board), diagFlag = True)


def getColumn(board, index):
    col = []
    for row in board:
        col.append(row[index])
    return col

def getDiagonals(board):
    diagonals = []
    diag1 = []
    diag2 =[]
    count = 0
    for row in board:
        diag1.append(row[count])
        diag2.append(row[matrixSize-1-count])
        count += 1
    diagonals.extend((diag1, diag2))
    return diagonals


def checkIfMatrix(board):
    l = len(board)
    if all(len(x) == l for x in board):
        global matrixSize
        matrixSize = l
        return True
    else:
        return False

def checkSets():
    for n in sets:
        if 'X' in n and 'X' not in finalWinner:
            finalWinner.append('X')
        elif 'O' in n and 'O' not in finalWinner:
            finalWinner.append('O')

def checkWinner():
    if not finalWinner:
        return '.'
    elif len(finalWinner) is 2:
        return 'DRAW'
    else:
        if 'X' in finalWinner:
            return 'X'
        elif 'O' in finalWinner:
            return 'O'

def whoWins(charList, line = [], col = [], diagonals = [], diagFlag = False):
    global sets
    if diagFlag is False:
        sets.append([char for char in charList if (line.count(char) == len(line) or col.count(char) == len(col))])
    else:
        for diag in diagonals:
            sets.append([char for char in charList if diag.count(char) == len(diag)])

def main(board = ['...','...','...']):
    if checkIfMatrix(board):
        getDiagonals(board)
        state(board)
        checkSets()
        return(checkWinner())
    else:
        return False


if __name__ == "__main__":
    main()

The main() function returns: 'X' if X won, 'O' if O won, 'DRAW' if there was a draw(I know it is a little bit stupid, because there is no such possibility in this game, but it was said to do so in the content of the task), '.' if there was no winner and False if given board dimensions were wrong for playing tic tac toe game. I've checked it manually by giving many different matrices as an argument and it works as it should. But, the problem occures when it comes to running some automatic tests I wrote for this script. Here is the content of tests.py file:

import unittest
import tic_tac_toe


class TicTacToeStateTest(unittest.TestCase):
    """Tests tic_tac_toe.main."""

    def assert_result(self, board, result):
        self.assertEqual(tic_tac_toe.main(board), result)

    def test_no_winner(self):
        """No winner."""

        board_a = [
            "XO.",
            ".OX",
            ".X.",
        ]
        board_b = [
            "O..",
            ".X.",
            "..O",
        ]
        self.assert_result(board_a, '.')
        self.assert_result(board_b, '.')

    def test_x_won(self):
        """X won."""

        board = [
            "X..",
            ".X.",
            "..X",
        ]
        self.assert_result(board, 'X')

    def test_o_won(self):
        """O won."""

        board = [
            "..O..",
            "..O..",
            "..O..",
            "..O..",
            "..O..",
        ]
        self.assert_result(board, 'O')


    def test_invalid_dimensions(self):
        """Board has invalid dimensions."""

        board = [
            "XXOO.",
            "...X.",
            "OOOO",
            "...",
            ".....",
        ]
        self.assert_result(board, False)

if __name__ == '__main__':
    unittest.main()

The issue is that, all tests pass without any problem aside from the one testing if X won. I don't know why but the case with X raises an AssertionError:

...F
======================================================================
FAIL: test_x_won (__main__.TicTacToeStateTest)
X won.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests.py", line 35, in test_x_won
    self.assert_result(board, 'X')
  File "tests.py", line 9, in assert_result
    self.assertEqual(tic_tac_toe.main(board), result)
AssertionError: 'DRAW' != 'X'

----------------------------------------------------------------------
Ran 4 tests in 0.000s

FAILED (failures=1)

But what is more interesting, with other tests commented, only the one for "X won" left, everything is working as it should without any exception raised.

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

So, here comes my question - what is the reason it's happening so? What am I doing wrong? I will be really grateful for any response.

Aucun commentaire:

Enregistrer un commentaire