Source code for tests.test_spritesheetlib

# -*- coding: utf-8 -*-
#
# New BSD license
#
# Copyright (c) DR0ID
# This file is part of spritesheetlib
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL DR0ID BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
TODO: module description


Versioning scheme based on: http://en.wikipedia.org/wiki/Versioning#Designating_development_stage

::

      +-- api change, probably incompatible with older versions
      |     +-- enhancements but no api change
      |     |
    major.minor[.build[.revision]]
                   |        |
                   |        +-|* x for x bugfixes
                   |
                   +-|* 0 for alpha (status)
                     |* 1 for beta (status)
                     |* 2 for release candidate
                     |* 3 for (public) release

.. versionchanged:: 0.0.0.0
    initial version

"""
import random
import unittest
import logging
import warnings
warnings.simplefilter('default')  # make warnings visible for developers

import spritesheetlib as mut  # module under test
import tests.datadriventestingdecorators as ddtd
from spritesheetlib import SpritesheetLib10
from spritesheetlib import FileInfo

__version__ = '1.0.3.0'

# for easy comparison as in sys.version_info but digits only
__version_info__ = tuple([int(d) for d in __version__.split('.')])

__author__ = "DR0ID"
__email__ = "dr0iddr0id [at] gmail [dot] com"
__copyright__ = "DR0ID @ 2014"
__credits__ = ["DR0ID"]  # list of contributors
__maintainer__ = "DR0ID"
__license__ = "New BSD license"


V1ELEMENTS = SpritesheetLib10.ELEMENTS
V1PROPERTIES = SpritesheetLib10.PROPERTIES

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.level = logging.DEBUG


[docs]class TestVersions(unittest.TestCase): """ This class test the version of this test module to be equal to the version of the module that is tested. """
[docs] def test_version_should_be_equal_to_mut_version(self): """ Tests if the module versions are equal. """ # arrange / act / verify self.assertTrue(mut.__version_info__ == __version_info__, "version of module under test should match version of this tests !")
[docs]class TestData(object): """ Contains all sprite definitions used for testing (valid and invalid ones). """ SDEF_GRID_2X2 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "out.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: 0, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 0, V1PROPERTIES.ROW: 0}, V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 32], [0, 32]], V1ELEMENTS.ANCHOR: [10, 10]}, {V1ELEMENTS.GID: 1, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 1, V1PROPERTIES.ROW: 0}, V1ELEMENTS.POINTS: [[32, 0], [64, 0], [64, 32], [32, 32]], }, {V1ELEMENTS.GID: 2, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 0, V1PROPERTIES.ROW: 1}, V1ELEMENTS.POINTS: [[0, 32], [32, 32], [32, 64], [0, 64]], }, {V1ELEMENTS.GID: 3, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 1, V1PROPERTIES.ROW: 1}, V1ELEMENTS.POINTS: [[32, 32], [64, 32], [64, 64], [32, 64]], }, ]} SDEF_GRID_2X2_TEST = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "test.sdef.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 32], [0, 32]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 0], [64, 0], [64, 32], [32, 32]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[0, 32], [32, 32], [32, 64], [0, 64]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[32, 32], [64, 32], [64, 64], [32, 64]], }, ]} SDEF_GRID_2X2_MARGIN_33 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "out.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: 0, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 0, V1PROPERTIES.ROW: 0}, V1ELEMENTS.ANCHOR: [10, 10], V1ELEMENTS.POINTS: [[0 + 33, 0 + 33], [32 + 33, 0 + 33], [32 + 33, 32 + 33], [0 + 33, 32 + 33]], }, {V1ELEMENTS.GID: 1, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 1, V1PROPERTIES.ROW: 0}, V1ELEMENTS.POINTS: [[32 + 33, 0 + 33], [64 + 33, 0 + 33], [64 + 33, 32 + 33], [32 + 33, 32 + 33]], }, {V1ELEMENTS.GID: 2, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 0, V1PROPERTIES.ROW: 1}, V1ELEMENTS.POINTS: [[0 + 33, 32 + 33], [32 + 33, 32 + 33], [32 + 33, 64 + 33], [0 + 33, 64 + 33]], }, {V1ELEMENTS.GID: 3, V1ELEMENTS.PROPERTIES: {V1PROPERTIES.COLUMN: 1, V1PROPERTIES.ROW: 1}, V1ELEMENTS.POINTS: [[32 + 33, 32 + 33], [64 + 33, 32 + 33], [64 + 33, 64 + 33], [32 + 33, 64 + 33]], }, ]} SDEF_GRID_2X2_SPECIAL_MARGIN = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "out.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 32], [0, 32]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 0 - 13], [64, 0 - 13], [64, 32], [32, 32]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[0 - 17, 32], [32, 32], [32, 64], [0 - 17, 64]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[32, 32], [64, 32], [64, 64], [32, 64]], }, ]} SDEF_GRID_2X2_SPECIAL_MARGIN_5 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "out.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0 + 22, 0 + 18], [32 + 22, 0 + 18], [32 + 22, 32 + 18], [0 + 22, 32 + 18]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32 + 22, 0 - 13 + 18], [64 + 22, 0 - 13 + 18], [64 + 22, 32 + 18], [32 + 22, 32 + 18]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[0 - 17 + 22, 32 + 18], [32 + 22, 32 + 18], [32 + 22, 64 + 18], [0 - 17 + 22, 64 + 18]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[32 + 22, 32 + 18], [64 + 22, 32 + 18], [64 + 22, 64 + 18], [32 + 22, 64 + 18]], }, ]} SDEF_GRID_10X10 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "out.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0 * 32, 0 * 32], [32 + 0 * 32, 0 * 32], [32 + 0 * 32, 32 + 0 * 32], [0 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[1 * 32, 0 * 32], [32 + 1 * 32, 0 * 32], [32 + 1 * 32, 32 + 0 * 32], [1 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[2 * 32, 0 * 32], [32 + 2 * 32, 0 * 32], [32 + 2 * 32, 32 + 0 * 32], [2 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[3 * 32, 0 * 32], [32 + 3 * 32, 0 * 32], [32 + 3 * 32, 32 + 0 * 32], [3 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "004", V1ELEMENTS.POINTS: [[4 * 32, 0 * 32], [32 + 4 * 32, 0 * 32], [32 + 4 * 32, 32 + 0 * 32], [4 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "005", V1ELEMENTS.POINTS: [[5 * 32, 0 * 32], [32 + 5 * 32, 0 * 32], [32 + 5 * 32, 32 + 0 * 32], [5 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "006", V1ELEMENTS.POINTS: [[6 * 32, 0 * 32], [32 + 6 * 32, 0 * 32], [32 + 6 * 32, 32 + 0 * 32], [6 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "007", V1ELEMENTS.POINTS: [[7 * 32, 0 * 32], [32 + 7 * 32, 0 * 32], [32 + 7 * 32, 32 + 0 * 32], [7 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "008", V1ELEMENTS.POINTS: [[8 * 32, 0 * 32], [32 + 8 * 32, 0 * 32], [32 + 8 * 32, 32 + 0 * 32], [8 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "009", V1ELEMENTS.POINTS: [[9 * 32, 0 * 32], [32 + 9 * 32, 0 * 32], [32 + 9 * 32, 32 + 0 * 32], [9 * 32, 32 + 0 * 32]], }, {V1ELEMENTS.GID: "010", V1ELEMENTS.POINTS: [[0 * 32, 1 * 32], [32 + 0 * 32, 1 * 32], [32 + 0 * 32, 32 + 1 * 32], [0 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "011", V1ELEMENTS.POINTS: [[1 * 32, 1 * 32], [32 + 1 * 32, 1 * 32], [32 + 1 * 32, 32 + 1 * 32], [1 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "012", V1ELEMENTS.POINTS: [[2 * 32, 1 * 32], [32 + 2 * 32, 1 * 32], [32 + 2 * 32, 32 + 1 * 32], [2 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "013", V1ELEMENTS.POINTS: [[3 * 32, 1 * 32], [32 + 3 * 32, 1 * 32], [32 + 3 * 32, 32 + 1 * 32], [3 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "014", V1ELEMENTS.POINTS: [[4 * 32, 1 * 32], [32 + 4 * 32, 1 * 32], [32 + 4 * 32, 32 + 1 * 32], [4 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "015", V1ELEMENTS.POINTS: [[5 * 32, 1 * 32], [32 + 5 * 32, 1 * 32], [32 + 5 * 32, 32 + 1 * 32], [5 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "016", V1ELEMENTS.POINTS: [[6 * 32, 1 * 32], [32 + 6 * 32, 1 * 32], [32 + 6 * 32, 32 + 1 * 32], [6 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "017", V1ELEMENTS.POINTS: [[7 * 32, 1 * 32], [32 + 7 * 32, 1 * 32], [32 + 7 * 32, 32 + 1 * 32], [7 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "018", V1ELEMENTS.POINTS: [[8 * 32, 1 * 32], [32 + 8 * 32, 1 * 32], [32 + 8 * 32, 32 + 1 * 32], [8 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "019", V1ELEMENTS.POINTS: [[9 * 32, 1 * 32], [32 + 9 * 32, 1 * 32], [32 + 9 * 32, 32 + 1 * 32], [9 * 32, 32 + 1 * 32]], }, {V1ELEMENTS.GID: "020", V1ELEMENTS.POINTS: [[0 * 32, 2 * 32], [32 + 0 * 32, 2 * 32], [32 + 0 * 32, 32 + 2 * 32], [0 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "021", V1ELEMENTS.POINTS: [[1 * 32, 2 * 32], [32 + 1 * 32, 2 * 32], [32 + 1 * 32, 32 + 2 * 32], [1 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "022", V1ELEMENTS.POINTS: [[2 * 32, 2 * 32], [32 + 2 * 32, 2 * 32], [32 + 2 * 32, 32 + 2 * 32], [2 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "023", V1ELEMENTS.POINTS: [[3 * 32, 2 * 32], [32 + 3 * 32, 2 * 32], [32 + 3 * 32, 32 + 2 * 32], [3 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "024", V1ELEMENTS.POINTS: [[4 * 32, 2 * 32], [32 + 4 * 32, 2 * 32], [32 + 4 * 32, 32 + 2 * 32], [4 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "025", V1ELEMENTS.POINTS: [[5 * 32, 2 * 32], [32 + 5 * 32, 2 * 32], [32 + 5 * 32, 32 + 2 * 32], [5 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "026", V1ELEMENTS.POINTS: [[6 * 32, 2 * 32], [32 + 6 * 32, 2 * 32], [32 + 6 * 32, 32 + 2 * 32], [6 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "027", V1ELEMENTS.POINTS: [[7 * 32, 2 * 32], [32 + 7 * 32, 2 * 32], [32 + 7 * 32, 32 + 2 * 32], [7 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "028", V1ELEMENTS.POINTS: [[8 * 32, 2 * 32], [32 + 8 * 32, 2 * 32], [32 + 8 * 32, 32 + 2 * 32], [8 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "029", V1ELEMENTS.POINTS: [[9 * 32, 2 * 32], [32 + 9 * 32, 2 * 32], [32 + 9 * 32, 32 + 2 * 32], [9 * 32, 32 + 2 * 32]], }, {V1ELEMENTS.GID: "030", V1ELEMENTS.POINTS: [[0 * 32, 3 * 32], [32 + 0 * 32, 3 * 32], [32 + 0 * 32, 32 + 3 * 32], [0 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "031", V1ELEMENTS.POINTS: [[1 * 32, 3 * 32], [32 + 1 * 32, 3 * 32], [32 + 1 * 32, 32 + 3 * 32], [1 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "032", V1ELEMENTS.POINTS: [[2 * 32, 3 * 32], [32 + 2 * 32, 3 * 32], [32 + 2 * 32, 32 + 3 * 32], [2 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "033", V1ELEMENTS.POINTS: [[3 * 32, 3 * 32], [32 + 3 * 32, 3 * 32], [32 + 3 * 32, 32 + 3 * 32], [3 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "034", V1ELEMENTS.POINTS: [[4 * 32, 3 * 32], [32 + 4 * 32, 3 * 32], [32 + 4 * 32, 32 + 3 * 32], [4 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "035", V1ELEMENTS.POINTS: [[5 * 32, 3 * 32], [32 + 5 * 32, 3 * 32], [32 + 5 * 32, 32 + 3 * 32], [5 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "036", V1ELEMENTS.POINTS: [[6 * 32, 3 * 32], [32 + 6 * 32, 3 * 32], [32 + 6 * 32, 32 + 3 * 32], [6 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "037", V1ELEMENTS.POINTS: [[7 * 32, 3 * 32], [32 + 7 * 32, 3 * 32], [32 + 7 * 32, 32 + 3 * 32], [7 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "038", V1ELEMENTS.POINTS: [[8 * 32, 3 * 32], [32 + 8 * 32, 3 * 32], [32 + 8 * 32, 32 + 3 * 32], [8 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "039", V1ELEMENTS.POINTS: [[9 * 32, 3 * 32], [32 + 9 * 32, 3 * 32], [32 + 9 * 32, 32 + 3 * 32], [9 * 32, 32 + 3 * 32]], }, {V1ELEMENTS.GID: "040", V1ELEMENTS.POINTS: [[0 * 32, 4 * 32], [32 + 0 * 32, 4 * 32], [32 + 0 * 32, 32 + 4 * 32], [0 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "041", V1ELEMENTS.POINTS: [[1 * 32, 4 * 32], [32 + 1 * 32, 4 * 32], [32 + 1 * 32, 32 + 4 * 32], [1 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "042", V1ELEMENTS.POINTS: [[2 * 32, 4 * 32], [32 + 2 * 32, 4 * 32], [32 + 2 * 32, 32 + 4 * 32], [2 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "043", V1ELEMENTS.POINTS: [[3 * 32, 4 * 32], [32 + 3 * 32, 4 * 32], [32 + 3 * 32, 32 + 4 * 32], [3 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "044", V1ELEMENTS.POINTS: [[4 * 32, 4 * 32], [32 + 4 * 32, 4 * 32], [32 + 4 * 32, 32 + 4 * 32], [4 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "045", V1ELEMENTS.POINTS: [[5 * 32, 4 * 32], [32 + 5 * 32, 4 * 32], [32 + 5 * 32, 32 + 4 * 32], [5 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "046", V1ELEMENTS.POINTS: [[6 * 32, 4 * 32], [32 + 6 * 32, 4 * 32], [32 + 6 * 32, 32 + 4 * 32], [6 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "047", V1ELEMENTS.POINTS: [[7 * 32, 4 * 32], [32 + 7 * 32, 4 * 32], [32 + 7 * 32, 32 + 4 * 32], [7 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "048", V1ELEMENTS.POINTS: [[8 * 32, 4 * 32], [32 + 8 * 32, 4 * 32], [32 + 8 * 32, 32 + 4 * 32], [8 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "049", V1ELEMENTS.POINTS: [[9 * 32, 4 * 32], [32 + 9 * 32, 4 * 32], [32 + 9 * 32, 32 + 4 * 32], [9 * 32, 32 + 4 * 32]], }, {V1ELEMENTS.GID: "050", V1ELEMENTS.POINTS: [[0 * 32, 5 * 32], [32 + 0 * 32, 5 * 32], [32 + 0 * 32, 32 + 5 * 32], [0 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "051", V1ELEMENTS.POINTS: [[1 * 32, 5 * 32], [32 + 1 * 32, 5 * 32], [32 + 1 * 32, 32 + 5 * 32], [1 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "052", V1ELEMENTS.POINTS: [[2 * 32, 5 * 32], [32 + 2 * 32, 5 * 32], [32 + 2 * 32, 32 + 5 * 32], [2 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "053", V1ELEMENTS.POINTS: [[3 * 32, 5 * 32], [32 + 3 * 32, 5 * 32], [32 + 3 * 32, 32 + 5 * 32], [3 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "054", V1ELEMENTS.POINTS: [[4 * 32, 5 * 32], [32 + 4 * 32, 5 * 32], [32 + 4 * 32, 32 + 5 * 32], [4 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "055", V1ELEMENTS.POINTS: [[5 * 32, 5 * 32], [32 + 5 * 32, 5 * 32], [32 + 5 * 32, 32 + 5 * 32], [5 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "056", V1ELEMENTS.POINTS: [[6 * 32, 5 * 32], [32 + 6 * 32, 5 * 32], [32 + 6 * 32, 32 + 5 * 32], [6 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "057", V1ELEMENTS.POINTS: [[7 * 32, 5 * 32], [32 + 7 * 32, 5 * 32], [32 + 7 * 32, 32 + 5 * 32], [7 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "058", V1ELEMENTS.POINTS: [[8 * 32, 5 * 32], [32 + 8 * 32, 5 * 32], [32 + 8 * 32, 32 + 5 * 32], [8 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "059", V1ELEMENTS.POINTS: [[9 * 32, 5 * 32], [32 + 9 * 32, 5 * 32], [32 + 9 * 32, 32 + 5 * 32], [9 * 32, 32 + 5 * 32]], }, {V1ELEMENTS.GID: "060", V1ELEMENTS.POINTS: [[0 * 32, 6 * 32], [32 + 0 * 32, 6 * 32], [32 + 0 * 32, 32 + 6 * 32], [0 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "061", V1ELEMENTS.POINTS: [[1 * 32, 6 * 32], [32 + 1 * 32, 6 * 32], [32 + 1 * 32, 32 + 6 * 32], [1 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "062", V1ELEMENTS.POINTS: [[2 * 32, 6 * 32], [32 + 2 * 32, 6 * 32], [32 + 2 * 32, 32 + 6 * 32], [2 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "063", V1ELEMENTS.POINTS: [[3 * 32, 6 * 32], [32 + 3 * 32, 6 * 32], [32 + 3 * 32, 32 + 6 * 32], [3 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "064", V1ELEMENTS.POINTS: [[4 * 32, 6 * 32], [32 + 4 * 32, 6 * 32], [32 + 4 * 32, 32 + 6 * 32], [4 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "065", V1ELEMENTS.POINTS: [[5 * 32, 6 * 32], [32 + 5 * 32, 6 * 32], [32 + 5 * 32, 32 + 6 * 32], [5 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "066", V1ELEMENTS.POINTS: [[6 * 32, 6 * 32], [32 + 6 * 32, 6 * 32], [32 + 6 * 32, 32 + 6 * 32], [6 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "067", V1ELEMENTS.POINTS: [[7 * 32, 6 * 32], [32 + 7 * 32, 6 * 32], [32 + 7 * 32, 32 + 6 * 32], [7 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "068", V1ELEMENTS.POINTS: [[8 * 32, 6 * 32], [32 + 8 * 32, 6 * 32], [32 + 8 * 32, 32 + 6 * 32], [8 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "069", V1ELEMENTS.POINTS: [[9 * 32, 6 * 32], [32 + 9 * 32, 6 * 32], [32 + 9 * 32, 32 + 6 * 32], [9 * 32, 32 + 6 * 32]], }, {V1ELEMENTS.GID: "070", V1ELEMENTS.POINTS: [[0 * 32, 7 * 32], [32 + 0 * 32, 7 * 32], [32 + 0 * 32, 32 + 7 * 32], [0 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "071", V1ELEMENTS.POINTS: [[1 * 32, 7 * 32], [32 + 1 * 32, 7 * 32], [32 + 1 * 32, 32 + 7 * 32], [1 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "072", V1ELEMENTS.POINTS: [[2 * 32, 7 * 32], [32 + 2 * 32, 7 * 32], [32 + 2 * 32, 32 + 7 * 32], [2 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "073", V1ELEMENTS.POINTS: [[3 * 32, 7 * 32], [32 + 3 * 32, 7 * 32], [32 + 3 * 32, 32 + 7 * 32], [3 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "074", V1ELEMENTS.POINTS: [[4 * 32, 7 * 32], [32 + 4 * 32, 7 * 32], [32 + 4 * 32, 32 + 7 * 32], [4 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "075", V1ELEMENTS.POINTS: [[5 * 32, 7 * 32], [32 + 5 * 32, 7 * 32], [32 + 5 * 32, 32 + 7 * 32], [5 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "076", V1ELEMENTS.POINTS: [[6 * 32, 7 * 32], [32 + 6 * 32, 7 * 32], [32 + 6 * 32, 32 + 7 * 32], [6 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "077", V1ELEMENTS.POINTS: [[7 * 32, 7 * 32], [32 + 7 * 32, 7 * 32], [32 + 7 * 32, 32 + 7 * 32], [7 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "078", V1ELEMENTS.POINTS: [[8 * 32, 7 * 32], [32 + 8 * 32, 7 * 32], [32 + 8 * 32, 32 + 7 * 32], [8 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "079", V1ELEMENTS.POINTS: [[9 * 32, 7 * 32], [32 + 9 * 32, 7 * 32], [32 + 9 * 32, 32 + 7 * 32], [9 * 32, 32 + 7 * 32]], }, {V1ELEMENTS.GID: "080", V1ELEMENTS.POINTS: [[0 * 32, 8 * 32], [32 + 0 * 32, 8 * 32], [32 + 0 * 32, 32 + 8 * 32], [0 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "081", V1ELEMENTS.POINTS: [[1 * 32, 8 * 32], [32 + 1 * 32, 8 * 32], [32 + 1 * 32, 32 + 8 * 32], [1 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "082", V1ELEMENTS.POINTS: [[2 * 32, 8 * 32], [32 + 2 * 32, 8 * 32], [32 + 2 * 32, 32 + 8 * 32], [2 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "083", V1ELEMENTS.POINTS: [[3 * 32, 8 * 32], [32 + 3 * 32, 8 * 32], [32 + 3 * 32, 32 + 8 * 32], [3 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "084", V1ELEMENTS.POINTS: [[4 * 32, 8 * 32], [32 + 4 * 32, 8 * 32], [32 + 4 * 32, 32 + 8 * 32], [4 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "085", V1ELEMENTS.POINTS: [[5 * 32, 8 * 32], [32 + 5 * 32, 8 * 32], [32 + 5 * 32, 32 + 8 * 32], [5 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "086", V1ELEMENTS.POINTS: [[6 * 32, 8 * 32], [32 + 6 * 32, 8 * 32], [32 + 6 * 32, 32 + 8 * 32], [6 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "087", V1ELEMENTS.POINTS: [[7 * 32, 8 * 32], [32 + 7 * 32, 8 * 32], [32 + 7 * 32, 32 + 8 * 32], [7 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "088", V1ELEMENTS.POINTS: [[8 * 32, 8 * 32], [32 + 8 * 32, 8 * 32], [32 + 8 * 32, 32 + 8 * 32], [8 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "089", V1ELEMENTS.POINTS: [[9 * 32, 8 * 32], [32 + 9 * 32, 8 * 32], [32 + 9 * 32, 32 + 8 * 32], [9 * 32, 32 + 8 * 32]], }, {V1ELEMENTS.GID: "090", V1ELEMENTS.POINTS: [[0 * 32, 9 * 32], [32 + 0 * 32, 9 * 32], [32 + 0 * 32, 32 + 9 * 32], [0 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "091", V1ELEMENTS.POINTS: [[1 * 32, 9 * 32], [32 + 1 * 32, 9 * 32], [32 + 1 * 32, 32 + 9 * 32], [1 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "092", V1ELEMENTS.POINTS: [[2 * 32, 9 * 32], [32 + 2 * 32, 9 * 32], [32 + 2 * 32, 32 + 9 * 32], [2 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "093", V1ELEMENTS.POINTS: [[3 * 32, 9 * 32], [32 + 3 * 32, 9 * 32], [32 + 3 * 32, 32 + 9 * 32], [3 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "094", V1ELEMENTS.POINTS: [[4 * 32, 9 * 32], [32 + 4 * 32, 9 * 32], [32 + 4 * 32, 32 + 9 * 32], [4 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "095", V1ELEMENTS.POINTS: [[5 * 32, 9 * 32], [32 + 5 * 32, 9 * 32], [32 + 5 * 32, 32 + 9 * 32], [5 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "096", V1ELEMENTS.POINTS: [[6 * 32, 9 * 32], [32 + 6 * 32, 9 * 32], [32 + 6 * 32, 32 + 9 * 32], [6 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "097", V1ELEMENTS.POINTS: [[7 * 32, 9 * 32], [32 + 7 * 32, 9 * 32], [32 + 7 * 32, 32 + 9 * 32], [7 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "098", V1ELEMENTS.POINTS: [[8 * 32, 9 * 32], [32 + 8 * 32, 9 * 32], [32 + 8 * 32, 32 + 9 * 32], [8 * 32, 32 + 9 * 32]], }, {V1ELEMENTS.GID: "099", V1ELEMENTS.POINTS: [[9 * 32, 9 * 32], [32 + 9 * 32, 9 * 32], [32 + 9 * 32, 32 + 9 * 32], [9 * 32, 32 + 9 * 32]], }, ]} SDEF_GRID_10X10_SPACE_50 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "out.png.sdef", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0 * 82, 0 * 82], [32 + 0 * 82, 0 * 82], [32 + 0 * 82, 32 + 0 * 82], [0 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[1 * 82, 0 * 82], [32 + 1 * 82, 0 * 82], [32 + 1 * 82, 32 + 0 * 82], [1 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[2 * 82, 0 * 82], [32 + 2 * 82, 0 * 82], [32 + 2 * 82, 32 + 0 * 82], [2 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[3 * 82, 0 * 82], [32 + 3 * 82, 0 * 82], [32 + 3 * 82, 32 + 0 * 82], [3 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "004", V1ELEMENTS.POINTS: [[4 * 82, 0 * 82], [32 + 4 * 82, 0 * 82], [32 + 4 * 82, 32 + 0 * 82], [4 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "005", V1ELEMENTS.POINTS: [[5 * 82, 0 * 82], [32 + 5 * 82, 0 * 82], [32 + 5 * 82, 32 + 0 * 82], [5 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "006", V1ELEMENTS.POINTS: [[6 * 82, 0 * 82], [32 + 6 * 82, 0 * 82], [32 + 6 * 82, 32 + 0 * 82], [6 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "007", V1ELEMENTS.POINTS: [[7 * 82, 0 * 82], [32 + 7 * 82, 0 * 82], [32 + 7 * 82, 32 + 0 * 82], [7 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "008", V1ELEMENTS.POINTS: [[8 * 82, 0 * 82], [32 + 8 * 82, 0 * 82], [32 + 8 * 82, 32 + 0 * 82], [8 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "009", V1ELEMENTS.POINTS: [[9 * 82, 0 * 82], [32 + 9 * 82, 0 * 82], [32 + 9 * 82, 32 + 0 * 82], [9 * 82, 32 + 0 * 82]], }, {V1ELEMENTS.GID: "010", V1ELEMENTS.POINTS: [[0 * 82, 1 * 82], [32 + 0 * 82, 1 * 82], [32 + 0 * 82, 32 + 1 * 82], [0 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "011", V1ELEMENTS.POINTS: [[1 * 82, 1 * 82], [32 + 1 * 82, 1 * 82], [32 + 1 * 82, 32 + 1 * 82], [1 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "012", V1ELEMENTS.POINTS: [[2 * 82, 1 * 82], [32 + 2 * 82, 1 * 82], [32 + 2 * 82, 32 + 1 * 82], [2 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "013", V1ELEMENTS.POINTS: [[3 * 82, 1 * 82], [32 + 3 * 82, 1 * 82], [32 + 3 * 82, 32 + 1 * 82], [3 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "014", V1ELEMENTS.POINTS: [[4 * 82, 1 * 82], [32 + 4 * 82, 1 * 82], [32 + 4 * 82, 32 + 1 * 82], [4 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "015", V1ELEMENTS.POINTS: [[5 * 82, 1 * 82], [32 + 5 * 82, 1 * 82], [32 + 5 * 82, 32 + 1 * 82], [5 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "016", V1ELEMENTS.POINTS: [[6 * 82, 1 * 82], [32 + 6 * 82, 1 * 82], [32 + 6 * 82, 32 + 1 * 82], [6 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "017", V1ELEMENTS.POINTS: [[7 * 82, 1 * 82], [32 + 7 * 82, 1 * 82], [32 + 7 * 82, 32 + 1 * 82], [7 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "018", V1ELEMENTS.POINTS: [[8 * 82, 1 * 82], [32 + 8 * 82, 1 * 82], [32 + 8 * 82, 32 + 1 * 82], [8 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "019", V1ELEMENTS.POINTS: [[9 * 82, 1 * 82], [32 + 9 * 82, 1 * 82], [32 + 9 * 82, 32 + 1 * 82], [9 * 82, 32 + 1 * 82]], }, {V1ELEMENTS.GID: "020", V1ELEMENTS.POINTS: [[0 * 82, 2 * 82], [32 + 0 * 82, 2 * 82], [32 + 0 * 82, 32 + 2 * 82], [0 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "021", V1ELEMENTS.POINTS: [[1 * 82, 2 * 82], [32 + 1 * 82, 2 * 82], [32 + 1 * 82, 32 + 2 * 82], [1 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "022", V1ELEMENTS.POINTS: [[2 * 82, 2 * 82], [32 + 2 * 82, 2 * 82], [32 + 2 * 82, 32 + 2 * 82], [2 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "023", V1ELEMENTS.POINTS: [[3 * 82, 2 * 82], [32 + 3 * 82, 2 * 82], [32 + 3 * 82, 32 + 2 * 82], [3 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "024", V1ELEMENTS.POINTS: [[4 * 82, 2 * 82], [32 + 4 * 82, 2 * 82], [32 + 4 * 82, 32 + 2 * 82], [4 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "025", V1ELEMENTS.POINTS: [[5 * 82, 2 * 82], [32 + 5 * 82, 2 * 82], [32 + 5 * 82, 32 + 2 * 82], [5 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "026", V1ELEMENTS.POINTS: [[6 * 82, 2 * 82], [32 + 6 * 82, 2 * 82], [32 + 6 * 82, 32 + 2 * 82], [6 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "027", V1ELEMENTS.POINTS: [[7 * 82, 2 * 82], [32 + 7 * 82, 2 * 82], [32 + 7 * 82, 32 + 2 * 82], [7 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "028", V1ELEMENTS.POINTS: [[8 * 82, 2 * 82], [32 + 8 * 82, 2 * 82], [32 + 8 * 82, 32 + 2 * 82], [8 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "029", V1ELEMENTS.POINTS: [[9 * 82, 2 * 82], [32 + 9 * 82, 2 * 82], [32 + 9 * 82, 32 + 2 * 82], [9 * 82, 32 + 2 * 82]], }, {V1ELEMENTS.GID: "030", V1ELEMENTS.POINTS: [[0 * 82, 3 * 82], [32 + 0 * 82, 3 * 82], [32 + 0 * 82, 32 + 3 * 82], [0 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "031", V1ELEMENTS.POINTS: [[1 * 82, 3 * 82], [32 + 1 * 82, 3 * 82], [32 + 1 * 82, 32 + 3 * 82], [1 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "032", V1ELEMENTS.POINTS: [[2 * 82, 3 * 82], [32 + 2 * 82, 3 * 82], [32 + 2 * 82, 32 + 3 * 82], [2 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "033", V1ELEMENTS.POINTS: [[3 * 82, 3 * 82], [32 + 3 * 82, 3 * 82], [32 + 3 * 82, 32 + 3 * 82], [3 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "034", V1ELEMENTS.POINTS: [[4 * 82, 3 * 82], [32 + 4 * 82, 3 * 82], [32 + 4 * 82, 32 + 3 * 82], [4 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "035", V1ELEMENTS.POINTS: [[5 * 82, 3 * 82], [32 + 5 * 82, 3 * 82], [32 + 5 * 82, 32 + 3 * 82], [5 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "036", V1ELEMENTS.POINTS: [[6 * 82, 3 * 82], [32 + 6 * 82, 3 * 82], [32 + 6 * 82, 32 + 3 * 82], [6 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "037", V1ELEMENTS.POINTS: [[7 * 82, 3 * 82], [32 + 7 * 82, 3 * 82], [32 + 7 * 82, 32 + 3 * 82], [7 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "038", V1ELEMENTS.POINTS: [[8 * 82, 3 * 82], [32 + 8 * 82, 3 * 82], [32 + 8 * 82, 32 + 3 * 82], [8 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "039", V1ELEMENTS.POINTS: [[9 * 82, 3 * 82], [32 + 9 * 82, 3 * 82], [32 + 9 * 82, 32 + 3 * 82], [9 * 82, 32 + 3 * 82]], }, {V1ELEMENTS.GID: "040", V1ELEMENTS.POINTS: [[0 * 82, 4 * 82], [32 + 0 * 82, 4 * 82], [32 + 0 * 82, 32 + 4 * 82], [0 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "041", V1ELEMENTS.POINTS: [[1 * 82, 4 * 82], [32 + 1 * 82, 4 * 82], [32 + 1 * 82, 32 + 4 * 82], [1 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "042", V1ELEMENTS.POINTS: [[2 * 82, 4 * 82], [32 + 2 * 82, 4 * 82], [32 + 2 * 82, 32 + 4 * 82], [2 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "043", V1ELEMENTS.POINTS: [[3 * 82, 4 * 82], [32 + 3 * 82, 4 * 82], [32 + 3 * 82, 32 + 4 * 82], [3 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "044", V1ELEMENTS.POINTS: [[4 * 82, 4 * 82], [32 + 4 * 82, 4 * 82], [32 + 4 * 82, 32 + 4 * 82], [4 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "045", V1ELEMENTS.POINTS: [[5 * 82, 4 * 82], [32 + 5 * 82, 4 * 82], [32 + 5 * 82, 32 + 4 * 82], [5 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "046", V1ELEMENTS.POINTS: [[6 * 82, 4 * 82], [32 + 6 * 82, 4 * 82], [32 + 6 * 82, 32 + 4 * 82], [6 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "047", V1ELEMENTS.POINTS: [[7 * 82, 4 * 82], [32 + 7 * 82, 4 * 82], [32 + 7 * 82, 32 + 4 * 82], [7 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "048", V1ELEMENTS.POINTS: [[8 * 82, 4 * 82], [32 + 8 * 82, 4 * 82], [32 + 8 * 82, 32 + 4 * 82], [8 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "049", V1ELEMENTS.POINTS: [[9 * 82, 4 * 82], [32 + 9 * 82, 4 * 82], [32 + 9 * 82, 32 + 4 * 82], [9 * 82, 32 + 4 * 82]], }, {V1ELEMENTS.GID: "050", V1ELEMENTS.POINTS: [[0 * 82, 5 * 82], [32 + 0 * 82, 5 * 82], [32 + 0 * 82, 32 + 5 * 82], [0 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "051", V1ELEMENTS.POINTS: [[1 * 82, 5 * 82], [32 + 1 * 82, 5 * 82], [32 + 1 * 82, 32 + 5 * 82], [1 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "052", V1ELEMENTS.POINTS: [[2 * 82, 5 * 82], [32 + 2 * 82, 5 * 82], [32 + 2 * 82, 32 + 5 * 82], [2 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "053", V1ELEMENTS.POINTS: [[3 * 82, 5 * 82], [32 + 3 * 82, 5 * 82], [32 + 3 * 82, 32 + 5 * 82], [3 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "054", V1ELEMENTS.POINTS: [[4 * 82, 5 * 82], [32 + 4 * 82, 5 * 82], [32 + 4 * 82, 32 + 5 * 82], [4 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "055", V1ELEMENTS.POINTS: [[5 * 82, 5 * 82], [32 + 5 * 82, 5 * 82], [32 + 5 * 82, 32 + 5 * 82], [5 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "056", V1ELEMENTS.POINTS: [[6 * 82, 5 * 82], [32 + 6 * 82, 5 * 82], [32 + 6 * 82, 32 + 5 * 82], [6 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "057", V1ELEMENTS.POINTS: [[7 * 82, 5 * 82], [32 + 7 * 82, 5 * 82], [32 + 7 * 82, 32 + 5 * 82], [7 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "058", V1ELEMENTS.POINTS: [[8 * 82, 5 * 82], [32 + 8 * 82, 5 * 82], [32 + 8 * 82, 32 + 5 * 82], [8 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "059", V1ELEMENTS.POINTS: [[9 * 82, 5 * 82], [32 + 9 * 82, 5 * 82], [32 + 9 * 82, 32 + 5 * 82], [9 * 82, 32 + 5 * 82]], }, {V1ELEMENTS.GID: "060", V1ELEMENTS.POINTS: [[0 * 82, 6 * 82], [32 + 0 * 82, 6 * 82], [32 + 0 * 82, 32 + 6 * 82], [0 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "061", V1ELEMENTS.POINTS: [[1 * 82, 6 * 82], [32 + 1 * 82, 6 * 82], [32 + 1 * 82, 32 + 6 * 82], [1 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "062", V1ELEMENTS.POINTS: [[2 * 82, 6 * 82], [32 + 2 * 82, 6 * 82], [32 + 2 * 82, 32 + 6 * 82], [2 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "063", V1ELEMENTS.POINTS: [[3 * 82, 6 * 82], [32 + 3 * 82, 6 * 82], [32 + 3 * 82, 32 + 6 * 82], [3 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "064", V1ELEMENTS.POINTS: [[4 * 82, 6 * 82], [32 + 4 * 82, 6 * 82], [32 + 4 * 82, 32 + 6 * 82], [4 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "065", V1ELEMENTS.POINTS: [[5 * 82, 6 * 82], [32 + 5 * 82, 6 * 82], [32 + 5 * 82, 32 + 6 * 82], [5 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "066", V1ELEMENTS.POINTS: [[6 * 82, 6 * 82], [32 + 6 * 82, 6 * 82], [32 + 6 * 82, 32 + 6 * 82], [6 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "067", V1ELEMENTS.POINTS: [[7 * 82, 6 * 82], [32 + 7 * 82, 6 * 82], [32 + 7 * 82, 32 + 6 * 82], [7 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "068", V1ELEMENTS.POINTS: [[8 * 82, 6 * 82], [32 + 8 * 82, 6 * 82], [32 + 8 * 82, 32 + 6 * 82], [8 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "069", V1ELEMENTS.POINTS: [[9 * 82, 6 * 82], [32 + 9 * 82, 6 * 82], [32 + 9 * 82, 32 + 6 * 82], [9 * 82, 32 + 6 * 82]], }, {V1ELEMENTS.GID: "070", V1ELEMENTS.POINTS: [[0 * 82, 7 * 82], [32 + 0 * 82, 7 * 82], [32 + 0 * 82, 32 + 7 * 82], [0 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "071", V1ELEMENTS.POINTS: [[1 * 82, 7 * 82], [32 + 1 * 82, 7 * 82], [32 + 1 * 82, 32 + 7 * 82], [1 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "072", V1ELEMENTS.POINTS: [[2 * 82, 7 * 82], [32 + 2 * 82, 7 * 82], [32 + 2 * 82, 32 + 7 * 82], [2 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "073", V1ELEMENTS.POINTS: [[3 * 82, 7 * 82], [32 + 3 * 82, 7 * 82], [32 + 3 * 82, 32 + 7 * 82], [3 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "074", V1ELEMENTS.POINTS: [[4 * 82, 7 * 82], [32 + 4 * 82, 7 * 82], [32 + 4 * 82, 32 + 7 * 82], [4 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "075", V1ELEMENTS.POINTS: [[5 * 82, 7 * 82], [32 + 5 * 82, 7 * 82], [32 + 5 * 82, 32 + 7 * 82], [5 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "076", V1ELEMENTS.POINTS: [[6 * 82, 7 * 82], [32 + 6 * 82, 7 * 82], [32 + 6 * 82, 32 + 7 * 82], [6 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "077", V1ELEMENTS.POINTS: [[7 * 82, 7 * 82], [32 + 7 * 82, 7 * 82], [32 + 7 * 82, 32 + 7 * 82], [7 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "078", V1ELEMENTS.POINTS: [[8 * 82, 7 * 82], [32 + 8 * 82, 7 * 82], [32 + 8 * 82, 32 + 7 * 82], [8 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "079", V1ELEMENTS.POINTS: [[9 * 82, 7 * 82], [32 + 9 * 82, 7 * 82], [32 + 9 * 82, 32 + 7 * 82], [9 * 82, 32 + 7 * 82]], }, {V1ELEMENTS.GID: "080", V1ELEMENTS.POINTS: [[0 * 82, 8 * 82], [32 + 0 * 82, 8 * 82], [32 + 0 * 82, 32 + 8 * 82], [0 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "081", V1ELEMENTS.POINTS: [[1 * 82, 8 * 82], [32 + 1 * 82, 8 * 82], [32 + 1 * 82, 32 + 8 * 82], [1 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "082", V1ELEMENTS.POINTS: [[2 * 82, 8 * 82], [32 + 2 * 82, 8 * 82], [32 + 2 * 82, 32 + 8 * 82], [2 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "083", V1ELEMENTS.POINTS: [[3 * 82, 8 * 82], [32 + 3 * 82, 8 * 82], [32 + 3 * 82, 32 + 8 * 82], [3 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "084", V1ELEMENTS.POINTS: [[4 * 82, 8 * 82], [32 + 4 * 82, 8 * 82], [32 + 4 * 82, 32 + 8 * 82], [4 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "085", V1ELEMENTS.POINTS: [[5 * 82, 8 * 82], [32 + 5 * 82, 8 * 82], [32 + 5 * 82, 32 + 8 * 82], [5 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "086", V1ELEMENTS.POINTS: [[6 * 82, 8 * 82], [32 + 6 * 82, 8 * 82], [32 + 6 * 82, 32 + 8 * 82], [6 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "087", V1ELEMENTS.POINTS: [[7 * 82, 8 * 82], [32 + 7 * 82, 8 * 82], [32 + 7 * 82, 32 + 8 * 82], [7 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "088", V1ELEMENTS.POINTS: [[8 * 82, 8 * 82], [32 + 8 * 82, 8 * 82], [32 + 8 * 82, 32 + 8 * 82], [8 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "089", V1ELEMENTS.POINTS: [[9 * 82, 8 * 82], [32 + 9 * 82, 8 * 82], [32 + 9 * 82, 32 + 8 * 82], [9 * 82, 32 + 8 * 82]], }, {V1ELEMENTS.GID: "090", V1ELEMENTS.POINTS: [[0 * 82, 9 * 82], [32 + 0 * 82, 9 * 82], [32 + 0 * 82, 32 + 9 * 82], [0 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "091", V1ELEMENTS.POINTS: [[1 * 82, 9 * 82], [32 + 1 * 82, 9 * 82], [32 + 1 * 82, 32 + 9 * 82], [1 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "092", V1ELEMENTS.POINTS: [[2 * 82, 9 * 82], [32 + 2 * 82, 9 * 82], [32 + 2 * 82, 32 + 9 * 82], [2 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "093", V1ELEMENTS.POINTS: [[3 * 82, 9 * 82], [32 + 3 * 82, 9 * 82], [32 + 3 * 82, 32 + 9 * 82], [3 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "094", V1ELEMENTS.POINTS: [[4 * 82, 9 * 82], [32 + 4 * 82, 9 * 82], [32 + 4 * 82, 32 + 9 * 82], [4 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "095", V1ELEMENTS.POINTS: [[5 * 82, 9 * 82], [32 + 5 * 82, 9 * 82], [32 + 5 * 82, 32 + 9 * 82], [5 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "096", V1ELEMENTS.POINTS: [[6 * 82, 9 * 82], [32 + 6 * 82, 9 * 82], [32 + 6 * 82, 32 + 9 * 82], [6 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "097", V1ELEMENTS.POINTS: [[7 * 82, 9 * 82], [32 + 7 * 82, 9 * 82], [32 + 7 * 82, 32 + 9 * 82], [7 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "098", V1ELEMENTS.POINTS: [[8 * 82, 9 * 82], [32 + 8 * 82, 9 * 82], [32 + 8 * 82, 32 + 9 * 82], [8 * 82, 32 + 9 * 82]], }, {V1ELEMENTS.GID: "099", V1ELEMENTS.POINTS: [[9 * 82, 9 * 82], [32 + 9 * 82, 9 * 82], [32 + 9 * 82, 32 + 9 * 82], [9 * 82, 32 + 9 * 82]], }, ]} SDEF_OVERLAPPING_SPRITES = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [0, 32]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 0], [64, 0], [32, 32], [28, 16]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[0, 32], [28, 28], [36, 64], [0, 64]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[32, 32], [64, 38], [64, 64], [48, 48]], }, ]} SDEF_OVERLAPPING_SPACING0 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [0, 32]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[36, 0], [68, 0], [36, 32], [32, 16]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[0, 36], [28, 32], [36, 68], [0, 68]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[36, 32], [68, 38], [68, 64], [52, 48]], }, ]} SDEF_OVERLAPPING_SPACING3 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [0, 32]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[39, 0], [71, 0], [39, 32], [35, 16]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[0, 39], [28, 35], [36, 71], [0, 71]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[39, 35], [71, 41], [71, 67], [55, 51]], }, ]} SDEF_EXTREME_OVERLAPPING = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[5, 0], [64, 0], [64, 10], [5, 10]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[10, 3], [40, 3], [40, 15], [10, 15]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[64, 0], [71, 0], [71, 67], [64, 67]], }, ]} SDEF_EXTREME_OVERLAPPING_MARGIN10 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[10, 10], [42, 10], [42, 15], [10, 15]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[5 + 10, 0 + 10], [64 + 10, 0 + 10], [64 + 10, 10 + 10], [5 + 10, 10 + 10]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[10 + 10, 3 + 10], [40 + 10, 3 + 10], [40 + 10, 15 + 10], [10 + 10, 15 + 10]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[64 + 10, 0 + 10], [71 + 10, 0 + 10], [71 + 10, 67 + 10], [64 + 10, 67 + 10]], }, ]} SDEF_EXTREME_OVERLAPPING_SPACING5 = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[5 + 32, 0], [64 + 32, 0], [64 + 32, 10], [5 + 32, 10]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[10 + 30, 3 + 12], [40 + 30, 3 + 12], [40 + 30, 15 + 12], [10 + 30, 15 + 12]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[64 + 37, 0], [71 + 37, 0], [71 + 37, 67], [64 + 37, 67]], }, ]} SDEF_INVALID_DUPLICATE_NAMES = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[37, 0], [96, 0], [96, 10], [37, 10]], }, ]} SDEF_INVALID_MISSING_SPRITES = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", } SDEF_INVALID_MISSING_SPRITES_LIST_EMPTY = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: []} SDEF_INVALID_INCONSISTENT_ORIENTATION = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[136, 0], [143, 10], [143, 67], [136, 67]], }, {V1ELEMENTS.GID: "002", V1ELEMENTS.POINTS: [[136, 67], [143, 67], [143, 10], [136, 0]], }, {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[136, 0], [143, 10], [143, 67], [136, 67]], }, ]} SDEF_INVALID_NEGATIVE_Y_COORDINATES = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[136, 0], [143, -10], [143, 67], [136, 67]], }, ]} SDEF_INVALID_NEGATIVE_X_COORDINATES = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "003", V1ELEMENTS.POINTS: [[136, 0], [143, 10], [-143, 67], [136, 67]], }, ]} SDEF_INVALID_VERSION = {V1ELEMENTS.VERSION: "0.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, ]} SDEF_INVALID_MISSING_VERSION = {V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, ]} SDEF_INVALID_MISSING_SPRITE_NAME = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, ]} SDEF_INVALID_MISSING_POINTS = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", }, ]} SDEF_INVALID_MISSING_POINT_COORDINATES = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 5], [0, 5]], }, ]} SDEF_INVALID_MISSING_FILENAME = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[10, 10], [42, 10], [42, 15], [10, 15]], }, ]} SDEF_INVALID_FILENAME_EMPTY = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[0, 0], [32, 0], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[10, 10], [42, 10], [42, 15], [10, 15]], }, ]} SDEF_INVALID_COLINEAR_COORDINATES_TRIANGLE = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[10, 10], [5, 5], [15, 15]], }, # colinear {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 5], [0, 5], [2, 3]], }, ]} SDEF_INVALID_COLINEAR_COORDINATES_POLYGON = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", # colinear points V1ELEMENTS.POINTS: [[1, 1], [2, 2], [5, 5], [10, 10], [55, 55], [15, 15]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 5], [0, 5], [2, 3]], }, ]} SDEF_INVALID_COLINEAR_2_POINTS_SAME = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[32, 5], [32, 5], [0, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 5], [0, 5], [2, 3]], }, ]} SDEF_INVALID_COLINEAR_3_POINTS_SAME = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[5, 5], [5, 5], [5, 5]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 5], [0, 5], [2, 3]], }, ]} SDEF_WARN_2_POINTS_SAME_IN_POLYGON = {V1ELEMENTS.VERSION: "1.0", V1ELEMENTS.FILENAME: "x.png", V1ELEMENTS.SPRITES: [ {V1ELEMENTS.GID: "000", V1ELEMENTS.POINTS: [[32, 5], [0, 5], [0, 20], [32, 5], [10, 6]], }, {V1ELEMENTS.GID: "001", V1ELEMENTS.POINTS: [[32, 5], [0, 5], [2, 30]], }, ]} # noinspection PyUnusedLocal
[docs]class LoggerMock(object): """ The mock object for the logging :param level: the logging level the mock should use, same as logging levels (e.g. logging.DEBUG) """ def __init__(self, level=logging.DEBUG): self.messages = [] # [(level, msg), ] self.level = level
[docs] def debug(self, msg, *args, **kwargs): """ The debug message to log. :param msg: The message to log. :param args: Arguments if msg is a format string. :param kwargs: Keyword arguments. """ # logger.debug(msg, *args, **kwargs) if self.level <= logging.DEBUG: self.messages.append((logging.DEBUG, msg))
[docs] def info(self, msg, *args, **kwargs): """ The info message to log. :param msg: The message to log. :param args: Arguments if msg is a format string. :param kwargs: Keyword arguments. """ # logger.info(msg, *args, **kwargs) if self.level <= logging.INFO: self.messages.append((logging.INFO, msg))
[docs] def error(self, msg, *args, **kwargs): """ The error message to log. :param msg: The message to log. :param args: Arguments if msg is a format string. :param kwargs: Keyword arguments. """ # logger.error(msg, *args, **kwargs) if self.level <= logging.ERROR: self.messages.append((logging.ERROR, msg))
[docs] def warn(self, msg, *args, **kwargs): """ The warn message to log. :param msg: The message to log. :param args: Arguments if msg is a format string. :param kwargs: Keyword arguments. """ # logger.warn(msg, *args, **kwargs) if self.level <= logging.WARN: self.messages.append((logging.WARN, msg))
[docs]class TestLoggerMock(unittest.TestCase):
[docs] def test_log_level_debug(self): # arrange logger_mock = LoggerMock() # act logger_mock.debug("debug") logger_mock.info("info") logger_mock.warn("warn") logger_mock.error("error") # verify self.assertEqual(4, len(logger_mock.messages)) self.assertEqual((logging.DEBUG, "debug"), logger_mock.messages[0]) self.assertEqual((logging.INFO, "info"), logger_mock.messages[1]) self.assertEqual((logging.WARN, "warn"), logger_mock.messages[2]) self.assertEqual((logging.ERROR, "error"), logger_mock.messages[3])
[docs] def test_log_level_info(self): # arrange logger_mock = LoggerMock(level=logging.INFO) # act logger_mock.debug("debug") logger_mock.info("info") logger_mock.warn("warn") logger_mock.error("error") # verify self.assertEqual(3, len(logger_mock.messages)) self.assertEqual((logging.INFO, "info"), logger_mock.messages[0]) self.assertEqual((logging.WARN, "warn"), logger_mock.messages[1]) self.assertEqual((logging.ERROR, "error"), logger_mock.messages[2])
[docs] def test_log_level_warn(self): # arrange logger_mock = LoggerMock(level=logging.WARN) # act logger_mock.debug("debug") logger_mock.info("info") logger_mock.warn("warn") logger_mock.error("error") # verify self.assertEqual(2, len(logger_mock.messages)) self.assertEqual((logging.WARN, "warn"), logger_mock.messages[0]) self.assertEqual((logging.ERROR, "error"), logger_mock.messages[1])
[docs] def test_log_level_error(self): # arrange logger_mock = LoggerMock(level=logging.ERROR) # act logger_mock.debug("debug") logger_mock.info("info") logger_mock.warn("warn") logger_mock.error("error") # verify self.assertEqual(1, len(logger_mock.messages)) self.assertEqual((logging.ERROR, "error"), logger_mock.messages[0])
[docs] def test_log_level_critical(self): # arrange logger_mock = LoggerMock(level=logging.CRITICAL) # act logger_mock.debug("debug") logger_mock.info("info") logger_mock.warn("warn") logger_mock.error("error") # verify self.assertEqual(0, len(logger_mock.messages))
[docs]def get_method_names(obj): """ Generator function that returns the public method names of the given object (public methods mean none that starts with '_'). :param obj: the object to get the method names from. """ import inspect for m in inspect.getmembers(obj, predicate=lambda x: inspect.ismethod(x) and not x.__name__.startswith('_') and type( obj) == find_defining_class(obj, x.__name__)): yield ((m[0], ), {})
[docs]def find_defining_class(obj, method_name): """ Finds the class where the method is defined. :param obj: any object :param method_name: the name of the method :return: returns the type of first class defining the method, otherwise None """ type1 = type(obj) type__mro = type1.mro() for ty in type__mro: dict__ = ty.__dict__ if method_name in dict__: return ty
[docs]class TestFindDefiningClass(unittest.TestCase): """ This tests test the working of the function 'find_defining_class'. """
[docs] def test_find_defining_class(self): # arrange # noinspection PyDocstring class Level0(object): """ The Level 0 class. """ def level0(self): pass def level01(self): pass def level02(self): pass def level012(self): pass # noinspection PyDocstring class Level1(Level0): """ The level 1 class. """ def level1(self): pass def level01(self): Level0.level01(self) def level12(self): pass def level012(self): Level0.level012(self) # noinspection PyDocstring class Level2(Level1): """ The level 2 class. """ def level2(self): pass def level12(self): Level1.level12(self) def level02(self): Level1.level02(self) def level012(self): Level1.level012(self) # act level = Level2() level.level0() level.level01() level.level02() level.level012() level.level1() level.level12() level.level2() # verify self.assertEqual(Level0, find_defining_class(level, "level0")) self.assertEqual(Level1, find_defining_class(level, "level1")) self.assertEqual(Level1, find_defining_class(level, "level01")) self.assertEqual(Level2, find_defining_class(level, "level2")) self.assertEqual(Level2, find_defining_class(level, "level02")) self.assertEqual(Level2, find_defining_class(level, "level12")) self.assertEqual(Level2, find_defining_class(level, "level012"))
[docs]class TestGridCommand(unittest.TestCase):
[docs] def setUp(self): self.logger_mock = LoggerMock()
[docs] def test_simple_grid_generation(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act actual_sprite_definition = sut.create_grid(2, 2, 32, 32, mut.FileInfo("out.png.sdef")) # verify self.maxDiff = None data = sut.clone_sprite_definition(TestData.SDEF_GRID_2X2) del data[V1ELEMENTS.SPRITES][0][V1ELEMENTS.ANCHOR] self.assertDictEqual(data, actual_sprite_definition)
@ddtd.use_data_driven_testing_decorators
[docs]class TestSpriteDefinitionGeneration(unittest.TestCase):
[docs] def setUp(self): self.logger_mock = LoggerMock()
@ddtd.test_case(TestData.SDEF_GRID_2X2, TestData.SDEF_GRID_2X2) @ddtd.test_case(TestData.SDEF_OVERLAPPING_SPRITES, TestData.SDEF_OVERLAPPING_SPRITES, None, test_name="overlapping_spacing_-1") @ddtd.test_case(TestData.SDEF_OVERLAPPING_SPACING0, TestData.SDEF_OVERLAPPING_SPRITES, 0, test_name="overlapping_spacing_0") @ddtd.test_case(TestData.SDEF_OVERLAPPING_SPACING3, TestData.SDEF_OVERLAPPING_SPRITES, 3, test_name="overlapping_spacing_3") @ddtd.test_case(TestData.SDEF_EXTREME_OVERLAPPING_SPACING5, TestData.SDEF_EXTREME_OVERLAPPING, 5, 0, test_name="overlapping_extreme_spacing_5") @ddtd.test_case(TestData.SDEF_EXTREME_OVERLAPPING, TestData.SDEF_EXTREME_OVERLAPPING, None, test_name="overlapping_extreme_no_spacing") @ddtd.test_case(TestData.SDEF_EXTREME_OVERLAPPING_MARGIN10, TestData.SDEF_EXTREME_OVERLAPPING, None, 10, test_name="overlapping_extreme_margin_10") @ddtd.test_case(TestData.SDEF_GRID_10X10_SPACE_50, TestData.SDEF_GRID_10X10, 50, 0, test_name="grid_10x10_spacing50") def test_simple_grid_sprite_definition_generation(self, expected, sdef, spacing=None, margin=0): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act actual_sprite_definition = sut.adjust_spacing(sdef, spacing) actual_sprite_definition = sut.adjust_margin(actual_sprite_definition, margin) # verify self.maxDiff = None self.assertDictEqual(expected, actual_sprite_definition)
[docs] def test_new_sprite_definition_is_a_different_instance(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act actual = sut.adjust_spacing(TestData.SDEF_GRID_2X2, None) # verify self.assertFalse(actual is TestData.SDEF_GRID_2X2)
[docs] def test_margin_0(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) sdef = TestData.SDEF_GRID_2X2 margin = 0 # act actual = sut.adjust_margin(sdef, margin) # verify self.assertDictEqual(TestData.SDEF_GRID_2X2, actual)
[docs] def test_margin_x(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) sdef = TestData.SDEF_GRID_2X2 margin = 33 # act actual = sut.adjust_margin(sdef, margin) # verify self.maxDiff = None self.assertDictEqual(TestData.SDEF_GRID_2X2_MARGIN_33, actual)
[docs] def test_special_aabb_margin_5(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) sdef = TestData.SDEF_GRID_2X2_SPECIAL_MARGIN margin = 5 self.maxDiff = None # act actual = sut.adjust_margin(sdef, margin) # verify self.assertDictEqual(TestData.SDEF_GRID_2X2_SPECIAL_MARGIN_5, actual)
[docs] def test_negative_margin_raises_ValueError(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) sdef = TestData.SDEF_GRID_2X2_SPECIAL_MARGIN margin = -5 self.maxDiff = None # act / verify self.assertRaises(ValueError, sut.adjust_margin, sdef, margin)
[docs]class TestImageGeneration(unittest.TestCase):
[docs] def setUp(self): self.logger_mock = LoggerMock()
[docs] def test_image_is_created(self): # arrange import pygame sut = mut.SpritesheetLib10(self.logger_mock) # act actual = sut.create_image(TestData.SDEF_GRID_2X2) actual_size = actual.get_size() # verify self.assertIsInstance(actual, pygame.Surface) expected_size = (64, 64) self.assertEqual(expected_size, actual_size)
[docs] def test_image_with_margin_is_created(self): # arrange import pygame sut = mut.SpritesheetLib10(self.logger_mock) margin = 20 sdef_grid_2x2_with_margin = sut.adjust_margin(TestData.SDEF_GRID_2X2, margin) # act actual = sut.create_image(sdef_grid_2x2_with_margin) actual_size = actual.get_size() # verify self.assertIsInstance(actual, pygame.Surface) expected_size = (104, 104) self.assertEqual(expected_size, actual_size)
@ddtd.use_data_driven_testing_decorators
[docs]class TestAABB(unittest.TestCase):
[docs] def setUp(self): self.min_x = 2 self.max_x = 20 self.min_y = 5 self.max_y = 7 self.center_x = self.min_x + (self.max_x - self.min_x) // 2 self.center_y = self.min_y + (self.max_y - self.min_y) // 2
[docs] def test_aabb_min_max(self): # arrange # act aabb = mut.AABB(self.min_x, self.min_y, self.max_x, self.max_y) # verify self.assertEqual(self.min_x, aabb.min_x) self.assertEqual(self.min_y, aabb.min_y) self.assertEqual(self.max_x, aabb.max_x) self.assertEqual(self.max_y, aabb.max_y) self.assertEqual(self.center_x, aabb.center_x) self.assertEqual(self.center_y, aabb.center_y)
[docs] def test_aabb_wrong_value_order_x(self): # arrange # act / verify self.assertRaises(AssertionError, mut.AABB, self.max_x, self.min_y, self.min_x, self.max_y)
[docs] def test_aabb_wrong_value_order_y(self): # arrange # act / verify self.assertRaises(AssertionError, mut.AABB, self.min_x, self.max_y, self.max_x, self.min_y)
@ddtd.test_case(11, 11, 20, 20, True) @ddtd.test_case(1, 1, 9, 9, True) @ddtd.test_case(1, 11, 9, 20, True) @ddtd.test_case(11, 1, 20, 9, True) @ddtd.test_case(2, 6, 20, 9, True) @ddtd.test_case(6, 2, 9, 20, True) @ddtd.test_case(6, 2, 9, 10, True) @ddtd.test_case(2, 6, 10, 9, True) @ddtd.test_case(12, 6, 19, 9, True) @ddtd.test_case(6, 12, 9, 19, True) @ddtd.test_case(1, 1, 3, 3, False) @ddtd.test_case(19, 10, 30, 13, False) @ddtd.test_case(1, 10, 3, 13, False) @ddtd.test_case(7, 19, 9, 33, False) def test_aabb_collision(self, v, w, x, y, expected): # arrange other = mut.AABB(v, w, x, y) aabb = mut.AABB(5, 5, 15, 15) # act actual = aabb.collide(other) other_actual = other.collide(aabb) # verify self.assertEqual(expected, actual) self.assertEqual(other_actual, actual)
[docs] def test_aabb_from_points(self): # arrange points = [(2, 3), (45, 2), (15, 33)] # act actual = mut.AABB.from_points(points) # verify expected = mut.AABB(2, 2, 45, 33) self.assertEqual(expected, actual)
[docs] def test_aabb_are_not_equal(self): # arrange aabb = mut.AABB(1, 1, 2, 2) other = mut.AABB(1, 2, 3, 4) # act actual = aabb != other # verify self.assertEqual(True, actual)
[docs] def test_aabb_not_equal_to_other_type(self): # arrange aabb = mut.AABB(1, 1, 5, 5) other = object() # act actual = aabb != other # verify self.assertEqual(True, actual)
[docs] def test_aabb_equal_to_other_type(self): # arrange aabb = mut.AABB(1, 1, 5, 5) other = object() # act actual = aabb == other # verify self.assertEqual(False, actual)
[docs] def test_aabb_are_not_equal_false(self): # arrange aabb = mut.AABB(1, 2, 3, 4) other = mut.AABB(10, 20, 30, 40) # act actual = aabb == other # verify self.assertEqual(False, actual)
[docs] def test_aabb_are_equal(self): # arrange aabb = mut.AABB(1, 2, 3, 4) other = mut.AABB(1, 2, 3, 4) # act actual = aabb == other # verify self.assertEqual(True, actual)
[docs] def test_aabb_move(self): # arrange aabb = mut.AABB(1, 1, 5, 5) # act moved = aabb.move(3, 6) # verify self.assertEqual(mut.AABB(4, 7, 8, 11), moved)
[docs] def test_aabb_move_ip(self): # arrange aabb = mut.AABB(1, 1, 5, 5) # act aabb.move_ip(2, 4) # verify self.assertEqual(mut.AABB(3, 5, 7, 9), aabb)
[docs] def test_aabb_move_ip_center(self): # arrange aabb = mut.AABB(0, 0, 10, 10) # act aabb.move_ip(2, 4) # verify self.assertEqual(7, aabb.center_x) self.assertEqual(9, aabb.center_y)
[docs] def test_aabb_collide_all(self): # arrange colliding = [ mut.AABB(11, 11, 20, 20), mut.AABB(1, 1, 9, 9), mut.AABB(1, 11, 9, 20), mut.AABB(11, 1, 20, 9), mut.AABB(2, 6, 20, 9), mut.AABB(6, 2, 9, 20), mut.AABB(6, 2, 9, 10), mut.AABB(2, 6, 10, 9), mut.AABB(12, 6, 19, 9), mut.AABB(6, 12, 9, 19)] others = list(colliding) # make a copy others.extend([mut.AABB(1, 1, 3, 3), mut.AABB(19, 10, 30, 13), mut.AABB(1, 10, 3, 13), mut.AABB(7, 19, 9, 33), ]) aabb = mut.AABB(5, 5, 15, 15) # act actual = aabb.collide_all(others) # verify self.assertEqual(10, len(actual)) self.assertEqual(colliding, actual)
[docs] def test_union_all(self): # arrange others = [ mut.AABB(11, 11, 20, 20), mut.AABB(1, 1, 9, 9), mut.AABB(1, 11, 9, 20), mut.AABB(11, 1, 20, 9), mut.AABB(2, 6, 20, 9), mut.AABB(6, 2, 9, 20), mut.AABB(6, 2, 9, 10), mut.AABB(2, 6, 10, 9), mut.AABB(12, 6, 19, 9), mut.AABB(6, 12, 9, 19), mut.AABB(1, 1, 3, 3), mut.AABB(19, 10, 30, 13), mut.AABB(1, 10, 3, 13), mut.AABB(7, 19, 9, 33), ] aabb = mut.AABB(3, 5, 8, 9) # act aabb_union = aabb.union_all(others) # verify expected = mut.AABB(1, 1, 30, 33) self.assertEqual(expected, aabb_union)
[docs] def test_union(self): # arrange other = mut.AABB(1, 2, 30, 40) aabb = mut.AABB(4, 20, 25, 25) # act union = aabb.union(other) # verify self.assertEqual(mut.AABB(1, 2, 30, 40), union)
[docs] def test_union2(self): # arrange aabb = mut.AABB(1, 2, 30, 40) other = mut.AABB(4, 20, 25, 25) # act union = aabb.union(other) # verify self.assertEqual(mut.AABB(1, 2, 30, 40), union)
[docs] def test_copy_from(self): # arrange aabb = mut.AABB(1, 1, 2, 2) source = mut.AABB(5, 6, 7, 8) self.assertNotEqual(source, aabb) # act aabb.copy_from(source) # verify self.assertEqual(source, aabb)
[docs] def test_copy(self): # arrange aabb = mut.AABB(1, 2, 3, 4) # act aabb_copy = aabb.copy() # verify self.assertEqual(aabb, aabb_copy)
[docs] def test_str(self): # arrange aabb = mut.AABB(1, 2, 3, 4) # act s = str(aabb) # verify self.assertTrue(len(s) > 0)
[docs] def test_repr(self): # arrange aabb = mut.AABB(1, 2, 3, 4) # act s = aabb.__repr__() # verify self.assertTrue(len(s) > 0) self.assertEqual("<AABB(1, 2, 3, 4)>", s)
[docs] def test_to_rect_tuple(self): # arrange aabb = mut.AABB(10, 20, 35, 40) # act rect_tuple = aabb.to_rect_tuple() # assert self.assertEqual((10, 20, 25, 20), rect_tuple)
def _invalid_sprite_definition_generator(): _INVALID_SPRITE_DEFINITIONS = [ ((TestData.SDEF_INVALID_DUPLICATE_NAMES, ), {'test_name': "TestData.SDEF_INVALID_DUPLICATE_NAMES"}), ((TestData.SDEF_INVALID_MISSING_SPRITES, ), {'test_name': "TestData.SDEF_INVALID_MISSING_SPRITES"}), ((TestData.SDEF_INVALID_NEGATIVE_X_COORDINATES, ), {'test_name': "TestData.SDEF_INVALID_NEGATIVE_X_COORDINATES"}), ((TestData.SDEF_INVALID_NEGATIVE_Y_COORDINATES, ), {'test_name': "TestData.SDEF_INVALID_NEGATIVE_Y_COORDINATES"}), ((TestData.SDEF_INVALID_VERSION, ), {'test_name': "TestData.SDEF_INVALID_VERSION"}), ((TestData.SDEF_INVALID_MISSING_VERSION, ), {'test_name': "TestData.SDEF_INVALID_MISSING_VERSION"}), ((TestData.SDEF_INVALID_MISSING_SPRITE_NAME, ), {'test_name': "TestData.SDEF_INVALID_MISSING_SPRITE_NAME"}), ((TestData.SDEF_INVALID_MISSING_POINTS, ), {'test_name': "TestData.SDEF_INVALID_MISSING_POINTS"}), ((TestData.SDEF_INVALID_MISSING_POINT_COORDINATES, ), {'test_name': "TestData.SDEF_INVALID_MISSING_POINT_COORDINATES"}), ((TestData.SDEF_INVALID_COLINEAR_COORDINATES_TRIANGLE, ), {'test_name': "TestData.SDEF_INVALID_COLINEAR_COORDINATES_TRIANGLE"}), ((TestData.SDEF_INVALID_COLINEAR_COORDINATES_POLYGON, ), {'test_name': "TestData.SDEF_INVALID_COLINEAR_COORDINATES_POLYGON"}), ((TestData.SDEF_INVALID_COLINEAR_2_POINTS_SAME, ), {'test_name': "TestData.SDEF_INVALID_COLINEAR_2_POINTS_SAME"}), ((TestData.SDEF_INVALID_COLINEAR_3_POINTS_SAME, ), {'test_name': "TestData.SDEF_INVALID_COLINEAR_3_POINTS_SAME"}), ((TestData.SDEF_INVALID_MISSING_SPRITES_LIST_EMPTY, ), {'test_name': "TestData.SDEF_INVALID_MISSING_SPRITES_LIST_EMPTY"}), ((TestData.SDEF_INVALID_INCONSISTENT_ORIENTATION, ), {'test_name': "TestData.SDEF_INVALID_INCONSISTENT_ORIENTATION"}), ((TestData.SDEF_INVALID_MISSING_FILENAME, ), {'test_name': "TestData.SDEF_INVALID_MISSING_FILENAME"}), ((TestData.SDEF_INVALID_FILENAME_EMPTY, ), {'test_name': "TestData.SDEF_INVALID_FILENAME_EMPTY"}), ] for item in _INVALID_SPRITE_DEFINITIONS: yield item @ddtd.use_data_driven_testing_decorators
[docs]class TestSpriteDefinitionValidation(unittest.TestCase):
[docs] def setUp(self): # arrange self.logger_mock = LoggerMock()
[docs] def test_is_valid(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act actual = sut.is_sprite_def_valid(TestData.SDEF_GRID_2X2) # verify self.assertTrue(actual)
@ddtd.test_case_from_generator(_invalid_sprite_definition_generator) def test_sprite_definition_is_invalid(self, sdef): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act actual = sut.is_sprite_def_valid(sdef) # verify self.assertFalse(actual) @ddtd.test_case_from_generator(_invalid_sprite_definition_generator) def test_sprite_definition_is_invalid_logs_error_message(self, sdef): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act sut.is_sprite_def_valid(sdef) # verify self.assertEqual(2, len(self.logger_mock.messages), self.logger_mock.messages) self.assertEqual(logging.ERROR, self.logger_mock.messages[1][0], self.logger_mock.messages)
[docs] def test_sprite_definition_logs_warning(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act sut.is_sprite_def_valid(TestData.SDEF_WARN_2_POINTS_SAME_IN_POLYGON) # verify self.assertEqual(2, len(self.logger_mock.messages)) self.assertEqual(logging.WARN, self.logger_mock.messages[1][0])
[docs] def test_sprite_definition_is_invalid_if_None(self): # arrange sut = mut.SpritesheetLib10(self.logger_mock) # act actual = sut.is_sprite_def_valid(None) # verify self.assertFalse(actual) self.assertEqual(logging.ERROR, self.logger_mock.messages[1][0])
import os import sys if sys.version_info[0] < 3: # Python 3.x renames the built-in module _bi = '__builtin__' # pragma: no cover else: _bi = 'builtins' # pragma: no cover __builtin__ = __import__(_bi) # class FileMock(object): # """ # The file mock simulates a file object of python. # """ # # def __exit__(self, exc_type, exc_val, exc_tb): # pass # # def __enter__(self): # return self # # # noinspection PyMethodMayBeStatic,PyUnusedLocal # def readlines(self, *args): # """ # Reads the lines of this file like object. # :param args: Any arguments, unused. # :return: The lines. # """ # return []
[docs]class TestFileInfoOpen(unittest.TestCase):
[docs] def setUp(self): self.method_calls = [] # [(name, args), ] self.file_mock = object() self.orig_open = __builtin__.open __builtin__.open = self.mocked_open
[docs] def tearDown(self): self.reset_builtin()
[docs] def reset_builtin(self): __builtin__.open = self.orig_open
[docs] def mocked_open(self, *args): self.method_calls.append(("open", args)) return self.file_mock
[docs] def test_open_same_casing(self): # arrange does_file_exist = True os_path_mock = OsPathMock(does_file_exist) list_dir = ["a.txt", "b.txt"] os_module_mock = OsModuleMock(os_path_mock, list_dir) sut = FileInfo("a.txt", os_module_mock) # act f = sut.open(mut.FileMode.ReadBinary) self.reset_builtin() # needs to be here to have no side effects in the assertions # verify self.assertIs(self.file_mock, f)
[docs] def test_open_different_casing(self): # arrange does_file_exist = True os_path_mock = OsPathMock(does_file_exist) list_dir = ["A.txt", "b.txt"] os_module_mock = OsModuleMock(os_path_mock, list_dir) sut = FileInfo("a.txt", os_module_mock) # act self.assertRaises(IOError, sut.open, mut.FileMode.ReadBinary)
@ddtd.use_data_driven_testing_decorators
[docs]class TestFileInfo(unittest.TestCase):
[docs] def test_directory_is_passed(self): # arrange directory_path = os.path.abspath("../tests") # act / verify self.assertRaises(ValueError, FileInfo, directory_path)
[docs] def test_is_casing_different_True(self): # arrange does_file_exist = True os_path_mock = OsPathMock(does_file_exist) list_dir = ["a.txt", "b.txt"] os_module_mock = OsModuleMock(os_path_mock, list_dir) fi = mut.FileInfo("A.txt", os_module_mock) # act actual = fi.is_casing_different # verify self.assertTrue(actual)
[docs] def test_is_casing_different_True_no_exists(self): # arrange does_file_exist = False os_path_mock = OsPathMock(does_file_exist) list_dir = ["a.txt", "b.txt"] os_module_mock = OsModuleMock(os_path_mock, list_dir) fi = mut.FileInfo("A.txt", os_module_mock) # act actual = fi.is_casing_different # verify self.assertFalse(actual)
[docs] def test_is_casing_different_False(self): # arrange does_file_exist = True os_path_mock = OsPathMock(does_file_exist) list_dir = ["a.txt", "b.txt"] os_module_mock = OsModuleMock(os_path_mock, list_dir) fi = mut.FileInfo("b.txt", os_module_mock) # act actual = fi.is_casing_different # verify self.assertFalse(actual)
[docs] def test_is_casing_different_False_no_exists(self): # arrange does_file_exist = False os_path_mock = OsPathMock(does_file_exist) list_dir = ["a.txt", "b.txt"] os_module_mock = OsModuleMock(os_path_mock, list_dir) fi = mut.FileInfo("b.txt", os_module_mock) # act actual = fi.is_casing_different # verify self.assertFalse(actual) # def test_file_does_not_exist_due_casing(self): # # arrange # does_file_exist = True # os_path_mock = OsPathMock(does_file_exist) # list_dir = ["a.txt", "b.py"] # os_module_mock = OsModuleMock(os_path_mock, list_dir) # fi = mut.FileInfo("B.py", os_module_mock) # # # act # actual = fi.exists # # # verify # self.assertFalse(actual)
[docs] def test_file_does_exist_with_correct_casing(self): # arrange does_file_exist = True os_path_mock = OsPathMock(does_file_exist) list_dir = ["a.txt", "b.py"] os_module_mock = OsModuleMock(os_path_mock, list_dir) fi = mut.FileInfo("b.py", os_module_mock) # act actual = fi.exists # verify self.assertTrue(actual)
[docs] def test_file_does_exists(self): # TODO: rewrite to use the os and os.path mock to remove disk access # arrange fi = mut.FileInfo("test_spritesheetlib.py") # act actual = fi.exists # verify self.assertTrue(actual)
[docs] def test_file_does_not_exists(self): # TODO: rewrite to use the os and os.path mock to remove disk access # arrange fi = mut.FileInfo("/tests/non-existing.txt") # act actual = fi.exists # verify self.assertFalse(actual)
[docs] def test_io_error_is_raised_for_non_existing(self): # TODO: rewrite to use the os and os.path mock to remove disk access # arrange fi = mut.FileInfo("/test/non-existing.txt") # act / verify self.assertRaises(IOError, fi.open, mut.FileMode.ReadBinary)
@ddtd.test_case(mut.FileMode.Read) @ddtd.test_case(mut.FileMode.ReadUpdate) @ddtd.test_case(mut.FileMode.ReadUniversalNewLines) @ddtd.test_case(mut.FileMode.ReadText) def test_open_read_using_mode(self, mode): # TODO: rewrite to use the os and os.path mock to remove disk access?? # arrange fi = mut.FileInfo(self.file_name) with fi.open(mut.FileMode.Write) as temp: temp.write("hello") # act with fi.open(mode) as fp: content = fp.readline() # verify self.assertEqual("hello", content) self.assertFalse(fp.closed) self.assertTrue(fp.closed) @ddtd.test_case(mut.FileMode.ReadBinary) @ddtd.test_case(mut.FileMode.ReadUpdateBinary) def test_open_read_using_mode_binary(self, mode): # TODO: rewrite to use the os and os.path mock to remove disk access?? # arrange fi = mut.FileInfo(self.file_name) with fi.open(mut.FileMode.WriteBinary) as temp: temp.write(b"hello") # act with fi.open(mode) as fp: content = fp.readline() # verify self.assertEqual(b"hello", content) self.assertFalse(fp.closed) self.assertTrue(fp.closed) @ddtd.test_case(mut.FileMode.Write) @ddtd.test_case(mut.FileMode.WriteUpdate) @ddtd.test_case(mut.FileMode.Append) @ddtd.test_case(mut.FileMode.AppendUpdate) @ddtd.test_case(mut.FileMode.WriteText) def test_open_write_with_mode(self, mode): # TODO: rewrite to use the os and os.path mock to remove disk access?? # arrange fi = mut.FileInfo(self.file_name) with fi.open(mode) as temp: temp.write("hello") # act with fi.open(mut.FileMode.ReadBinary) as fp: content = fp.readline() # verify self.assertEqual(b"hello", content) self.assertFalse(fp.closed) self.assertTrue(fp.closed) @ddtd.test_case(mut.FileMode.WriteBinary) @ddtd.test_case(mut.FileMode.WriteUpdateBinary) @ddtd.test_case(mut.FileMode.AppendBinary) @ddtd.test_case(mut.FileMode.AppendUpdateBinary) def test_open_write_with_mode_binary(self, mode): # TODO: rewrite to use the os and os.path mock to remove disk access?? # arrange fi = mut.FileInfo(self.file_name) with fi.open(mode) as temp: temp.write(b"hello") # act with fi.open(mut.FileMode.ReadBinary) as fp: content = fp.readline() # verify self.assertEqual(b"hello", content) self.assertFalse(fp.closed) self.assertTrue(fp.closed)
[docs] def test_file_info_does_not_accept_a_directory_path(self): # arrange dir_path = "." # act / verify self.assertRaises(ValueError, mut.FileInfo, dir_path)
[docs] def test_file_info_does_not_accept_a_directory_path_with_sep(self): # arrange dir_path = os.path.join(os.curdir, "test", os.sep) # act / verify self.assertRaises(ValueError, mut.FileInfo, dir_path)
[docs] def test_file_info_does_not_accept_a_directory_path_with_altsep(self): # arrange dir_path = os.path.join(os.curdir, "test", os.altsep) # act / verify self.assertRaises(ValueError, mut.FileInfo, dir_path)
[docs] def test_file_info_does_not_accept_a_directory_path_with_pardir(self): # arrange dir_path = os.path.join(os.curdir, "test", os.pardir) # act / verify self.assertRaises(ValueError, mut.FileInfo, dir_path)
[docs] def test_file_info_accepts_file_without_extension(self): # arrange file_name = os.path.join(os.curdir, "test", "test_file") # act / verify mut.FileInfo(file_name)
[docs] def test_file_info_raises_if_file_name_contains_pathsep(self): # arrange file_name = os.path.join("test.txt" + os.pathsep + os.curdir, "test", "test_file.txt") # act / verify self.assertRaises(ValueError, mut.FileInfo, file_name)
[docs] def test_file_info_raises_on_null_path(self): # arrange file_path = os.devnull # act / verify self.assertRaises(ValueError, mut.FileInfo, file_path)
[docs] def test_file_info_delete(self): # arrange fi = mut.FileInfo(self.file_name) with fi.open(mut.FileMode.Write) as f: f.write("hello") # act self.assertTrue(fi.exists) fi.delete() # verify self.assertFalse(fi.exists)
[docs] def test_name_property(self): # arrange file_name_and_path = os.path.join("subdir", "sub-sub-dir", self.file_name) fi = mut.FileInfo(file_name_and_path) # act name = fi.name # verify self.assertEqual(self.file_name, name)
[docs] def test_directory_name_property(self): # arrange directory_full_path = os.path.join("subdir", "sub-sub-dir") file_name_and_path = os.path.join(directory_full_path, self.file_name) fi = mut.FileInfo(file_name_and_path) # act name = fi.directory_name # verify expected = directory_full_path if os.path.altsep is not None: expected = expected.replace(os.path.sep, os.path.altsep) self.assertEqual(expected, name)
[docs] def test_directory_name_property_case(self): # arrange directory_full_path = os.path.join("subDir", "SubSubDir") file_name_and_path = os.path.join(directory_full_path, self.file_name) fi = mut.FileInfo(file_name_and_path) # act name = fi.directory_name # verify expected = directory_full_path if os.path.altsep is not None: expected = expected.replace(os.path.sep, os.path.altsep) self.assertEqual(expected, name)
[docs] def setUp(self): self.file_name = "temp.txt"
[docs] def tearDown(self): remove_file(mut.FileInfo(self.file_name))
[docs] def test_fi_are_not_equal(self): # arrange fi = mut.FileInfo(self.file_name) other = mut.FileInfo("a.txt") # act actual = fi != other # verify self.assertEqual(True, actual)
[docs] def test_fi_not_equal_to_other_type(self): # arrange fi = mut.FileInfo(self.file_name) other = object() # act actual = fi != other # verify self.assertEqual(True, actual)
[docs] def test_fi_not_equal_false(self): # arrange fi = mut.FileInfo(self.file_name) other = mut.FileInfo(self.file_name + ".json") # act actual = fi == other # verify self.assertEqual(False, actual)
[docs] def test_fi_equal_to_other_type(self): # arrange fi = mut.FileInfo(self.file_name) other = mut.AABB(1, 2, 3, 4) # act actual = fi == other # verify self.assertEqual(False, actual)
[docs] def test_fi_are_equal(self): # arrange fi = mut.FileInfo(self.file_name) other = mut.FileInfo(self.file_name) # act actual = fi == other # verify self.assertEqual(True, actual)
[docs] def test_fi_fullname(self): # arrange directory_full_path = os.path.join("subdir", "sub-sub-dir") file_name_and_path = os.path.join(directory_full_path, self.file_name) fi = mut.FileInfo(file_name_and_path) # act name = fi.full_name # verify expected = file_name_and_path if os.path.altsep is not None: expected = expected.replace(os.path.sep, os.path.altsep) self.assertEqual(expected, name)
[docs] def test_fi_fullname_case(self): # arrange directory_full_path = os.path.join("subDir", "SubSubdir") file_name_and_path = os.path.join(directory_full_path, self.file_name) fi = mut.FileInfo(file_name_and_path) # act name = fi.full_name # verify expected = file_name_and_path if os.path.altsep is not None: expected = expected.replace(os.path.sep, os.path.altsep) self.assertEqual(expected, name)
[docs] def test_fi_fullname_normpath(self): # arrange directory_full_path = "subDir/SubSubdir" file_name_and_path = directory_full_path + "\\" + self.file_name fi = mut.FileInfo(file_name_and_path) # act name = fi.full_name # verify expected = os.path.normpath(file_name_and_path) if os.path.altsep is not None: expected = expected.replace(os.path.sep, os.path.altsep) self.assertEqual(expected, name)
[docs] def test_str(self): # arrange aabb = mut.FileInfo(self.file_name) # act s = str(aabb) # verify self.assertTrue(len(s) > 0)
[docs] def test_repr(self): # arrange aabb = mut.FileInfo(self.file_name) # act s = aabb.__repr__() # verify self.assertTrue(len(s) > 0) self.assertEqual("<FileInfo('{0}')>".format(self.file_name), s)
[docs]class TestPolygon(unittest.TestCase): points = [[0, 0], [10, 0], [10, 10], [0, 10]]
[docs] def test_sign_positive(self): # arrange positive = 23 # act actual = mut.sign(positive) # verify self.assertEqual(mut.PolygonOrientation.Clockwise, actual)
[docs] def test_sign_negative(self): # arrange negative = -55 # act actual = mut.sign(negative) # verify self.assertEqual(mut.PolygonOrientation.CounterClockwise, actual)
[docs] def test_sign_zero(self): # arrange zero = 0.0 # act actual = mut.sign(zero) # verify self.assertEqual(zero, actual)
[docs] def test_signed_area_positive(self): # arrange # act actual = mut.get_signed_area_of_polygon(TestPolygon.points) # verify area = 100 self.assertEqual(area * mut.PolygonOrientation.CounterClockwise, actual)
[docs] def test_signed_area_negative(self): # arrange # act actual = mut.get_signed_area_of_polygon(reversed(TestPolygon.points)) # verify area = 100 self.assertEqual(area * mut.PolygonOrientation.Clockwise, actual)
[docs] def test_area_clockwise(self): # arrange # act actual = mut.get_area_of_polygon(TestPolygon.points) # verify area = 100 self.assertEqual(area, actual)
[docs] def test_area_counterclockwise(self): # arrange # act actual = mut.get_area_of_polygon(reversed(TestPolygon.points)) # verify area = 100 self.assertEqual(area, actual)
[docs] def test_get_orientation_counter_clockwise(self): # arrange # act actual = mut.get_orientation(TestPolygon.points) # verify self.assertEqual(mut.PolygonOrientation.CounterClockwise, actual)
[docs] def test_get_orientation_clockwise(self): # arrange # act actual = mut.get_orientation(reversed(TestPolygon.points)) # verify self.assertEqual(mut.PolygonOrientation.Clockwise, actual)
[docs]class FileInfoMock(mut.FileInfo): """ The mock object for the FileInfo class. :param file_path: The file path to store. :param exists_value: Bool, the value if the path exists. """ def __init__(self, file_path, exists_value): mut.FileInfo.__init__(self, file_path) self._captured_text = None self.open_args = None self.close_args = None self.exists_value = exists_value self.method_calls = [] # [(method_name, args), ] @property def exists(self): """ The exists property. :return: Returns the exists_value given in the constructor. """ return self.exists_value
[docs] def open(self, *args, **kwargs): """ Opens the file. This mocked method returns itself as file object. It saves the arguments in open_args = (args, kwargs) :param args: The passed arguments. :param kwargs: The passed keyword arguments. :return: Itself as file object. """ self.method_calls.append((FileInfoMock.open.__name__, args)) self.open_args = (args, kwargs) return self # def close(self, *args, **kwargs): # self.close_args = (args, kwargs)
[docs] def write(self, *args): """ Write something to the file like object. :param args: The data to write. This data is saved in _captured_text. """ self.method_calls.append((FileInfoMock.write.__name__, args)) self._captured_text = args
[docs] def read(self): """ Read the file like object. :return: Returns the contents of _captured_text (see write) """ self.method_calls.append((FileInfoMock.read.__name__, tuple())) return self._captured_text
[docs] def delete(self): """ Deletes the file. """ self.method_calls.append((FileInfoMock.delete.__name__, tuple())) # TODO: this would be more correct but breaks currently a test case (maybe it needs a rewrite?) # self.exists_value = False
def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass
[docs] def getvalue(self): """ Returns the contents of _captured_text. :return: Contents of _captured_text (see write and read methods). """ return self._captured_text
[docs]class TestFileInfoMock(unittest.TestCase):
[docs] def test_mock_exist_returns_true(self): # arrange sut = FileInfoMock("xxx", True) # act / verify self.assertTrue(sut.exists)
[docs] def test_mock_exist_returns_false(self): # arrange sut = FileInfoMock("yyy", False) # act / verify self.assertFalse(sut.exists)
[docs] def test_write_to_file(self): # arrange fi = FileInfoMock("out.path", False) f = fi.open(mut.FileMode.Write) data = u"hello" # act f.write(data) # verify self.assertTrue(data, f.getvalue()) # noinspection PyNoneFunctionAssignment
[docs] def test_read_from_file(self): # arrange fi = FileInfoMock("out.path", False) f = fi.open(mut.FileMode.Write) data = u"hello" f.write(data) # act actual = f.read() # verify self.assertTrue(data, actual)
[docs]def remove_file(file_info, logger_instance=logger): # noinspection PyBroadException """ Tries to remove the given file. It will log an error if the file could not be removed. :param logger_instance: The logger instance to use. Defaults to the module logger. :param file_info: The filename to be removed. """ try: file_info.delete() except Exception as ex: if file_info.exists: logger_instance.error("ex: failed to remove file " + file_info.name + " with exception " + str(ex)) finally: if file_info.exists: logger_instance.error("failed to remove file, it still exists: " + file_info.name)
[docs]class TestRemoveFile(unittest.TestCase):
[docs] def test_remove_existing_file(self): # arrange self.file_name = "temp1.txt" # TODO: revise this unittest, it should be using mut.FileInfo and a os_module_mock! file_info_mock = FileInfoMock(self.file_name, True) # act remove_file(file_info_mock) # verify self.assertEqual((FileInfoMock.delete.__name__, tuple()), file_info_mock.method_calls[0])
[docs] def test_remove_fails(self): # arrange # noinspection PyDocstring class FileInfoMockFailingDelete(FileInfoMock): def delete(self): raise Exception("Mocked delete failed") self.file_name = "temp2.txt" file_info_mock = FileInfoMockFailingDelete(self.file_name, True) logger_mock = LoggerMock() # act remove_file(file_info_mock, logger_mock) # verify self.assertTrue(logger_mock.messages[0][1].startswith("ex: failed to remove file " + self.file_name))
[docs] def test_remove_but_file_still_exists(self): # arrange self.file_name = "temp3.txt" # TODO: revise this unittest, it should be using mut.FileInfo and a os_module_mock! file_info_mock = FileInfoMock(self.file_name, True) logger_mock = LoggerMock() # act remove_file(file_info_mock, logger_mock) # verify self.assertTrue(logger_mock.messages[0][1].startswith("failed to remove file, it still exists: "))
[docs]class TestNeededDigitsFromValue(unittest.TestCase):
[docs] def test_zero(self): # arrange value = 0 # act num_digits = mut.get_needed_digits(value) # verify self.assertAlmostEqual(1, num_digits)
[docs] def test_value_9(self): # arrange value = 9 # act num_digits = mut.get_needed_digits(value) # verify self.assertAlmostEqual(1, num_digits)
[docs] def test_value_10(self): # arrange value = 10 # act num_digits = mut.get_needed_digits(value) # verify self.assertAlmostEqual(2, num_digits)
[docs] def test_value_100(self): # arrange value = 100 # act num_digits = mut.get_needed_digits(value) # verify self.assertAlmostEqual(3, num_digits)
[docs] def test_value_1000(self): # arrange value = 1000 # act num_digits = mut.get_needed_digits(value) # verify self.assertAlmostEqual(4, num_digits)
[docs] def test_value_10000(self): # arrange value = 10000 # act num_digits = mut.get_needed_digits(value) # verify self.assertAlmostEqual(5, num_digits)
[docs] def test_non_int_raises_TypeError(self): # arrange value = 45.234 # act / verify self.assertRaises(TypeError, mut.get_needed_digits, value)
[docs] def test_negative_values_raise_ValueError(self): # arrange value = -23 # act / verify self.assertRaises(ValueError, mut.get_needed_digits, value)
[docs]class JsonMock(object): """ The JsonMock. :param load_value: The value that the method load() will return. """ def __init__(self, load_value=None, loads_value=None): self.load_value = load_value self.loads_value = loads_value self.method_calls = [] # [(name, args), ]
[docs] def load(self, fp, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """ The load method. It would load a json from a file, but this mock just returns the load_value given through the constructor. All other arguments are stored, but ignored. :param fp: :param encoding: :param cls: :param object_hook: :param parse_float: :param parse_int: :param parse_constant: :param object_pairs_hook: :param kw: :return: Returns the value given by the constructor. """ self.method_calls.append((JsonMock.load.__name__, ( fp, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, kw))) return self.load_value
[docs] def loads(self, s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """ The load method. It would load a json from a string, but this mock just returns the loads_value given through the constructor. All other arguments are stored, but ignored. :param s: :param encoding: :param cls: :param object_hook: :param parse_float: :param parse_int: :param parse_constant: :param object_pairs_hook: :param kw: :return: Returns the value given by the constructor. """ self.method_calls.append((JsonMock.loads.__name__, ( s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, kw))) return self.loads_value
[docs]class TestJsonMock(unittest.TestCase):
[docs] def test_load(self): # arrange load_value = "blb" sut = JsonMock(load_value) # act actual = sut.load(None) # verify self.assertEqual(load_value, actual) self.assertEqual(JsonMock.load.__name__, sut.method_calls[0][0])
[docs] def test_loads(self): # arrange load_value = "blb" sut = JsonMock(loads_value=load_value) # act actual = sut.loads(None) # verify self.assertEqual(load_value, actual) self.assertEqual(JsonMock.loads.__name__, sut.method_calls[0][0]) # noinspection PyDocstring
[docs]class OsPathMock(object): """ The os.path module Mock. :param does_file_exist: The value that exists() should return. """ def __init__(self, does_file_exist, is_dir=False): self._does_file_exist = does_file_exist self.method_calls = [] # [(name, args), ] self._is_dir = is_dir
[docs] def dirname(self, path_name): self.method_calls.append((OsPathMock.dirname.__name__, (path_name,))) return self.split(path_name)[0]
[docs] def split(self, path_name): self.method_calls.append((OsPathMock.split.__name__, (path_name,))) return os.path.split(path_name)
[docs] def exists(self, path_name): self.method_calls.append((OsPathMock.exists.__name__, (path_name,))) return self._does_file_exist
[docs] def isdir(self, path_name): self.method_calls.append((OsPathMock.isdir.__name__, (path_name,))) return self._is_dir # noinspection PyDocstring
[docs]class OsModuleMock(object): """ The os module mock. :param path_module: The os.path module mock. :param list_dir: The list that should be returned when listdir() is called. """ def __init__(self, path_module, list_dir): self.path = path_module self._list_dir = list_dir self.method_calls = [] # [(name, args), ]
[docs] def remove(self, file_path): self.method_calls.append((OsModuleMock.remove.__name__, (file_path,)))
[docs] def listdir(self, directory): self.method_calls.append((OsModuleMock.listdir.__name__, (directory,))) return self._list_dir
[docs]class TestOsPathMock(unittest.TestCase):
[docs] def test_directory_name(self): # arrange sut = OsPathMock(True) directory = "dir/Dir" p = directory + "/file_name.png" # act actual = sut.dirname(p) # verify self.assertEqual(directory, actual) self.assertEqual((OsPathMock.dirname.__name__, (p,),), sut.method_calls[0])
[docs] def test_split(self): # arrange sut = OsPathMock(True) directory = "dir/Dir" f = "file_name.png" p = directory + "/" + f # act actual = sut.split(p) # verify self.assertEqual(directory, actual[0]) self.assertEqual(f, actual[1]) self.assertEqual((OsPathMock.split.__name__, (p,),), sut.method_calls[0])
[docs] def test_exists_false(self): # arrange sut = OsPathMock(False) # act arg = "bla" actual = sut.exists(arg) # verify self.assertFalse(actual) self.assertEqual((OsPathMock.exists.__name__, (arg,),), sut.method_calls[0])
[docs] def test_exists_true(self): # arrange sut = OsPathMock(True) arg = "bla" # act actual = sut.exists(arg) # verify self.assertTrue(actual) self.assertEqual((OsPathMock.exists.__name__, (arg,),), sut.method_calls[0])
[docs] def test_is_dir_true(self): # arrange sut = OsPathMock(True, True) arg = "bla" # act actual = sut.isdir(arg) # verify self.assertTrue(actual) self.assertEqual((OsPathMock.isdir.__name__, (arg,),), sut.method_calls[0])
[docs] def test_is_dir_false(self): # arrange sut = OsPathMock(True) arg = "bla" # act actual = sut.isdir(arg) # verify self.assertFalse(actual) self.assertEqual((OsPathMock.isdir.__name__, (arg,),), sut.method_calls[0])
[docs]class TestOsModuleMock(unittest.TestCase):
[docs] def test_listdir(self): # arrange pm = OsPathMock(False) list_dir = [1, 3, 5, 7] sut = OsModuleMock(pm, list_dir) arg = "bar" # act actual = sut.listdir(arg) # verify self.assertEqual(list_dir, actual) self.assertIs(list_dir, actual) self.assertEqual((OsModuleMock.listdir.__name__, (arg,),), sut.method_calls[0])
[docs] def test_remove(self): # arrange pm = OsPathMock(False) list_dir = [1, 3, 5, 7] sut = OsModuleMock(pm, list_dir) arg = "image.gif" # act sut.remove(arg) # verify self.assertEqual((OsModuleMock.remove.__name__, (arg,),), sut.method_calls[0])
[docs]class SpritesheetLib10SpecialMock(SpritesheetLib10): """ The special mock to log the call to 'load_spritesheet_from_sdef'. :param the_logger: The logger instance to use. """ def __init__(self, sprites, sdef, the_logger): SpritesheetLib10.__init__(self, the_logger) self.method_calls = [] # [(method_name, (args)), ] self.sprites = sprites self.sdef = sdef # noinspection PyDocstring
[docs] def load_sdef_from_file(self, *args): return self.sdef # noinspection PyDocstring
[docs] def load_spritesheet_from_sdef(self, *args): self.method_calls.append((self.load_spritesheet_from_sdef.__name__, args)) return self.sprites
[docs]class TestSpritesheetLibLoadingSpriteDefinition(unittest.TestCase):
[docs] def setUp(self): # arrange self.logger_mock = LoggerMock()
[docs] def test_load_sdef_from_file_existing(self): # arrange lib = mut.SpritesheetLib10(self.logger_mock) sdef_file_name = "test.sdef.png.sdef" sdef_file_info = FileInfoMock(sdef_file_name, True) sdef_file_info.write(TestData.SDEF_GRID_2X2_TEST) json_mock = JsonMock(TestData.SDEF_GRID_2X2_TEST) # act actual = lib.load_sdef_from_file(sdef_file_info, json_mock) # verify expected = TestData.SDEF_GRID_2X2_TEST self.maxDiff = None self.assertDictEqual(expected, actual)
[docs] def test_load_sdef_from_file_not_existing(self): # arrange lib = mut.SpritesheetLib10(self.logger_mock) sdef_file_name = "test.sdef.PNG.sdef" sdef_file_info = FileInfoMock(sdef_file_name, True) sdef_file_info.write(TestData.SDEF_GRID_2X2_TEST) json_mock = JsonMock(TestData.SDEF_GRID_2X2_TEST) # act / verify self.assertRaises(ValueError, lib.load_sdef_from_file, sdef_file_info, json_mock)
[docs] def test_load_sdef_from_file_raises(self): # arrange # noinspection PyDocstring class JsonMockRaising(JsonMock): def load(self, fp, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): JsonMock.load(self, fp, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook) raise ValueError("bla") lib = mut.SpritesheetLib10(self.logger_mock) sdef_file_name = "test-non-existing.png.sdef" sdef_file_info = FileInfoMock(sdef_file_name, True) sdef_file_info.write(TestData.SDEF_GRID_2X2_TEST) json_mock = JsonMockRaising(TestData.SDEF_GRID_2X2_TEST) # act / verify self.assertRaises(ValueError, lib.load_sdef_from_file, sdef_file_info, json_mock)
[docs] def test_load_spritesheet(self): # arrange sprites = {'001': 'bla', '002': 'blu'} sut = SpritesheetLib10SpecialMock(sprites, TestData.SDEF_GRID_2X2_TEST, self.logger_mock) image_path = "test.sdef.png" definition_file_info = FileInfo(image_path + ".sdef") # act actual = sut.load_spritesheet(definition_file_info) # verify that the method has been called self.assertEqual(sut.load_spritesheet_from_sdef.__name__, sut.method_calls[0][0]) # verify that the arguments where right sdef = sut.method_calls[0][1][0] self.assertEqual(TestData.SDEF_GRID_2X2_TEST, sdef) image_file_info = sut.method_calls[0][1][1] self.assertEqual(FileInfo(image_path), image_file_info) # verify return value self.assertDictEqual(sprites, actual)
[docs] def test_load_spritesheet_with_dir_path(self): # arrange sprites = {'001': 'bla', '002': 'blu'} sut = SpritesheetLib10SpecialMock(sprites, TestData.SDEF_GRID_2X2_TEST, self.logger_mock) image_path = "images\\walk\\test.sdef.png" definition_file_info = FileInfo(image_path + ".sdef") # act actual = sut.load_spritesheet(definition_file_info) # verify that the method has been called self.assertEqual(sut.load_spritesheet_from_sdef.__name__, sut.method_calls[0][0]) # verify that the arguments where right sdef = sut.method_calls[0][1][0] self.assertEqual(TestData.SDEF_GRID_2X2_TEST, sdef) image_file_info = sut.method_calls[0][1][1] self.assertEqual(FileInfo(image_path), image_file_info) # verify return value self.assertDictEqual(sprites, actual)
[docs] def test_load_spritesheet_sdef_is_replaced_correctly(self): # arrange sprites = {'001': 'bla', '002': 'blu'} sut = SpritesheetLib10SpecialMock(sprites, TestData.SDEF_GRID_2X2_TEST, self.logger_mock) image_path = os.path.normpath("images/walk/test.sdef.png") definition_file_info = FileInfo(image_path + ".sdef") # act actual = sut.load_spritesheet(definition_file_info) # verify that the method has been called self.assertEqual(sut.load_spritesheet_from_sdef.__name__, sut.method_calls[0][0]) # verify that the arguments where right sdef = sut.method_calls[0][1][0] self.assertEqual(TestData.SDEF_GRID_2X2_TEST, sdef) image_file_info = sut.method_calls[0][1][1] self.assertEqual(FileInfo(image_path), image_file_info) # verify return value self.assertDictEqual(sprites, actual)
[docs] def test_load_spritesheet_is_loaded_with_different_extension(self): # arrange sprites = {'001': 'bla', '002': 'blu'} sut = SpritesheetLib10SpecialMock(sprites, TestData.SDEF_GRID_2X2_TEST, self.logger_mock) image_path = "images\\walk\\test.sdef.png" definition_file_info = FileInfo(image_path + ".spr") # act actual = sut.load_spritesheet(definition_file_info) # verify that the method has been called self.assertEqual(sut.load_spritesheet_from_sdef.__name__, sut.method_calls[0][0]) # verify that the arguments where right sdef = sut.method_calls[0][1][0] self.assertEqual(TestData.SDEF_GRID_2X2_TEST, sdef) image_file_info = sut.method_calls[0][1][1] self.assertEqual(FileInfo(image_path), image_file_info) # verify return value self.assertDictEqual(sprites, actual)
def _create_pygame_module_mock(self): sprite_sheet_surf = PygameSurfaceMock([], [], "spritesheet") images = [sprite_sheet_surf] draw_rects = [PygameRectMock((1, 1), "draw_rect1"), PygameRectMock((1, 2), "draw_rect2"), PygameRectMock((1, 3), "draw_rect3"), PygameRectMock((1, 4), "draw_rect4")] image_mock = PygameImageModuleMock(images) draw_mock = PygameDrawModuleMock(draw_rects) modules = {PygameMock.IMAGE_MODULE_NAME: image_mock, PygameMock.DRAW_MODULE_NAME: draw_mock} mask1 = PygameSurfaceMock([], [PygameRectMock((1, 0), "mask_rect1")], "mask1") mask2 = PygameSurfaceMock([], [PygameRectMock((2, 0), "mask_rect2")], "mask2") mask3 = PygameSurfaceMock([], [PygameRectMock((3, 0), "mask_rect3")], "mask3") mask4 = PygameSurfaceMock([], [PygameRectMock((4, 0), "mask_rect4")], "mask4") blit_rects1 = [PygameRectMock((1, 1), "blit_rect1.1"), PygameRectMock((1, 2), "blit_rect1.2")] spr_image1 = PygameSurfaceMock(blit_rects1, [], "spr_img1") blit_rects2 = [PygameRectMock((2, 1), "blit_rect2.1"), PygameRectMock((2, 2), "blit_rect2.2")] spr_image2 = PygameSurfaceMock(blit_rects2, [], "spr_img2") blit_rects3 = [PygameRectMock((3, 1), "blit_rect3.1"), PygameRectMock((3, 2), "blit_rect3.2")] spr_image3 = PygameSurfaceMock(blit_rects3, [], "spr_img3") blit_rects4 = [PygameRectMock((4, 1), "blit_rect4.1"), PygameRectMock((4, 2), "blit_rect4.2")] spr_image4 = PygameSurfaceMock(blit_rects4, [], "spr_img4") surfaces = [mask1, spr_image1, mask2, spr_image2, mask3, spr_image3, mask4, spr_image4, ] rects = [PygameRectMock((1, 1), "rect1"), PygameRectMock((2, 2), "rect2"), PygameRectMock((3, 3), "rect3"), PygameRectMock((4, 4), "rect4")] pygame_mock = PygameMock(surfaces, rects, modules) return draw_mock, mask1, mask2, mask3, mask4, pygame_mock, rects, spr_image1, spr_image2, spr_image3, \ spr_image4, sprite_sheet_surf def _verify_pygame_module_mock_usage(self, actual, draw_mock, mask1, mask2, mask3, mask4, rects, spr_image1, spr_image2, spr_image3, spr_image4, sprite_sheet_surf): # verify that the right sprite images are returned act = [(spr.image, spr.anchor, spr.gid) for spr in actual] expected = [(spr_image1, [10, 10], 0), (spr_image2, [0, 0], 1), (spr_image3, [0, 0], 2), (spr_image4, [0, 0], 3), ] self.maxDiff = None self.assertEqual(expected, act) # verify that the right area is drawn to the sprites self.assertIs(rects[0], spr_image1.method_calls[0][1][2]) self.assertIs(rects[1], spr_image2.method_calls[0][1][2]) self.assertIs(rects[2], spr_image3.method_calls[0][1][2]) self.assertIs(rects[3], spr_image4.method_calls[0][1][2]) # verify that the right points are drawn as polygon (point list is in local coordinates) local_points_list = [[0, 0], [32, 0], [32, 32], [0, 32]] self.assertEqual((PygameDrawModuleMock.polygon.__name__, (mask1, (255, 255, 255, 255), local_points_list, 0)), draw_mock.method_calls[0]) self.assertEqual((PygameDrawModuleMock.polygon.__name__, (mask2, (255, 255, 255, 255), local_points_list, 0)), draw_mock.method_calls[1]) self.assertEqual((PygameDrawModuleMock.polygon.__name__, (mask3, (255, 255, 255, 255), local_points_list, 0)), draw_mock.method_calls[2]) self.assertEqual((PygameDrawModuleMock.polygon.__name__, (mask4, (255, 255, 255, 255), local_points_list, 0)), draw_mock.method_calls[3]) # verify that the right area is used to blit the sprites image self.assertEqual((PygameSurfaceMock.blit.__name__, (sprite_sheet_surf, (0, 0), rects[0], 0)), spr_image1.method_calls[0]) self.assertEqual((PygameSurfaceMock.blit.__name__, (sprite_sheet_surf, (0, 0), rects[1], 0)), spr_image2.method_calls[0]) self.assertEqual((PygameSurfaceMock.blit.__name__, (sprite_sheet_surf, (0, 0), rects[2], 0)), spr_image3.method_calls[0]) self.assertEqual((PygameSurfaceMock.blit.__name__, (sprite_sheet_surf, (0, 0), rects[3], 0)), spr_image4.method_calls[0])
[docs] def test_load_spritesheet_from_sdef(self): # arrange sdef = TestData.SDEF_GRID_2X2 image_file_info = FileInfoMock("spritesheet.png", True) logger_mock = LoggerMock() sut = SpritesheetLib10(logger_mock) draw_mock, mask1, mask2, mask3, mask4, pygame_mock, rects, spr_image1, spr_image2, spr_image3, spr_image4, \ sprite_sheet_surf = self._create_pygame_module_mock() # act actual = sut.load_spritesheet_from_sdef(sdef, image_file_info, pygame_module=pygame_mock) # verify self._verify_pygame_module_mock_usage(actual, draw_mock, mask1, mask2, mask3, mask4, rects, spr_image1, spr_image2, spr_image3, spr_image4, sprite_sheet_surf)
[docs] def test_load_spritesheet_from_sdef_and_surface(self): # arrange sdef = TestData.SDEF_GRID_2X2 logger_mock = LoggerMock() sut = SpritesheetLib10(logger_mock) draw_mock, mask1, mask2, mask3, mask4, pygame_mock, rects, spr_image1, spr_image2, spr_image3, spr_image4, \ sprite_sheet_surf = self._create_pygame_module_mock() # act actual = sut.load_spritesheet_from_sdef_and_surface(sdef, sprite_sheet_surf, pygame_module=pygame_mock) # verify self._verify_pygame_module_mock_usage(actual, draw_mock, mask1, mask2, mask3, mask4, rects, spr_image1, spr_image2, spr_image3, spr_image4, sprite_sheet_surf)
[docs] def test_get_image_name_from_sdef_name(self): # arrange logger_mock = LoggerMock() sut = SpritesheetLib10(logger_mock) image_file_name = "bla.png" sdef_file_name = image_file_name + ".grr" # act actual = sut.get_image_name_from_sdef_name(sdef_file_name) # verify self.assertEqual(image_file_name, actual)
[docs] def test_get_image_name_from_sdef_name_missing_extension(self): # arrange logger_mock = LoggerMock() sut = SpritesheetLib10(logger_mock) image_file_name = "bla" sdef_file_name = image_file_name + ".grr" # act / verify self.assertRaises(ValueError, sut.get_image_name_from_sdef_name, sdef_file_name)
[docs] def test_get_image_name_from_sdef(self): # arrange logger_mock = LoggerMock() sut = SpritesheetLib10(logger_mock) image_file_name = "sdef_name.png" sdef = sut.clone_sprite_definition(TestData.SDEF_GRID_2X2) sdef_file_name = image_file_name + ".sdef" sdef[SpritesheetLib10.ELEMENTS.FILENAME] = sdef_file_name # act actual = sut.get_image_name_from_sdef(sdef) # verify self.assertEqual(image_file_name, actual)
[docs] def test_get_image_name_from_sdef_missing_extension(self): # arrange logger_mock = LoggerMock() sut = SpritesheetLib10(logger_mock) image_file_name = "bla" sdef = sut.clone_sprite_definition(TestData.SDEF_GRID_2X2) sdef_file_name = image_file_name + ".sdef" sdef[SpritesheetLib10.ELEMENTS.FILENAME] = sdef_file_name # act / verify self.assertRaises(ValueError, sut.get_image_name_from_sdef, sdef)
[docs]class TestSpritesheetLibSaveToDisk(unittest.TestCase):
[docs] def setUp(self): self.logger_mock = LoggerMock() self.file_name_sdef = "temp_out.png.sdef" self.file_name_image = self.file_name_sdef
[docs] def test_image_is_written_to_disk(self): # arrange img_fi = FileInfoMock(self.file_name_sdef, False) import pygame img = pygame.Surface((10, 10)) sut = mut.SpritesheetLib10(self.logger_mock) pyg_image = PygameImageModuleMock([]) pyg_mod = PygameMock([], [], {PygameMock.IMAGE_MODULE_NAME: pyg_image}) # act sut.save_image_to_disk(img, img_fi, pygame_module=pyg_mod) # verify self.assertEqual(0, len(img_fi.method_calls)) self.assertEqual((PygameImageModuleMock.save.__name__, (img, self.file_name_image)), pyg_image.method_calls[0])
[docs] def test_image_is_deleted_if_exists_before_written_to_disk(self): # arrange img_fi = FileInfoMock(self.file_name_sdef, True) import pygame img = pygame.Surface((10, 10)) sut = mut.SpritesheetLib10(self.logger_mock) pyg_image = PygameImageModuleMock([]) pyg_mod = PygameMock([], [], {PygameMock.IMAGE_MODULE_NAME: pyg_image}) # act sut.save_image_to_disk(img, img_fi, pygame_module=pyg_mod) # verify # self.assertTrue(img_fi.exists) # self.assertTrue(os.path.getsize(img_fi.name) > 0) self.assertEqual((FileInfoMock.delete.__name__, ()), img_fi.method_calls[0]) self.assertEqual((PygameImageModuleMock.save.__name__, (img, self.file_name_image)), pyg_image.method_calls[0])
[docs] def test_sdef_is_written_to_disk(self): # arrange fi = FileInfoMock(self.file_name_image, False) sut = mut.SpritesheetLib10(self.logger_mock) sdef = TestData.SDEF_GRID_2X2 # act sut.save_sprite_definition_to_disk(sdef, fi) # verify # noinspection PyTypeChecker self.assertTrue(len(fi.getvalue()) > 0)
[docs] def test_sdef_is_deleted_before_written_to_disk(self): # arrange fi = FileInfoMock(self.file_name_image, True) sut = mut.SpritesheetLib10(self.logger_mock) sdef = TestData.SDEF_GRID_2X2 # act sut.save_sprite_definition_to_disk(sdef, fi) # verify # noinspection PyTypeChecker self.assertTrue(len(fi.getvalue()) > 0) self.assertEqual((FileInfoMock.delete.__name__, ()), fi.method_calls[0]) self.assertEqual((FileInfoMock.open.__name__, (mut.FileMode.WriteBinary, )), fi.method_calls[1]) # noinspection PyDocstring
[docs]class PygameImageModuleMock(object): """ The pygame image module mock. :param images: The images if loads. Must be provided in the order they are needed. """ def __init__(self, images): self.images = list(images) self.method_calls = [] # [(method_name, (args)), ]
[docs] def load(self, filename): self.method_calls.append((PygameImageModuleMock.load.__name__, (filename,))) return self.images.pop(0)
[docs] def save(self, surface, filename): self.method_calls.append((PygameImageModuleMock.save.__name__, (surface, filename,)))
[docs]class TestPygameImageModuleMock(unittest.TestCase):
[docs] def test_load(self): # arrange sut = PygameImageModuleMock([1, 2, 3]) # act actual1 = sut.load(345345) actual2 = sut.load(1234) # verify self.assertEqual(1, actual1) self.assertEqual(2, actual2) self.assertEqual((PygameImageModuleMock.load.__name__, (345345,)), sut.method_calls[0]) self.assertEqual((PygameImageModuleMock.load.__name__, (1234,)), sut.method_calls[1])
[docs] def test_save(self): # arrange sut = PygameImageModuleMock([]) surf = object() image_name = "whatever" # act sut.save(surf, image_name) # verify self.assertEqual((PygameImageModuleMock.save.__name__, (surf, image_name)), sut.method_calls[0]) # noinspection PyDocstring
[docs]class PygameDrawModuleMock(object): """ The pygame draw module mock. :param rects: The rects returned by the draw methods. They have to be in the order they are needed. """ def __init__(self, rects): self.method_calls = [] # [(method_name, (args)), ] self.rects = list(rects)
[docs] def polygon(self, surface, color, pointlist, width=0): self.method_calls.append((PygameDrawModuleMock.polygon.__name__, (surface, color, pointlist, width))) return self.rects.pop(0)
[docs]class TestPygameDrawModuleMock(unittest.TestCase):
[docs] def test_polygon(self): # arrange sut = PygameDrawModuleMock([1, 2, 3]) surf = 1 color = "black" pointlist = "points" width = 3 # act actual1 = sut.polygon(surf, color, pointlist, width) actual2 = sut.polygon(surf, color, pointlist) # verify self.assertEqual(1, actual1) self.assertEqual(2, actual2) self.assertEqual((PygameDrawModuleMock.polygon.__name__, (surf, color, pointlist, width,)), sut.method_calls[0]) self.assertEqual((PygameDrawModuleMock.polygon.__name__, (surf, color, pointlist, 0)), sut.method_calls[1]) # noinspection PyDocstring
[docs]class PygameSurfaceMock(object): """ The pygame surface mock. :param blit_rects: The rects returned by the blit method. :param fill_rects: The rects returned by the fill method. :param name: The name of the surface, more of an identifier, makes it easier to match the correct surface mocks. """ def __init__(self, blit_rects, fill_rects, name): self.method_calls = [] # [(method_name, (args)), ] self.blit_rects = list(blit_rects) self.fill_rects = list(fill_rects) self.name = name
[docs] def blit(self, source, destination, area=None, special_flags=0): self.method_calls.append((PygameSurfaceMock.blit.__name__, (source, destination, area, special_flags))) return self.blit_rects.pop(0)
[docs] def fill(self, color, rect=None, special_flags=0): self.method_calls.append((PygameSurfaceMock.fill.__name__, (color, rect, special_flags))) return self.fill_rects.pop(0)
def __str__(self): return "<{0}.{1}['{2}']>".format(self.__module__, self.__class__.__name__, self.name) def __repr__(self): return str(self)
[docs]class TestPygameSurfaceMock(unittest.TestCase):
[docs] def test_name_str(self): # arrange name = "mock1" sut = PygameSurfaceMock([], [], name) # act actual = repr(sut) # verify expected = "<{0}.{1}['{2}']>".format(PygameSurfaceMock.__module__, PygameSurfaceMock.__name__, name) self.assertEqual(expected, actual)
[docs] def test_name_string(self): # arrange name = "mock1" sut = PygameSurfaceMock([], [], name) # act actual = str(sut) # verify expected = "<{0}.{1}['{2}']>".format(PygameSurfaceMock.__module__, PygameSurfaceMock.__name__, name) self.assertEqual(expected, actual)
[docs] def test_blit(self): # arrange sut = PygameSurfaceMock([1, 2, 3], [10, 11, 12], "mock1") source = "source" destination = "destination" area = "area" special_flags = 42 # act actual1 = sut.blit(source, destination, area, special_flags) actual2 = sut.blit(source, destination) # verify self.assertEqual(1, actual1) self.assertEqual(2, actual2) self.assertEqual((PygameSurfaceMock.blit.__name__, (source, destination, area, special_flags)), sut.method_calls[0]) self.assertEqual((PygameSurfaceMock.blit.__name__, (source, destination, None, 0)), sut.method_calls[1])
[docs] def test_fill(self): # arrange sut = PygameSurfaceMock([], [1, 2, 3], "mock1") color = 33 rect = "R" special_flags = 42 # act actual_rect = sut.fill(color, rect, special_flags) # verify self.assertEqual(1, actual_rect) self.assertEqual((PygameSurfaceMock.fill.__name__, (color, rect, special_flags)), sut.method_calls[0]) # noinspection PyDocstring
[docs]class PygameRectMock(object): """ The pygame rect mock. :param size: The size of the rect. :param name: The name of the rect, makes matching rect mock instances easier. """ def __init__(self, size, name): self.property_calls = [] # [(prop_name, 'set'|'get', args), ] self._size = size self.name = name @property def size(self): self.property_calls.append(("size", "get", tuple())) return self._size @size.setter def size(self, value): self.property_calls.append(("size", "set", tuple(value))) self._size = value def __str__(self): return "<{0}.{1}['{2}']>".format(self.__module__, self.__class__.__name__, self.name) def __repr__(self): return str(self)
[docs]class TestPygameRectMock(unittest.TestCase):
[docs] def test_name_str(self): # arrange name = "mock1" sut = PygameRectMock([], name) # act actual = repr(sut) # verify expected = "<{0}.{1}['{2}']>".format(PygameRectMock.__module__, PygameRectMock.__name__, name) self.assertEqual(expected, actual)
[docs] def test_name_string(self): # arrange name = "mock1" sut = PygameRectMock([], name) # act actual = str(sut) # verify expected = "<{0}.{1}['{2}']>".format(PygameRectMock.__module__, PygameRectMock.__name__, name) self.assertEqual(expected, actual)
[docs] def test_get_size_property(self): # arrange w = 14 h = 42 sut = PygameRectMock((w, h), "rect_mock1") # act actual = sut.size # verify self.assertEqual((w, h), actual) self.assertEqual(("size", "get", tuple()), sut.property_calls[0])
[docs] def test_set_size_property(self): # arrange w = 14 h = 42 sut = PygameRectMock((1, 2), "rect_mock1") # act sut.size = (w, h) actual = sut.size # verify self.assertEqual((w, h), actual) self.assertEqual(("size", "set", tuple((w, h))), sut.property_calls[0]) # noinspection PyDocstring
[docs]class PygameMock(object): """ The pygame module mock. :param surfaces: The surfaces that should be returned by calls to pygame.Surface(). :param rects: The rects that should be returned by calls to pygame.Rect(). :param modules: The modules present as a dictionary, e.g. {PygameMock.IMAGE_MODULE_NAME: image_module_mock} """ IMAGE_MODULE_NAME = "image" DRAW_MODULE_NAME = "draw" # constants BLEND_RGBA_MULT = 1 SRCALPHA = 2 def __init__(self, surfaces, rects, modules=None): if not modules: modules = {} self.method_calls = [] # [(method_name, (args)), ] self.property_calls = [] # [(property_name, 'set'|'get', args), ] self.surfaces = list(surfaces) self.rects = list(rects) self._image = None if self.IMAGE_MODULE_NAME in modules: self._image = modules[self.IMAGE_MODULE_NAME] self._draw = None if self.DRAW_MODULE_NAME in modules: self._draw = modules[self.DRAW_MODULE_NAME] @property def image(self): self.property_calls.append((self.IMAGE_MODULE_NAME, "get", tuple())) return self._image @property def draw(self): self.property_calls.append((self.DRAW_MODULE_NAME, "get", tuple())) return self._draw # noinspection PyPep8Naming
[docs] def Surface(self, size, flags=0, depth=0, masks=None): # surf = PygameSurfaceMock([], [], "Surface" + str(len(self.method_calls))) # self.method_calls.append((PygameMock.Surface.__name__, (size, flags, depth, masks), surf)) # return surf self.method_calls.append((PygameMock.Surface.__name__, (size, flags, depth, masks))) return self.surfaces.pop(0) # noinspection PyPep8Naming
[docs] def Rect(self, left, top=None, width=None, height=None): self.method_calls.append((PygameMock.Rect.__name__, (left, top, width, height))) return self.rects.pop(0)
[docs]class TestPygameMock(unittest.TestCase):
[docs] def test_image_module_retrieval(self): # arrange images = ["spritesheet"] # draw_rects = [] image_module_mock = PygameImageModuleMock(images) modules = {PygameMock.IMAGE_MODULE_NAME: image_module_mock, } surfaces = [] rects = [] sut = PygameMock(surfaces, rects, modules) # act actual_image_module = sut.image # verify self.assertIs(image_module_mock, actual_image_module) self.assertEqual(("image", "get", tuple()), sut.property_calls[0])
[docs] def test_draw_module_retrieval(self): # arrange draw_rects = ["rects"] draw_module_mock = PygameDrawModuleMock(draw_rects) modules = {PygameMock.DRAW_MODULE_NAME: draw_module_mock} surfaces = [] rects = [] sut = PygameMock(surfaces, rects, modules) # act actual_draw_module = sut.draw # verify self.assertIs(draw_module_mock, actual_draw_module) self.assertEqual(("draw", "get", tuple()), sut.property_calls[0])
[docs] def test_surface_creation(self): # arrange blit_rects = [] fill_rects = [] surf1 = PygameSurfaceMock(blit_rects, fill_rects, "surf1") surf2 = PygameSurfaceMock(blit_rects, fill_rects, "surf2") surfaces = [surf1, surf2] rects = [] sut = PygameMock(surfaces, rects) size = (2, 3) # act actual = sut.Surface(size) actual2 = sut.Surface(size) # verify self.assertIs(surf1, actual) self.assertIs(surf2, actual2) self.assertEqual((PygameMock.Surface.__name__, (size, 0, 0, None)), sut.method_calls[0])
[docs] def test_rect_creation(self): # arrange surfaces = [] size = (2, 3) rect1 = PygameRectMock(size, "rect_mock1") rect2 = PygameRectMock(size, "rect_mock2") rects = [rect1, rect2] sut = PygameMock(surfaces, rects) x = 1 y = 2 w = 5 h = 7 # act actual = sut.Rect(x, y, w, h) actual2 = sut.Rect(x, y, w, h) # verify self.assertIs(rect1, actual) self.assertIs(rect2, actual2) self.assertEqual((PygameMock.Rect.__name__, (x, y, w, h)), sut.method_calls[0])
[docs]class TestSpritesList(unittest.TestCase):
[docs] def setUp(self): self.sprites = mut.SpritesList() gid = 0 for y in range(4): for x in range(4): properties = {SpritesheetLib10.PROPERTIES.COLUMN: x, SpritesheetLib10.PROPERTIES.ROW: y} self.sprites.append(mut.Sprite(PygameSurfaceMock([], [], str(gid)), [], gid, properties)) gid += 1
[docs] def test_create_empty_instance(self): # act actual = mut.SpritesList() # verify self.assertEqual(0, len(actual))
[docs] def test_create_instance_with_entries(self): # arrange data = [1, 2, 3, 4] # act actual = mut.SpritesList(data) # verify self.assertEqual(data, actual)
[docs] def test_get_cols(self): # arrange expected = [ [self.sprites[0], self.sprites[4], self.sprites[8], self.sprites[12]], [self.sprites[1], self.sprites[5], self.sprites[9], self.sprites[13]], [self.sprites[2], self.sprites[6], self.sprites[10], self.sprites[14]], [self.sprites[3], self.sprites[7], self.sprites[11], self.sprites[15]], ] # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act cols = self.sprites.get_columns() # verify self.maxDiff = None self.assertListEqual(expected, cols)
[docs] def test_get_cols_with_gap(self): # arrange expected = [ [self.sprites[0], self.sprites[4], self.sprites[8], self.sprites[12]], [self.sprites[5], self.sprites[9], self.sprites[13]], [self.sprites[2], self.sprites[10], self.sprites[14]], [self.sprites[3], self.sprites[7], self.sprites[11], self.sprites[15]], ] self.sprites[1].properties = {} self.sprites[6].properties = {} # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act cols = self.sprites.get_columns() # verify self.maxDiff = None self.assertEqual(expected, cols)
[docs] def test_get_cols_fail_while_row_prop_is_missing(self): # arrange del self.sprites[5].properties[SpritesheetLib10.PROPERTIES.ROW] # act / verify self.assertRaises(mut.SpriteListException, self.sprites.get_columns)
[docs] def test_get_rows(self): # arrange expected = [ [self.sprites[0], self.sprites[1], self.sprites[2], self.sprites[3]], [self.sprites[4], self.sprites[5], self.sprites[6], self.sprites[7]], [self.sprites[8], self.sprites[9], self.sprites[10], self.sprites[11]], [self.sprites[12], self.sprites[13], self.sprites[14], self.sprites[15]], ] # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act rows = self.sprites.get_rows() # verify self.assertEqual(expected, rows)
[docs] def test_get_row_with_gap(self): # arrange expected = [ [self.sprites[0], self.sprites[2], self.sprites[3]], [self.sprites[4], self.sprites[5], self.sprites[7]], [self.sprites[8], self.sprites[9], self.sprites[10], self.sprites[11]], [self.sprites[12], self.sprites[13], self.sprites[14], self.sprites[15]], ] self.sprites[1].properties = {} self.sprites[6].properties = {} # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act rows = self.sprites.get_rows() # verify self.assertEqual(expected, rows)
[docs] def test_get_rows_fail_while_col_prop_is_missing(self): # arrange del self.sprites[5].properties[SpritesheetLib10.PROPERTIES.COLUMN] # act / verify self.assertRaises(mut.SpriteListException, self.sprites.get_rows)
[docs] def test_get_grouped_by_property(self): # arrange property_name = 'count' self.sprites[0].properties[property_name] = 1 self.sprites[1].properties[property_name] = 2 self.sprites[2].properties[property_name] = 2 self.sprites[3].properties[property_name] = 3 self.sprites[4].properties[property_name] = 3 self.sprites[5].properties[property_name] = 3 self.sprites[6].properties[property_name] = 4 self.sprites[7].properties[property_name] = 4 self.sprites[8].properties[property_name] = 4 self.sprites[9].properties[property_name] = 4 self.sprites[10].properties[property_name] = 5 self.sprites[11].properties[property_name] = 5 self.sprites[12].properties[property_name] = 5 self.sprites[13].properties[property_name] = 5 self.sprites[14].properties[property_name] = 5 expected = { 1: [self.sprites[0], ], 2: [self.sprites[1], self.sprites[2], ], 3: [self.sprites[3], self.sprites[4], self.sprites[5], ], 4: [self.sprites[6], self.sprites[7], self.sprites[8], self.sprites[9], ], 5: [self.sprites[10], self.sprites[11], self.sprites[12], self.sprites[13], self.sprites[14], ], None: [self.sprites[15], ], } for k, v in expected.items(): v.sort(key=lambda spr: id(spr)) # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act actual = self.sprites.get_grouped_by_property(property_name, lambda spr: id(spr)) # verify self.maxDiff = None self.assertDictEqual(expected, actual)
def _setup_facing_and_action_properties(self): self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'up' self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'still' self.sprites[1].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'up' self.sprites[1].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[2].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'up' self.sprites[2].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[3].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'up' self.sprites[3].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[4].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'left' self.sprites[4].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'still' self.sprites[5].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'left' self.sprites[5].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[6].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'left' self.sprites[6].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[7].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'left' self.sprites[7].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[8].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'r' self.sprites[8].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'still' self.sprites[9].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'r' self.sprites[9].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[10].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'r' self.sprites[10].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[11].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'r' self.sprites[11].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[12].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'd' self.sprites[12].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'still' self.sprites[13].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'd' self.sprites[13].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[14].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'd' self.sprites[14].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk' self.sprites[15].properties[mut.SpritesheetLib10.PROPERTIES.FACING] = 'd' self.sprites[15].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] = 'walk'
[docs] def test_get_grouped_by_facing_and_action(self): # arrange self._setup_facing_and_action_properties() expected = { 'up': {'still': [self.sprites[0]], 'walk': [self.sprites[1], self.sprites[2], self.sprites[3], ]}, 'r': {'still': [self.sprites[8]], 'walk': [self.sprites[9], self.sprites[10], self.sprites[11], ]}, 'd': {'still': [self.sprites[12]], 'walk': [self.sprites[13], self.sprites[14], self.sprites[15], ]}, 'left': {'still': [self.sprites[4]], 'walk': [self.sprites[5], self.sprites[6], self.sprites[7], ]}, } # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act actual = self.sprites.get_grouped_by_facing_and_action() # verify self.maxDiff = None self.assertDictEqual(expected, actual)
[docs] def test_get_grouped_by_facing_and_action_some_missing(self): # arrange self._setup_facing_and_action_properties() del self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.FACING] del self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] del self.sprites[1].properties[mut.SpritesheetLib10.PROPERTIES.FACING] expected = { 'up': {'walk': [self.sprites[2], self.sprites[3], ]}, 'r': {'still': [self.sprites[8]], 'walk': [self.sprites[9], self.sprites[10], self.sprites[11], ]}, 'd': {'still': [self.sprites[12]], 'walk': [self.sprites[13], self.sprites[14], self.sprites[15], ]}, 'left': {'still': [self.sprites[4]], 'walk': [self.sprites[5], self.sprites[6], self.sprites[7], ]}, None: {None: [self.sprites[0]], 'walk': [self.sprites[1]]}, } # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act actual = self.sprites.get_grouped_by_facing_and_action() # verify self.maxDiff = None self.assertDictEqual(expected, actual)
[docs] def test_get_grouped_by_facing_and_action_fails_missing_action(self): # arrange self._setup_facing_and_action_properties() del self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act / verify self.assertRaises(mut.SpriteListException, self.sprites.get_grouped_by_facing_and_action)
[docs] def test_get_grouped_by_action_and_facing(self): # arrange self._setup_facing_and_action_properties() expected = { 'walk': {'up': [self.sprites[1], self.sprites[2], self.sprites[3], ], 'r': [self.sprites[9], self.sprites[10], self.sprites[11], ], 'd': [self.sprites[13], self.sprites[14], self.sprites[15], ], 'left': [self.sprites[5], self.sprites[6], self.sprites[7], ]}, 'still': {'up': [self.sprites[0], ], 'r': [self.sprites[8], ], 'd': [self.sprites[12], ], 'left': [self.sprites[4], ]}, } # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act actual = self.sprites.get_grouped_by_action_and_facing() # verify self.maxDiff = None self.assertDictEqual(expected, actual)
[docs] def test_get_grouped_by_action_and_facing_some_missing(self): # arrange self._setup_facing_and_action_properties() del self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.FACING] del self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] del self.sprites[1].properties[mut.SpritesheetLib10.PROPERTIES.ACTION] expected = { 'walk': {'up': [self.sprites[2], self.sprites[3], ], 'r': [self.sprites[9], self.sprites[10], self.sprites[11], ], 'd': [self.sprites[13], self.sprites[14], self.sprites[15], ], 'left': [self.sprites[5], self.sprites[6], self.sprites[7], ]}, 'still': {'r': [self.sprites[8], ], 'd': [self.sprites[12], ], 'left': [self.sprites[4], ]}, None: {None: [self.sprites[0]], 'up': [self.sprites[1]], } } # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act actual = self.sprites.get_grouped_by_action_and_facing() # verify self.maxDiff = None self.assertDictEqual(expected, actual)
[docs] def test_get_grouped_by_action_and_facing_fails_missing_facing(self): # arrange self._setup_facing_and_action_properties() del self.sprites[0].properties[mut.SpritesheetLib10.PROPERTIES.FACING] # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act / verify self.assertRaises(mut.SpriteListException, self.sprites.get_grouped_by_action_and_facing)
[docs] def test_get_gid_slice(self): # arrange expected = [self.sprites[4], self.sprites[5], self.sprites[6], self.sprites[7], self.sprites[8], ] # random sprite order to ensure right order in the result random.shuffle(self.sprites) # act actual = self.sprites.get_gid_slice(4, 8) # verify self.assertEqual(expected, actual)
@ddtd.use_data_driven_testing_decorators
[docs]class TestSpritesheetLib10UpdateProperties(unittest.TestCase):
[docs] def setUp(self): self.logger_mock = LoggerMock() self.data = SpritesheetLib10(self.logger_mock).clone_sprite_definition(TestData.SDEF_GRID_2X2)
[docs] def test_update_properties_need_key_mode(self): # arrange properties = {1: 'bla'} sut = SpritesheetLib10(self.logger_mock) # act with self.assertRaises(KeyError) as cm: sut.update_sprite_properties(TestData.SDEF_GRID_2X2, properties) # verify message = str(cm.exception) self.assertTrue(V1PROPERTIES.MODE in message)
@ddtd.test_case(V1PROPERTIES.MODE_UPDATE, test_name="mode_update") @ddtd.test_case(V1PROPERTIES.MODE_UPDATE_STRICT, test_name="mode_update_strict") @ddtd.test_case(V1PROPERTIES.MODE_EXTEND, test_name="mode_extend") @ddtd.test_case(V1PROPERTIES.MODE_EXTEND_STRICT, test_name="mode_extend_strict") def test_properties_mode_only_accepts_valid_mode_value(self, mode): # arrange self._add_bla_bla_property() properties = { V1PROPERTIES.MODE: mode, 0: {'bla': 'zzz', 'BLU': 'blu'}, 1: {'bla': 'zzz'}, 2: {'bla': 'zzz'}, 3: {'bla': 'zzz'}, } sut = SpritesheetLib10(self.logger_mock) # act sut.update_sprite_properties(self.data, properties)
[docs] def test_properties_mode_wrong_value_raises_value_error(self): # arrange properties = { V1PROPERTIES.MODE: 'wrong_value', } sut = SpritesheetLib10(self.logger_mock) # act / verify self.assertRaises(ValueError, sut.update_sprite_properties, TestData.SDEF_GRID_2X2, properties)
def _add_bla_bla_property(self, value='bla'): for sprite in self.data[V1ELEMENTS.SPRITES]: sprite[V1ELEMENTS.PROPERTIES] = {'bla': value}
[docs] def test_mode_update_strict_missing_key_raise(self): # arrange self._add_bla_bla_property() new_value = 'zzz' properties = { V1PROPERTIES.MODE: V1PROPERTIES.MODE_UPDATE_STRICT, 0: {'bla': new_value, 'new': 'new_val'}, # 1: {'bla': new_value}, missing # 2: {'bla': new_value}, missing # 3: {'bla': new_value}, missing } sut = SpritesheetLib10(self.logger_mock) # act / verify self.assertRaises(KeyError, sut.update_sprite_properties, self.data, properties)
[docs] def test_mode_update_strict_no_missing_key(self): # arrange self._add_bla_bla_property() new_value = 'zzz' bla = 'bla' properties = { V1PROPERTIES.MODE: V1PROPERTIES.MODE_UPDATE_STRICT, 0: {bla: new_value, 'new': 'new-val'}, 1: {bla: new_value}, 2: {bla: new_value}, 3: {bla: new_value}, } sut = SpritesheetLib10(self.logger_mock) expected = sut.clone_sprite_definition(self.data) expected[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES][bla] = new_value expected[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES]['new'] = 'new-val' expected[V1ELEMENTS.SPRITES][1][V1ELEMENTS.PROPERTIES][bla] = new_value expected[V1ELEMENTS.SPRITES][2][V1ELEMENTS.PROPERTIES][bla] = new_value expected[V1ELEMENTS.SPRITES][3][V1ELEMENTS.PROPERTIES][bla] = new_value # act sut.update_sprite_properties(self.data, properties) # verify self.maxDiff = None self.assertDictEqual(expected, self.data)
[docs] def test_mode_update_missing_key_does_not_raise(self): # arrange # sprite definition self._add_bla_bla_property() self.data[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES]['blu'] = 'xxx' # properties properties = { V1PROPERTIES.MODE: V1PROPERTIES.MODE_UPDATE, 0: {'bla': 'zzz', 'ble': 'ble'}, } sut = SpritesheetLib10(self.logger_mock) expected = sut.clone_sprite_definition(self.data) expected[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES]['bla'] = 'zzz' expected[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES]['ble'] = 'ble' # act sut.update_sprite_properties(self.data, properties) # verify self.maxDiff = None self.assertDictEqual(expected, self.data)
[docs] def test_mode_extend(self): # arrange self._add_bla_bla_property() properties = { V1PROPERTIES.MODE: V1PROPERTIES.MODE_EXTEND, 0: {'bla': 'zzz', 'blu': 'xxx'}, } sut = SpritesheetLib10(self.logger_mock) expected = sut.clone_sprite_definition(self.data) expected[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES][u'blu'] = u'xxx' # act sut.update_sprite_properties(self.data, properties) # verify self.maxDiff = None self.assertDictEqual(expected, self.data)
[docs] def test_mode_extend_strict_ok(self): # arrange self._add_bla_bla_property() properties = { V1PROPERTIES.MODE: V1PROPERTIES.MODE_EXTEND_STRICT, 0: {'bla': 'zzz', 'blu': 'xxx'}, 1: {'bla': 'zzz', 'blu': 'xxx'}, 2: {'bla': 'zzz', 'blu': 'xxx'}, 3: {'bla': 'zzz', 'blu': 'xxx'}, } sut = SpritesheetLib10(self.logger_mock) expected = sut.clone_sprite_definition(self.data) expected[V1ELEMENTS.SPRITES][0][V1ELEMENTS.PROPERTIES][u'blu'] = u'xxx' expected[V1ELEMENTS.SPRITES][1][V1ELEMENTS.PROPERTIES][u'blu'] = u'xxx' expected[V1ELEMENTS.SPRITES][2][V1ELEMENTS.PROPERTIES][u'blu'] = u'xxx' expected[V1ELEMENTS.SPRITES][3][V1ELEMENTS.PROPERTIES][u'blu'] = u'xxx' # act sut.update_sprite_properties(self.data, properties) # verify self.maxDiff = None self.assertDictEqual(expected, self.data)
[docs] def test_mode_extend_strict_raises_on_missing_gid(self): # arrange self._add_bla_bla_property() properties = { V1PROPERTIES.MODE: V1PROPERTIES.MODE_EXTEND_STRICT, 0: {'bla': 'zzz', 'blu': 'xxx'}, # 1: {'bla': 'zzz', 'blu': 'xxx'}, missing gid! 2: {'bla': 'zzz', 'blu': 'xxx'}, 3: {'bla': 'zzz', 'blu': 'xxx'}, } sut = SpritesheetLib10(self.logger_mock) # act / verify self.assertRaises(KeyError, sut.update_sprite_properties, self.data, properties)
if __name__ == '__main__': # pragma: no cover unittest.main()