Test media accessors, and the media organization itself
authorPetr Viktorin <encukou@gmail.com>
Thu, 14 Apr 2011 10:53:43 +0000 (13:53 +0300)
committerPetr Viktorin <encukou@gmail.com>
Thu, 14 Apr 2011 10:53:43 +0000 (13:53 +0300)
A few tests of the accessors, along with a very dumb, long-running script
to ensure everything is in its proper place, and there's nothing but the
proper things.

For now it still finds some beta form cruft for Burmy, Pichu and Cherrim.

pokedex/tests/test_media.py [new file with mode: 0644]

diff --git a/pokedex/tests/test_media.py b/pokedex/tests/test_media.py
new file mode 100644 (file)
index 0000000..81b5714
--- /dev/null
@@ -0,0 +1,256 @@
+
+"""Test the media accessors.
+
+If run directly from the command line, also tests the accessors and the names
+of all the media by getting just about everything in a naive brute-force way.
+This, of course, takes a lot of time to run.
+"""
+
+import os
+import re
+
+from nose.tools import *
+from nose.plugins.skip import SkipTest
+import nose
+import pkg_resources
+
+from pokedex.db import tables, connect
+from pokedex.util import media
+
+session = connect()
+basedir = pkg_resources.resource_filename('pokedex', 'data/media')
+
+path_re = re.compile('^[-a-z0-9./]*$')
+
+def test_totodile():
+    """Totodile's female sprite -- same as male"""
+    totodile = session.query(tables.Pokemon).filter_by(identifier=u'totodile').one()
+    accessor = media.PokemonMedia(totodile)
+    assert accessor.sprite() == accessor.sprite(female=True)
+
+def test_chimecho():
+    """Chimecho's Platinum female backsprite -- diffeent from male"""
+    chimecho = session.query(tables.Pokemon).filter_by(identifier=u'chimecho').one()
+    accessor = media.PokemonMedia(chimecho)
+    male = accessor.sprite('platinum', back=True, frame=2)
+    female = accessor.sprite('platinum', back=True, female=True, frame=2)
+    assert male != female
+
+def test_venonat():
+    """Venonat's shiny Yellow sprite -- same as non-shiny"""
+    venonat = session.query(tables.Pokemon).filter_by(identifier=u'venonat').one()
+    accessor = media.PokemonMedia(venonat)
+    assert accessor.sprite('yellow') == accessor.sprite('yellow', shiny=True)
+
+def test_arceus_icon():
+    """Arceus fire-form icon -- same as base icon"""
+    arceus = session.query(tables.Pokemon).filter_by(identifier=u'arceus').one()
+    accessor = media.PokemonMedia(arceus)
+    fire_arceus = [f for f in arceus.forms if f.identifier == 'fire'][0]
+    fire_accessor = media.PokemonFormMedia(fire_arceus)
+    assert accessor.icon() == fire_accessor.icon()
+
+@raises(ValueError)
+def test_strict_castform():
+    """Castform rainy form overworld with strict -- unavailable"""
+    castform = session.query(tables.Pokemon).filter_by(identifier=u'castform').first()
+    rainy_castform = [f for f in castform.forms if f.identifier == 'rainy'][0]
+    rainy_castform = media.PokemonFormMedia(rainy_castform)
+    rainy_castform.overworld('up', strict=True)
+
+@raises(ValueError)
+def test_strict_exeggcute():
+    """Exeggcutes's female backsprite, with strict -- unavailable"""
+    exeggcute = session.query(tables.Pokemon).filter_by(identifier=u'exeggcute').one()
+    accessor = media.PokemonMedia(exeggcute)
+    accessor.sprite(female=True, strict=True)
+
+
+
+def get_all_filenames():
+    print 'Reading all filenames...'
+
+    all_filenames = set()
+
+    for dirpath, dirnames, filenames in os.walk(basedir):
+        for filename in filenames:
+            path = os.path.join(dirpath, filename)
+            assert path_re.match(path), path
+            all_filenames.add(path)
+
+    return all_filenames
+
+def hit(filenames, method, *args, **kwargs):
+    """
+    Run the given accessor method with args & kwargs; if found remove the
+    result path from filenames and return True, else return False.
+    """
+    try:
+        medium = method(*args, **kwargs)
+        #print 'Hit', medium.relative_path
+        assert medium.exists
+    except ValueError, e:
+        #print 'DNF', e
+        return False
+    except:
+        print 'Error while processing', method, args, kwargs
+        raise
+    try:
+        filenames.remove(medium.path)
+    except KeyError:
+        pass
+    return True
+
+def check_get_everything():
+    """
+    For every the accessor method, loop over the Cartesian products of all
+    possible values for its arguments.
+    Make sure we get every file in the repo, and that we get a file whenever
+    we should.
+
+    Well, there are exceptions of course.
+    """
+
+    versions = list(session.query(tables.Version).all())
+    versions.append('red-green')
+
+    black = session.query(tables.Version).filter_by(identifier=u'black').one()
+
+    filenames = get_all_filenames()
+
+    # Some small stuff first
+
+    for damage_class in session.query(tables.MoveDamageClass).all():
+        assert hit(filenames, media.DamageClassMedia(damage_class).icon)
+
+    for habitat in session.query(tables.PokemonHabitat).all():
+        assert hit(filenames, media.HabitatMedia(habitat).icon)
+
+    for shape in session.query(tables.PokemonShape).all():
+        assert hit(filenames, media.ShapeMedia(shape).icon)
+
+    for item_pocket in session.query(tables.ItemPocket).all():
+        assert hit(filenames, media.ItemPocketMedia(item_pocket).icon)
+        assert hit(filenames, media.ItemPocketMedia(item_pocket).icon, selected=True)
+
+    for contest_type in session.query(tables.ContestType).all():
+        assert hit(filenames, media.ContestTypeMedia(contest_type).icon)
+
+    for elemental_type in session.query(tables.Type).all():
+        assert hit(filenames, media.TypeMedia(elemental_type).icon)
+
+    # Items
+    versions_for_items = [
+            None,
+            session.query(tables.Version).filter_by(identifier='emerald').one(),
+        ]
+
+    for item in session.query(tables.Item).all():
+        accessor = media.ItemMedia(item)
+        assert hit(filenames, accessor.berry_image) or not item.berry
+        for rotation in (0, 90, 180, 270):
+            assert hit(filenames, accessor.underground, rotation=rotation) or (
+                    not item.appears_underground or rotation)
+        for version in versions_for_items:
+            success = hit(filenames, accessor.sprite, version=version)
+            if version is None:
+                assert success
+
+    for color in 'red green blue pale prism'.split():
+        for big in (True, False):
+            accessor = media.UndergroundSphereMedia(color=color, big=big)
+            assert hit(filenames, accessor.underground)
+
+    for rock_type in 'i ii o o-big s t z'.split():
+        accessor = media.UndergroundRockMedia(rock_type)
+        for rotation in (0, 90, 180, 270):
+            success = hit(filenames, accessor.underground, rotation=rotation)
+            assert success or rotation
+
+    # Pokemon!
+    accessors = []
+
+    accessors.append(media.UnknownPokemonMedia())
+    accessors.append(media.EggMedia())
+    manaphy = session.query(tables.Pokemon).filter_by(identifier=u'manaphy').one()
+    accessors.append(media.EggMedia(manaphy))
+    accessors.append(media.SubstituteMedia())
+
+    print 'Loading pokemon'
+
+    for form in session.query(tables.PokemonForm).filter(tables.PokemonForm.identifier != '').all():
+        accessors.append(media.PokemonFormMedia(form))
+
+    for pokemon in session.query(tables.Pokemon).all():
+        accessors.append(media.PokemonMedia(pokemon))
+
+    for accessor in accessors:
+        assert hit(filenames, accessor.footprint) or not accessor.form
+        assert hit(filenames, accessor.trozei) or not accessor.form or (
+                accessor.form.pokemon.generation.id > 3)
+        assert hit(filenames, accessor.cry) or not accessor.form
+        assert hit(filenames, accessor.cropped_sprite) or not accessor.form
+        for female in (True, False):
+            assert hit(filenames, accessor.icon, female=female) or not accessor.form
+            assert hit(filenames, accessor.sugimori, female=female) or (
+                    not accessor.form or accessor.form.pokemon.id >= 647)
+            for shiny in (True, False):
+                for frame in (1, 2):
+                    for direction in 'up down left right'.split():
+                        assert hit(filenames, accessor.overworld,
+                                direction=direction,
+                                shiny=shiny,
+                                female=female,
+                                frame=frame,
+                            ) or not accessor.form or (
+                                    accessor.form.pokemon.generation.id > 4)
+                    for version in versions:
+                        for animated in (True, False):
+                            for back in (True, False):
+                                for color in (None, 'gray', 'gbc'):
+                                    success = hit(filenames,
+                                            accessor.sprite,
+                                            version,
+                                            animated=animated,
+                                            back=back,
+                                            color=color,
+                                            shiny=shiny,
+                                            female=female,
+                                            frame=frame,
+                                        )
+                                    if (version == black and not animated
+                                        and not back and not color and not
+                                        shiny and not female and
+                                        frame == 1):
+                                        # All pokemon are in Black
+                                        assert success or not accessor.form
+                                    if (str(accessor.pokemon_id) == '1'
+                                        and not animated and not color and
+                                        frame == 1):
+                                        # Bulbasaur is in all versions
+                                        assert success
+
+    # Remove exceptions
+    exceptions = [os.path.join(basedir, dirname) for dirname in
+            'chrome fonts ribbons'.split()]
+    exceptions.append(os.path.join(basedir, 'items', 'hm-'))
+    exceptions = tuple(exceptions)
+
+    for filename in tuple(filenames):
+        if filename.startswith(exceptions):
+            filenames.remove(filename)
+
+    if len(filenames):
+        print
+        print '-----------------'
+        print 'Unaccessed stuff:'
+        for filename in sorted(filenames):
+            print filename
+        print len(filenames), 'unaccessed files :('
+
+    return (not filenames)
+
+if __name__ == '__main__':
+    result = nose.run(defaultTest=__file__)
+    result = result and check_get_everything()
+    exit(not result)