# -*- 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
"""
from __future__ import print_function
import logging
import unittest
import sys
sys.path.insert(0, "../bin/")
import warnings
warnings.simplefilter('default') # make warnings visible for developers
import spritesheet_mask_generator as mut # module under test
from spritesheetlib import FileInfo, FileMode
from tests.test_spritesheetlib import LoggerMock, get_method_names, FileInfoMock, TestData, remove_file, JsonMock
import tests.datadriventestingdecorators as ddtd
__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 @ 2015"
__credits__ = ["DR0ID"] # list of contributors
__maintainer__ = "DR0ID"
__license__ = "New BSD license"
if mut.__version_info__ != __version_info__:
raise Exception("version numbers do not match!") # pragma: no cover
[docs]class SpritesheetLib10Mock(mut.SpritesheetLib10):
"""
This is a mock object for the SpritesheetLib10 class.
:param logger_instance: The logger instance to use.
"""
def __init__(self, logger_instance):
mut.SpritesheetLib10.__init__(self, logger_instance)
self.logger = logger_instance
self.method_calls = [] # [(method_name, (args)), ]
[docs] def create_grid(self, *args):
# import inspect
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.create_grid.__name__, args))
# number_of_args = len(inspect.getargspec(mut.SpritesheetLib.create_grid).args) - 1 # remove 'self'
# if number_of_args == len(args) or number_of_args - 1 == len(args):
# return SpritesheetLib.create_grid(self, *args)
return TestData.SDEF_GRID_2X2
[docs] def load_sdef_from_file(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.load_sdef_from_file.__name__, args))
return TestData.SDEF_GRID_2X2
[docs] def adjust_spacing(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.adjust_spacing.__name__, args))
[docs] def adjust_margin(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.adjust_margin.__name__, args))
[docs] def create_image(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.create_image.__name__, args))
[docs] def save_sprite_definition_to_disk(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.save_sprite_definition_to_disk.__name__, args))
[docs] def save_image_to_disk(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
"""
self.method_calls.append((self.save_image_to_disk.__name__, args))
[docs] def is_sprite_def_valid(self, *args):
"""
Mocked method, just stores the call with arguments for later checks.
:param args: The passed in arguments.
:return: Returns always True.
"""
self.method_calls.append((self.is_sprite_def_valid.__name__, args))
return True
[docs] def update_sprite_properties(self, *args):
"""
Updates the properties of the sprites.
:param args: The passed in arguments.
"""
self.method_calls.append((self.update_sprite_properties.__name__, args))
@ddtd.use_data_driven_testing_decorators
[docs]class TestSpritesheetLib10Mock(unittest.TestCase):
@ddtd.test_case_from_generator(get_method_names, SpritesheetLib10Mock(LoggerMock()))
def test_method_call_is_logged(self, method_name):
# arrange
logger_mock = LoggerMock()
sut = SpritesheetLib10Mock(logger_mock)
arg = 1
# act
getattr(sut, method_name)(arg)
# verify
self.assertEqual((method_name, (arg,)), sut.method_calls[0])
class _SpriteSheetMaskGeneratorCommandsMock(mut.SpriteSheetMaskGenerator):
"""
This is a mock object that only mocks the call to save_to_disk (see its doc string for details).
"""
def __init__(self, spritesheet_lib, logger, json_module=None):
"""
The _SpriteSheetMaskGeneratorCommandsMock.
:param spritesheet_lib: The spritesheetlib instance to use.
:param logger: The logger instance to use.
:param json_module: The json module to use. Only used to mock json module.
"""
mut.SpriteSheetMaskGenerator.__init__(self, spritesheet_lib, logger, json_module)
self.method_calls = []
def save_to_disk(self, *args):
"""
The save_to_disk mocked method. It will store the method call and if the number of arguments are equal, call
the save_to_disk method of SpriteSheetMaskGenerator.
:param args: The passed arguments
"""
import inspect
self.method_calls.append((self.save_to_disk.__name__, args))
number_of_args = len(inspect.getargspec(mut.SpriteSheetMaskGenerator.save_to_disk).args) - 1 # remove 'self'
if number_of_args == len(args) or number_of_args - 1 == len(args):
mut.SpriteSheetMaskGenerator.save_to_disk(self, *args)
@ddtd.use_data_driven_testing_decorators
[docs]class SSMGCommandsMockTests(unittest.TestCase):
@ddtd.test_case_from_generator(get_method_names,
_SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(LoggerMock()),
LoggerMock()))
def test_method_call_is_logged(self, method_name):
# arrange
logger_mock = LoggerMock()
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(logger_mock), logger_mock)
arg = 1
# act
getattr(sut, method_name)(arg)
# verify
self.assertEqual((method_name, (arg,)), sut.method_calls[0])
# class SpritesheetMaskGeneratorMock(mut.SpriteSheetMaskGenerator):
# """
# The SpritesheetMaskGeneratorMock.
# :param lib:
# :param logger:
# """
#
# def __init__(self, lib, logger):
# mut.SpriteSheetMaskGenerator.__init__(self, lib, logger)
# self.recorded_method_calls = []
#
# # def save_image_to_disk(self, sprite_sheet_mask, file_info):
# # self.recorded_method_calls.append((self.save_image_to_disk.__name__, (sprite_sheet_mask, file_info)))
#
# # def save_sprite_definition_to_disk(self, sprite_definition, file_info):
# # self.recorded_method_calls.append(
# # (self.save_sprite_definition_to_disk.__name__, (sprite_definition, file_info)))
@ddtd.use_data_driven_testing_decorators
[docs]class ArgumentParsingTests(unittest.TestCase):
[docs] def setUp(self):
self.logger_mock = LoggerMock()
[docs] def test_main(self):
# arrange
args = "-h".split()
# act / verify
self.assertRaises(SystemExit, mut.main, args)
@ddtd.test_case(list("create_grid 2 2 out.png.sdef".split()),
(SpritesheetLib10Mock.create_grid.__name__,
(2, 2, 32, 32, FileInfo("out.png.sdef"))))
@ddtd.test_case(list("create_grid 2 2 --tile_width=10 --tile_height=10 out.png.sdef".split()),
(SpritesheetLib10Mock.create_grid.__name__,
(2, 2, 10, 10, FileInfo("out.png.sdef"))))
def test_grid_command_arguments(self, args, expected):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main(args)
# verify
self.assertEqual(expected, lib_mock.method_calls[0])
[docs] def test_create_from_file_command(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_from_file in.png.sdef out.png.sdef".split())
# verify
self.assertEqual(
(lib_mock.load_sdef_from_file.__name__, (FileInfo("in.png.sdef"),)),
lib_mock.method_calls[0])
[docs] def test_v_argument_set_log_level(self):
# arrange
self.logger_mock.level = logging.INFO
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef -vvv".split())
# verify
self.assertEqual(logging.DEBUG, self.logger_mock.level)
[docs] def test_v_count_argument_set_log_level_debug(self):
# arrange
self.logger_mock.level = logging.INFO
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef -vvvvvv".split())
# verify
self.assertEqual(logging.DEBUG, self.logger_mock.level)
[docs] def test_verbose_argument_set_log_level(self):
# arrange
self.logger_mock.level = logging.INFO
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef --verbose".split())
# verify
self.assertEqual(logging.WARN, self.logger_mock.level)
[docs] def test_q_argument_set_log_level(self):
# arrange
self.logger_mock.level = logging.DEBUG
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef -q".split())
# verify
self.assertEqual(logging.WARN, self.logger_mock.level)
[docs] def test_no_log_level_argument(self):
# arrange
self.logger_mock.level = logging.INFO
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef".split())
# verify
self.assertEqual(logging.ERROR, self.logger_mock.level)
[docs] def test_log_level_arguments_are_exclusive(self):
# arrange
sut = mut.SpriteSheetMaskGenerator(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act / verify
self.assertRaises(SystemExit, sut.main, "create_grid 2 2 out.png.sdef -v -q".split())
[docs] def test_dry_run_and_force_are_exclusive(self):
# arrange
sut = mut.SpriteSheetMaskGenerator(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act / verify
self.assertRaises(SystemExit, sut.main, "create_grid 2 2 out.png.sdef -f --dry-run".split())
[docs] def test_wrong_command(self):
# arrange
class _ArgParseWrong(mut.SpriteSheetMaskGenerator):
def __init__(self, logger):
mut.SpriteSheetMaskGenerator.__init__(self, SpritesheetLib10Mock(logger), logger)
def _parse_arguments(self, commandline_args=None):
class _ArgParseFaultyResult(object):
def __init__(self):
self.command = "bla"
self.filename = "out.png.sdef"
self.properties = None
return _ArgParseFaultyResult()
sut = _ArgParseWrong(self.logger_mock)
# act / verify
self.assertRaises(SystemExit, sut.main, "")
@ddtd.test_case((SpritesheetLib10Mock.adjust_spacing.__name__, (TestData.SDEF_GRID_2X2, None)),
"create_grid 2 2 out.png.sdef".split())
@ddtd.test_case((SpritesheetLib10Mock.adjust_spacing.__name__, (TestData.SDEF_GRID_2X2, 0)),
"create_grid 2 2 out.png.sdef -s=0".split())
@ddtd.test_case((SpritesheetLib10Mock.adjust_spacing.__name__, (TestData.SDEF_GRID_2X2, 3)),
"create_grid 2 2 out.png.sdef -s=3".split())
@ddtd.test_case((SpritesheetLib10Mock.adjust_spacing.__name__, (TestData.SDEF_GRID_2X2, 3)),
"create_grid 2 2 out.png.sdef -s=3 -m=3".split())
def test_create_sprite_definition_is_called_after_grid_command(self, expected, args):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main(args)
# verify
self.maxDiff = None
self.assertEqual(expected, lib_mock.method_calls[3])
[docs] def test_save_sprite_definition_to_disk_arguments(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef -i".split())
# verify
self.maxDiff = None
self.assertEqual(
(SpritesheetLib10Mock.save_sprite_definition_to_disk.__name__,
(None, FileInfo("out.png.sdef"))),
lib_mock.method_calls[7])
[docs] def test_save_image_to_disk_arguments(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("-i create_grid 2 2 out.png.sdef".split())
# verify
self.maxDiff = None
self.assertEqual(
(SpritesheetLib10Mock.save_image_to_disk.__name__, (None, FileInfo("out.png"))),
lib_mock.method_calls[8])
[docs] def test_save_to_disk_arguments_dry_run_save_image_to_disk(self):
# arrange
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef --dry-run -i".split())
# verify
self.maxDiff = None
self.assertEqual((_SpriteSheetMaskGeneratorCommandsMock.save_to_disk.__name__,
(FileInfo("out.png"), None, FileInfo("out.png.sdef"), None, True, False, True)),
sut.method_calls[0])
[docs] def test_save_to_disk_arguments_dry_run_no_save_image(self):
# arrange
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef --dry-run".split())
# verify
self.maxDiff = None
self.assertEqual((_SpriteSheetMaskGeneratorCommandsMock.save_to_disk.__name__,
(FileInfo("out.png"), None, FileInfo("out.png.sdef"), None, True, False, False)),
sut.method_calls[0])
@ddtd.test_case("create_grid 2 2 out.png.sdef -s=-1".split())
@ddtd.test_case("create_grid 2 2 out.png.sdef -s=-3 -m=3".split())
@ddtd.test_case("create_grid 2 2 out.png.sdef -s=3 -m=-1".split())
@ddtd.test_case("create_grid 2 2 out.png.sdef -s=3 -m=-3".split())
def test_create_sprite_definition_is_called_with_invalid_values_after_grid_command(self, args):
# arrange
sut = mut.SpriteSheetMaskGenerator(mut.SpritesheetLib10(self.logger_mock), self.logger_mock)
# act / verify
self.assertRaises(ValueError, sut.main, args)
[docs] def test_create_image_is_called_after_grid_command(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef -i".split())
# verify
self.assertEqual((lib_mock.create_image.__name__, (None, )), lib_mock.method_calls[6])
[docs] def test_create_sprite_definition_is_called_after_from_file_command(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_from_file in.png.sdef out.png.sdef".split())
# verify
self.assertEqual(lib_mock.adjust_spacing.__name__, lib_mock.method_calls[3][0])
[docs] def test_create_image_is_called_after_from_file_command(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_from_file in.png.sdef out.png.sdef -i".split())
# verify
self.assertEqual((lib_mock.create_image.__name__, (None, )), lib_mock.method_calls[6])
[docs] def test_method_sequence_save_image_to_disk(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef -i".split())
# verify
# print("method calls({0}: {1}".format(len(sut.method_calls), sut.method_calls))
self.assertEqual(sut.save_to_disk.__name__, sut.method_calls[0][0])
self.assertEqual(lib_mock.create_grid.__name__, lib_mock.method_calls[0][0])
self.assertEqual(lib_mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertEqual(lib_mock.is_sprite_def_valid.__name__, lib_mock.method_calls[2][0])
self.assertEqual(lib_mock.adjust_spacing.__name__, lib_mock.method_calls[3][0])
self.assertEqual(lib_mock.adjust_margin.__name__, lib_mock.method_calls[4][0])
self.assertEqual(lib_mock.is_sprite_def_valid.__name__, lib_mock.method_calls[5][0])
self.assertEqual(lib_mock.create_image.__name__, lib_mock.method_calls[6][0])
self.assertEqual(lib_mock.save_sprite_definition_to_disk.__name__, lib_mock.method_calls[7][0],
"method calls({0}: {1}".format(len(lib_mock.method_calls), lib_mock.method_calls))
self.assertEqual(lib_mock.save_image_to_disk.__name__, lib_mock.method_calls[8][0])
[docs] def test_method_sequence_no_image(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef".split())
# verify
# print("method calls({0}: {1}".format(len(sut.method_calls), sut.method_calls))
self.assertEqual(sut.save_to_disk.__name__, sut.method_calls[0][0])
self.assertEqual(lib_mock.create_grid.__name__, lib_mock.method_calls[0][0])
self.assertEqual(lib_mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertEqual(lib_mock.is_sprite_def_valid.__name__, lib_mock.method_calls[2][0])
self.assertEqual(lib_mock.adjust_spacing.__name__, lib_mock.method_calls[3][0])
self.assertEqual(lib_mock.adjust_margin.__name__, lib_mock.method_calls[4][0])
self.assertEqual(lib_mock.is_sprite_def_valid.__name__, lib_mock.method_calls[5][0])
self.assertEqual(lib_mock.save_sprite_definition_to_disk.__name__, lib_mock.method_calls[6][0],
"method calls({0}: {1}".format(len(lib_mock.method_calls), lib_mock.method_calls))
[docs] def test_version(self):
# act / verify
self.assertRaises(SystemExit, mut.main, "--version".split())
@ddtd.use_data_driven_testing_decorators
[docs]class TestPropertyParsing(unittest.TestCase):
[docs] def setUp(self):
self.logger_mock = LoggerMock()
[docs] def test_p_arg_is_accepted(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("-p {} create_grid 2 2 out.png.sdef".split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertEqual({}, lib_mock.method_calls[1][1][-1])
[docs] def test_properties_arg_is_accepted(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("--properties {} create_grid 2 2 out.png.sdef".split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertEqual({}, lib_mock.method_calls[1][1][-1])
[docs] def test_no_properties(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("create_grid 2 2 out.png.sdef".split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertEqual(None, lib_mock.method_calls[1][1][-1])
[docs] def test_properties_arg_is_empty_dict(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main("--properties {} create_grid 2 2 out.png.sdef".split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertDictEqual({}, lib_mock.method_calls[1][1][-1])
[docs] def test_properties_arg_passes_keys(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
expected = {'resolution': 'keep'}
# act
sut.main("--properties {'resolution':'keep'} create_grid 2 2 out.png.sdef".split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertDictEqual(expected, lib_mock.method_calls[1][1][-1])
[docs] def test_properties_same_key_raises(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
args = "--properties {'0:':{'keep':true},'2:':{'other':false,'keep':true}} create_grid 2 2 out.png.sdef".split()
self.assertRaises(mut.DictParseError, sut.main, args)
[docs] def test_properties_same_key_single_raises(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
args = "--properties {'0:':{'keep':true,'other':false},'1':{'other':false}} create_grid 2 2 out.png.sdef".split()
self.assertRaises(mut.DictParseError, sut.main, args)
[docs] def test_properties_merge_same_duplicate_keys_raises(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
# 'keep' is the error
args = "--properties {'bla':{'keep':true},'bla':{'other':false,'keep':false}} create_grid 2 2 out.png.sdef".split()
self.assertRaises(mut.DictParseError, sut.main, args)
[docs] def test_properties_same_duplicate_keys_raises(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
# 'keep' is the error
args = "--properties {'bla':{'keep':true,'keep':false}} create_grid 2 2 out.png.sdef".split()
self.assertRaises(mut.DictParseError, sut.main, args)
[docs] def test_properties_same_empty_key_raises(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
args = "--properties {'':'keep','bla':'other'} create_grid 2 2 out.png.sdef".split()
self.assertRaises(mut.DictParseError, sut.main, args)
[docs] def test_properties_negative_step_key_raises(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
args = "--properties {'10:0:-2':'keep'} create_grid 2 2 out.png.sdef".split()
self.assertRaises(mut.DictParseError, sut.main, args)
[docs] def test_load_dict_from_file_mocked(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
# following would be returned by json.load(...)
json_module = JsonMock(loads_value={'0': {'facing': 'up'}})
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock, json_module)
expected = {0: {'facing': 'up'}}
# act / verify
sut.main("--properties not-existent.json create_from_file in.png.sdef out.png.sdef".split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertDictEqual(expected, lib_mock.method_calls[1][1][-1])
[docs] def test_load_dict_from_file(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
# following would be returned by json.load(...)
# json_module = JsonMock(loads_value={'0': {'facing': 'up'}})
expected = {0: {'facing': 'up'}}
import json
dict_file_name = "prop-dict.json"
try:
json.dump(expected, FileInfo(dict_file_name).open(FileMode.WriteText))
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act / verify
sut.main("--properties {0} create_from_file in.png.sdef out.png.sdef".format(dict_file_name).split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertDictEqual(expected, lib_mock.method_calls[1][1][-1])
finally:
FileInfo(dict_file_name).delete()
_up_str = 'up'
_down_str = 'down'
@ddtd.test_case("{'0':{'facing':'up'}}", {0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str}},
test_name='single_sprite')
@ddtd.test_case("{'0:':{'facing':'up'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
2: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
3: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='all_from_zero')
@ddtd.test_case("{':':{'facing':'up'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
2: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
3: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='all')
@ddtd.test_case("{'::':{'facing':'up'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
2: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
3: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='all_double')
@ddtd.test_case("{'::2':{'facing':'up'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
2: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='even')
@ddtd.test_case("{'1::2':{'facing':'up'}}", {
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
3: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='odd')
@ddtd.test_case("{'1:3':{'facing':'up'}}", {
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
2: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='slice')
@ddtd.test_case("{'1:3:2':{'facing':'up'}}", {
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='slice_stepped')
@ddtd.test_case("{'0::2':{'facing':'up'},'1::2':{'facing':'down'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _down_str},
2: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
3: {SpritesheetLib10Mock.PROPERTIES.FACING: _down_str},
}, test_name='slice_column')
@ddtd.test_case("{'-1':{'facing':'up'}}", {
3: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='last')
@ddtd.test_case("{'1':{'facing':'up'},'resolution':'bla'}", {
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
'resolution': 'bla',
}, test_name='additional_non_slice_key')
@ddtd.test_case("{'10:12':{'facing':'up'}}", {
10: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
11: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str},
}, test_name='out_of_range')
@ddtd.test_case("{'0':{'facing':'up'},'0':{'other':'x'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str, 'other': 'x'},
}, test_name='merge')
@ddtd.test_case("{'0:2':{'facing':'up'},'0':{'other':'x'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str, 'other': 'x'},
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str, },
}, test_name='merge_range_and_single')
@ddtd.test_case("{'0:2':{'facing':'up'},'0:3':{'other':'x'}}", {
0: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str, 'other': 'x'},
1: {SpritesheetLib10Mock.PROPERTIES.FACING: _up_str, 'other': 'x'},
2: {'other': 'x'},
}, test_name='merge_range')
def test_properties_gid_keys(self, properties_string, expected):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = _SpriteSheetMaskGeneratorCommandsMock(lib_mock, self.logger_mock)
# act
sut.main(("--properties " + properties_string + " create_grid 2 2 out.png.sdef").split())
# verify
self.assertEqual(SpritesheetLib10Mock.update_sprite_properties.__name__, lib_mock.method_calls[1][0])
self.assertDictEqual(expected, lib_mock.method_calls[1][1][-1])
@ddtd.use_data_driven_testing_decorators
[docs]class SaveToFileTests(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
remove_file(FileInfo(self.file_name_sdef))
remove_file(FileInfo(self.file_name_image))
[docs] def tearDown(self):
remove_file(FileInfo(self.file_name_sdef))
remove_file(FileInfo(self.file_name_image))
[docs] def test_dry_run_does_not_call_save_methods(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
# act
cmd_line = "create_grid 2 2 " + self.file_name_sdef + " --dry-run"
sut.main(cmd_line.split())
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
[docs] def test_dry_run_logs_messages(self):
# arrange
sut = mut.SpriteSheetMaskGenerator(mut.SpritesheetLib10(self.logger_mock), self.logger_mock)
# act
cmd_line = "create_grid 2 2 " + self.file_name_sdef + " --dry-run"
sut.main(cmd_line.split())
# verify
self.assertTrue(5 < len(self.logger_mock.messages))
self.assertEqual(logging.WARN, self.logger_mock.messages[-1][0])
[docs] def test_dry_run_not_set_logs_no_messages(self):
# TODO: what does this test test exactly???
# arrange
sut = mut.SpriteSheetMaskGenerator(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
# act
cmd_line = "create_grid 2 2 " + self.file_name_sdef
sut.main(cmd_line.split())
# verify
self.assertFalse(7 < len(self.logger_mock.messages),
"should not be bigger than 7, but was {0}".format(str(len(self.logger_mock.messages))))
@ddtd.test_case(True, True, False, True, True, logging.INFO, 1)
@ddtd.test_case(True, False, False, True, True, logging.INFO, 1)
@ddtd.test_case(False, True, False, True, True, logging.INFO, 1)
@ddtd.test_case(False, False, False, True, True, logging.DEBUG, 1)
@ddtd.test_case(True, True, False, False, True, logging.ERROR, 1)
@ddtd.test_case(True, False, False, False, True, logging.ERROR, 1)
@ddtd.test_case(False, True, False, False, True, logging.ERROR, 1)
@ddtd.test_case(False, False, False, False, True, logging.DEBUG, 1)
@ddtd.test_case(True, True, False, True, False, logging.INFO, 2)
@ddtd.test_case(True, False, False, True, False, logging.INFO, 2)
@ddtd.test_case(False, True, False, True, False, logging.INFO, 2)
@ddtd.test_case(False, False, False, True, False, logging.DEBUG, 2)
@ddtd.test_case(True, True, False, False, False, logging.ERROR, 1)
@ddtd.test_case(True, False, False, False, False, logging.ERROR, 1)
@ddtd.test_case(False, True, False, False, False, logging.ERROR, 1)
@ddtd.test_case(False, False, False, False, False, logging.DEBUG, 2)
# dry run
@ddtd.test_case(False, False, True, False, True, logging.WARN, 1) # dry run
@ddtd.test_case(False, False, True, False, False, logging.WARN, 1) # dry run
@ddtd.test_case(False, False, True, True, True, logging.WARN, 1) # dry run
@ddtd.test_case(False, False, True, True, False, logging.WARN, 1) # dry run
@ddtd.test_case(False, True, True, False, True, logging.WARN, 1) # dry run
@ddtd.test_case(False, True, True, False, False, logging.WARN, 1) # dry run
@ddtd.test_case(False, True, True, True, True, logging.WARN, 1) # dry run
@ddtd.test_case(False, True, True, True, False, logging.WARN, 1) # dry run
@ddtd.test_case(True, False, True, False, True, logging.WARN, 1) # dry run
@ddtd.test_case(True, False, True, False, False, logging.WARN, 1) # dry run
@ddtd.test_case(True, False, True, True, True, logging.WARN, 1) # dry run
@ddtd.test_case(True, False, True, True, False, logging.WARN, 1) # dry run
@ddtd.test_case(True, True, True, False, True, logging.WARN, 1) # dry run
@ddtd.test_case(True, True, True, False, False, logging.WARN, 1) # dry run
@ddtd.test_case(True, True, True, True, True, logging.WARN, 1) # dry run
@ddtd.test_case(True, True, True, True, False, logging.WARN, 1) # dry run
def test_log_messages_written_when_saving_depending_on_vars(self, img_exists, sdef_exists, dry_run, force,
save_image,
expected, msg_count):
# arrange
sut = _SpriteSheetMaskGeneratorCommandsMock(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
img = object()
img_fi = FileInfoMock(self.file_name_sdef, img_exists)
sdef = {}
sdef_fi = FileInfoMock(self.file_name_image, sdef_exists)
# act
sut.save_to_disk(img_fi, img, sdef_fi, sdef, dry_run, force, save_image)
# verify
self.assertEqual(msg_count, len(self.logger_mock.messages),
"should be {0}, but is {1}".format(msg_count, len(self.logger_mock.messages)))
if self.logger_mock.messages:
self.assertEqual(expected, self.logger_mock.messages[0][0])
[docs] def test_force_argument_if_sdef_file_exists(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, False, True, True)
# verify
self.assertEqual(2, len(lib_mock.method_calls))
[docs] def test_no_file_is_overridden_if_exists(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, False, False, False)
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
[docs] def test_no_file_is_overridden_if_dry_run_force_false(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, True, False, False)
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
[docs] def test_no_file_is_overridden_if_dry_run_force_true(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, True, True, False)
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
[docs] def test_force_argument_if_sdef_file_exists_no_image(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, False, True, False)
# verify
self.assertEqual(1, len(lib_mock.method_calls))
[docs] def test_no_file_is_overridden_if_exists_save_image(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, False, False, True)
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
[docs] def test_no_file_is_overridden_if_dry_run_force_false_omit_true(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, True, False, True)
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
[docs] def test_no_file_is_overridden_if_dry_run_force_true_omit_true(self):
# arrange
lib_mock = SpritesheetLib10Mock(self.logger_mock)
sut = mut.SpriteSheetMaskGenerator(lib_mock, self.logger_mock)
image_fi_exists = FileInfoMock(self.file_name_sdef, True)
img = object()
sdef_fi_exists = FileInfoMock(self.file_name_image, True)
sdef = object()
# act
sut.save_to_disk(image_fi_exists, img, sdef_fi_exists, sdef, True, True, True)
# verify
called_method_names = [x[0] for x in lib_mock.method_calls]
self.assertFalse(lib_mock.save_image_to_disk.__name__ in called_method_names)
self.assertFalse(lib_mock.save_sprite_definition_to_disk.__name__ in called_method_names)
@ddtd.use_data_driven_testing_decorators
[docs]class SpriteDefinitionValidationTests(unittest.TestCase):
[docs] def setUp(self):
# arrange
self.logger_mock = LoggerMock()
self.sut = mut.SpriteSheetMaskGenerator(SpritesheetLib10Mock(self.logger_mock), self.logger_mock)
[docs] def test_invalid_sprite_definition_from_grid_command(self):
# arrange
class _TestMock(mut.SpritesheetLib10):
# noinspection PyDocstring
def create_grid(self, num_tiles_x, num_tiles_y, tile_width, tile_height, file_info):
return TestData.SDEF_INVALID_DUPLICATE_NAMES
sut = mut.SpriteSheetMaskGenerator(_TestMock(self.logger_mock), self.logger_mock)
# act / verify
self.assertRaises(SystemExit, sut.main, "create_grid 2 2 out.png.sdef".split())
[docs] def test_invalid_sprite_definition_from_from_file_command(self):
# arrange
class _TestMock(mut.SpritesheetLib10):
# noinspection PyDocstring
def load_sdef_from_file(self, file_info, json_module=None):
return TestData.SDEF_INVALID_DUPLICATE_NAMES
sut = mut.SpriteSheetMaskGenerator(_TestMock(self.logger_mock), self.logger_mock)
# act / verify
self.assertRaises(SystemExit, sut.main, "create_from_file in.png out.png.sdef".split())
[docs] def test_invalid_sprite_definition_after_convert_sprite_definition(self):
# arrange
class _TestMock(mut.SpritesheetLib10):
# noinspection PyDocstring
def adjust_spacing(self, source_sprite_def, spacing):
return TestData.SDEF_INVALID_DUPLICATE_NAMES
sut = mut.SpriteSheetMaskGenerator(_TestMock(self.logger_mock), self.logger_mock)
# act / verify
self.assertRaises(SystemExit, sut.main, "create_grid 2 2 out.png.sdef".split())
if __name__ == '__main__': # pragma: no cover
unittest.main()