mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Switch to py.test #604
This commit is contained in:
parent
c710457717
commit
332647c362
10 changed files with 392 additions and 359 deletions
21
conftest.py
Normal file
21
conftest.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
# Configuration for the tests.
|
||||
# Use `py.test` to run the tests.
|
||||
|
||||
# (This file needs to be in or above the directory where py.test is called)
|
||||
|
||||
import pytest
|
||||
import os
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--media-root", action="store",
|
||||
default=None,
|
||||
help="Root for the media files (if not specified and pokedex/data/media doesn't exist, tests are skipped)")
|
||||
parser.addoption("--all", action="store_true", default=False,
|
||||
help="Run all tests, even those that take a lot of time")
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
for funcargs in getattr(metafunc.function, 'funcarglist', ()):
|
||||
metafunc.addcall(funcargs=funcargs)
|
||||
for posargs in getattr(metafunc.function, 'posarglist', ()):
|
||||
metafunc.addcall(funcargs=dict(zip(metafunc.funcargnames, posargs)))
|
|
@ -1,6 +1,45 @@
|
|||
def setup():
|
||||
# XXX This needs to recreate the database, someday. :(
|
||||
pass
|
||||
|
||||
def teardown():
|
||||
pass
|
||||
import inspect
|
||||
from functools import wraps
|
||||
|
||||
# test support code
|
||||
def params(funcarglist):
|
||||
"""Basic list-of-dicts test parametrization
|
||||
|
||||
From: http://pytest.org/funcargs.html
|
||||
|
||||
Example:
|
||||
@params([dict(a=1, b=2), dict(a=3, b=4)])
|
||||
def test_lt(a, b):
|
||||
assert a < b
|
||||
"""
|
||||
def decorator(function):
|
||||
function.funcarglist = funcarglist
|
||||
return function
|
||||
return decorator
|
||||
|
||||
def positional_params(*paramlist):
|
||||
"""Magic list-of-lists parametrization
|
||||
|
||||
Example:
|
||||
@params([(1, 2), (3, 4)])
|
||||
def test_lt(a, b):
|
||||
assert a < b
|
||||
"""
|
||||
def decorator(function):
|
||||
function.posarglist = paramlist
|
||||
return function
|
||||
return decorator
|
||||
|
||||
def single_params(*paramlist):
|
||||
"""Magic list-of-lists parametrization
|
||||
|
||||
Example:
|
||||
@params('1', '2', '3', '4'])
|
||||
def test_int(k):
|
||||
assert int(k)
|
||||
"""
|
||||
def decorator(function):
|
||||
function.posarglist = [[param] for param in paramlist]
|
||||
return function
|
||||
return decorator
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from nose.tools import *
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
|
||||
from sqlalchemy.orm import aliased
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
|
@ -21,8 +22,8 @@ def test_encounter_slots():
|
|||
.join((version_group_b, tables.Version.version_group)) \
|
||||
.filter(version_group_a.id != version_group_b.id)
|
||||
|
||||
assert_equal(sanity_q.count(), 0,
|
||||
"Encounter slots all match the encounters they belong to")
|
||||
# Encounter slots all match the encounters they belong to
|
||||
assert sanity_q.count() == 0
|
||||
|
||||
def test_nonzero_autoincrement_ids():
|
||||
"""Check that autoincrementing ids don't contain zeroes
|
||||
|
@ -34,8 +35,8 @@ def test_nonzero_autoincrement_ids():
|
|||
for cls in tables.mapped_classes:
|
||||
if 'id' in cls.__table__.c:
|
||||
if cls.__table__.c.id.autoincrement:
|
||||
@raises(NoResultFound)
|
||||
def nonzero_id(cls):
|
||||
util.get(session, cls, id=0)
|
||||
with pytest.raises(NoResultFound):
|
||||
util.get(session, cls, id=0)
|
||||
nonzero_id.description = "No zero id in %s" % cls.__name__
|
||||
yield nonzero_id, cls
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
# encoding: utf8
|
||||
from nose.tools import *
|
||||
import unittest
|
||||
# Encoding: UTF-8
|
||||
|
||||
from pokedex.tests import *
|
||||
|
||||
from pokedex.lookup import PokedexLookup
|
||||
|
||||
lookup = None
|
||||
lookup = PokedexLookup()
|
||||
|
||||
def setup():
|
||||
# Recreate data
|
||||
global lookup
|
||||
lookup = PokedexLookup()
|
||||
|
||||
def test_exact_lookup():
|
||||
tests = [
|
||||
@positional_params(
|
||||
# Simple lookups
|
||||
(u'Eevee', 'pokemon_species',133),
|
||||
(u'Scratch', 'moves', 10),
|
||||
|
@ -37,68 +31,61 @@ def test_exact_lookup():
|
|||
(u'이브이', 'pokemon_species', 133),
|
||||
(u'伊布', 'pokemon_species', 133),
|
||||
(u'Evoli', 'pokemon_species', 133),
|
||||
]
|
||||
)
|
||||
def test_exact_lookup(input, table, id):
|
||||
results = lookup.lookup(input)
|
||||
assert len(results) == 1
|
||||
assert results[0].exact == True
|
||||
|
||||
for input, table, id in tests:
|
||||
results = lookup.lookup(input)
|
||||
assert_equal(len(results), 1, u"'%s' returns one result" % input)
|
||||
assert_equal(results[0].exact, True, u"'%s' match exactly" % input)
|
||||
|
||||
row = results[0].object
|
||||
assert_equal(row.__tablename__, table, u"'%s' is in the right table" % input)
|
||||
assert_equal(row.id, id, u"'%s' returns the right id" % input)
|
||||
row = results[0].object
|
||||
assert row.__tablename__ == table
|
||||
assert row.id == id
|
||||
|
||||
|
||||
def test_id_lookup():
|
||||
results = lookup.lookup(u'1')
|
||||
assert_true(len(results) >= 5, u'At least five things have id 1')
|
||||
assert_true(all(_.object.id == 1 for _ in results),
|
||||
u'All results have id 1')
|
||||
assert len(results) >= 5
|
||||
assert all(result.object.id == 1 for result in results)
|
||||
|
||||
|
||||
def test_multi_lookup():
|
||||
results = lookup.lookup(u'Metronome')
|
||||
assert_equal(len(results), 2, u'Two things called "Metronome"')
|
||||
assert_true(results[0].exact, u'Metronome matches are exact')
|
||||
assert len(results) == 2
|
||||
assert results[0].exact
|
||||
|
||||
|
||||
def test_type_lookup():
|
||||
results = lookup.lookup(u'pokemon:1')
|
||||
assert_equal(results[0].object.__tablename__, 'pokemon_species',
|
||||
u'Type restriction works correctly')
|
||||
assert_equal(len(results), 1, u'Only one id result when type is specified')
|
||||
assert_equal(results[0].object.name, u'Bulbasaur',
|
||||
u'Type + id returns the right result')
|
||||
assert results[0].object.__tablename__ == 'pokemon_species'
|
||||
assert len(results) == 1
|
||||
assert results[0].object.name == u'Bulbasaur'
|
||||
|
||||
results = lookup.lookup(u'1', valid_types=['pokemon_species'])
|
||||
assert_equal(results[0].object.name, u'Bulbasaur',
|
||||
u'valid_types works as well as type: prefix')
|
||||
assert results[0].object.name == u'Bulbasaur'
|
||||
|
||||
|
||||
def test_language_lookup():
|
||||
# There are two objects named "charge": the move Charge, and the move
|
||||
# Tackle, which is called "Charge" in French.
|
||||
results = lookup.lookup(u'charge')
|
||||
assert_true(len(results) > 1, u'There are multiple "charge"s')
|
||||
assert len(results) > 1
|
||||
|
||||
results = lookup.lookup(u'@fr:charge')
|
||||
assert_equal(results[0].iso639, u'fr', u'Language restriction works correctly')
|
||||
assert_equal(len(results), 1, u'Only one "charge" result when language is specified')
|
||||
assert_equal(results[0].object.name, u'Tackle',
|
||||
u'Language + vague name returns the right result')
|
||||
assert results[0].iso639 == u'fr'
|
||||
assert len(results) == 1
|
||||
assert results[0].object.name == u'Tackle'
|
||||
|
||||
results = lookup.lookup(u'charge', valid_types=['@fr'])
|
||||
assert_equal(results[0].object.name, u'Tackle',
|
||||
u'valid_types works as well as @lang: prefix')
|
||||
assert results[0].object.name == u'Tackle'
|
||||
|
||||
results = lookup.lookup(u'@fr,move:charge')
|
||||
assert_equal(results[0].object.name, u'Tackle',
|
||||
u'Languages and types both work together')
|
||||
assert results[0].object.name == u'Tackle'
|
||||
|
||||
results = lookup.lookup(u'@fr:charge', valid_types=['move'])
|
||||
assert_equal(results[0].object.name, u'Tackle',
|
||||
u'valid_types and language prefixes get along')
|
||||
assert results[0].object.name, u'Tackle'
|
||||
|
||||
def test_fuzzy_lookup():
|
||||
tests = [
|
||||
|
||||
@positional_params(
|
||||
# Regular English names
|
||||
(u'chamander', u'Charmander'),
|
||||
(u'pokeball', u'Poké Ball'),
|
||||
|
@ -110,44 +97,51 @@ def test_fuzzy_lookup():
|
|||
# Sufficiently long foreign names
|
||||
(u'カクレオ', u'Kecleon'),
|
||||
(u'Yamikrasu', u'Murkrow'),
|
||||
]
|
||||
)
|
||||
def test_fuzzy_lookup(misspelling, name):
|
||||
results = lookup.lookup(misspelling)
|
||||
first_result = results[0]
|
||||
assert first_result.object.name == name
|
||||
|
||||
for misspelling, name in tests:
|
||||
results = lookup.lookup(misspelling)
|
||||
first_result = results[0]
|
||||
assert_equal(first_result.object.name, name,
|
||||
u'Simple misspellings are corrected')
|
||||
|
||||
def test_nidoran():
|
||||
results = lookup.lookup(u'Nidoran')
|
||||
top_names = [_.object.name for _ in results[0:2]]
|
||||
assert_true(u'Nidoran♂' in top_names, u'Nidoran♂ is a top result for "Nidoran"')
|
||||
assert_true(u'Nidoran♀' in top_names, u'Nidoran♀ is a top result for "Nidoran"')
|
||||
top_names = [result.object.name for result in results[0:2]]
|
||||
assert u'Nidoran♂' in top_names
|
||||
assert u'Nidoran♀' in top_names
|
||||
|
||||
def test_wildcard_lookup():
|
||||
tests = [
|
||||
|
||||
@positional_params(
|
||||
(u'pokemon:*meleon', u'Charmeleon'),
|
||||
(u'item:master*', u'Master Ball'),
|
||||
(u'ee?ee', u'Eevee'),
|
||||
]
|
||||
)
|
||||
def test_wildcard_lookup(wildcard, name):
|
||||
results = lookup.lookup(wildcard)
|
||||
first_result = results[0]
|
||||
assert first_result.object.name == name
|
||||
|
||||
for wildcard, name in tests:
|
||||
results = lookup.lookup(wildcard)
|
||||
first_result = results[0]
|
||||
assert_equal(first_result.object.name, name,
|
||||
u'Wildcards work correctly')
|
||||
|
||||
def test_random_lookup():
|
||||
for _ in xrange(5):
|
||||
def test_bare_random():
|
||||
for i in range(5):
|
||||
results = lookup.lookup(u'random')
|
||||
assert_equal(len(results), 1, u'Random returns one result')
|
||||
assert len(results) == 1
|
||||
|
||||
|
||||
@positional_params(
|
||||
[u'pokemon_species'],
|
||||
[u'moves'],
|
||||
[u'items'],
|
||||
[u'abilities'],
|
||||
[u'types'],
|
||||
)
|
||||
def test_qualified_random(table_name):
|
||||
results = lookup.lookup(u'random', valid_types=[table_name])
|
||||
assert len(results) == 1
|
||||
assert results[0].object.__tablename__ == table_name
|
||||
|
||||
for table_name in [u'pokemon_species', u'moves', u'items', u'abilities', u'types']:
|
||||
results = lookup.lookup(u'random', valid_types=[table_name])
|
||||
assert_equal(len(results), 1, u'Constrained random returns one result')
|
||||
assert_equal(results[0].object.__tablename__, table_name,
|
||||
u'Constrained random returns result from the right table')
|
||||
|
||||
def test_crash_empty_prefix():
|
||||
"""Searching for ':foo' used to crash, augh!"""
|
||||
results = lookup.lookup(u':Eevee')
|
||||
assert_equal(results[0].object.name, u'Eevee', u'Empty prefix dun crash')
|
||||
assert results[0].object.name == u'Eevee'
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
"""Test the media accessors.
|
||||
|
||||
If run directly from the command line, also tests the accessors and the names
|
||||
|
@ -6,45 +5,33 @@ 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 pytest
|
||||
|
||||
import os
|
||||
import re
|
||||
from functools import wraps
|
||||
|
||||
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
|
||||
|
||||
def pytest_funcarg__root(request):
|
||||
root = request.config.option.media_root
|
||||
if not root:
|
||||
root = os.path.join(os.path.dirname(__file__), *'../data/media'.split('/'))
|
||||
if not media.BaseMedia(root).available:
|
||||
raise pytest.skip("Media unavailable")
|
||||
return root
|
||||
|
||||
session = connect()
|
||||
basedir = pkg_resources.resource_filename('pokedex', 'data/media')
|
||||
|
||||
path_re = re.compile('^[-a-z0-9./]*$')
|
||||
|
||||
root = pkg_resources.resource_filename('pokedex', 'data/media')
|
||||
|
||||
media_available = media.BaseMedia(root).available
|
||||
|
||||
def if_available(func):
|
||||
@wraps(func)
|
||||
def if_available_wrapper(*args, **kwargs):
|
||||
if not media_available:
|
||||
raise SkipTest('Media not available at %s' % root)
|
||||
else:
|
||||
func(*args, **kwargs)
|
||||
return if_available_wrapper
|
||||
|
||||
@if_available
|
||||
def test_totodile():
|
||||
def test_totodile(root):
|
||||
"""Totodile's female sprite -- same as male"""
|
||||
totodile = session.query(tables.PokemonSpecies).filter_by(identifier=u'totodile').one()
|
||||
accessor = media.PokemonSpeciesMedia(root, totodile)
|
||||
assert accessor.sprite() == accessor.sprite(female=True)
|
||||
|
||||
@if_available
|
||||
def test_chimecho():
|
||||
def test_chimecho(root):
|
||||
"""Chimecho's Platinum female backsprite -- diffeent from male"""
|
||||
chimecho = session.query(tables.PokemonSpecies).filter_by(identifier=u'chimecho').one()
|
||||
accessor = media.PokemonSpeciesMedia(root, chimecho)
|
||||
|
@ -52,15 +39,13 @@ def test_chimecho():
|
|||
female = accessor.sprite('platinum', back=True, female=True, frame=2)
|
||||
assert male != female
|
||||
|
||||
@if_available
|
||||
def test_venonat():
|
||||
def test_venonat(root):
|
||||
"""Venonat's shiny Yellow sprite -- same as non-shiny"""
|
||||
venonat = session.query(tables.PokemonSpecies).filter_by(identifier=u'venonat').one()
|
||||
accessor = media.PokemonSpeciesMedia(root, venonat)
|
||||
assert accessor.sprite('yellow') == accessor.sprite('yellow', shiny=True)
|
||||
|
||||
@if_available
|
||||
def test_arceus_icon():
|
||||
def test_arceus_icon(root):
|
||||
"""Arceus fire-form icon -- same as base icon"""
|
||||
arceus = session.query(tables.PokemonSpecies).filter_by(identifier=u'arceus').one()
|
||||
accessor = media.PokemonSpeciesMedia(root, arceus)
|
||||
|
@ -68,32 +53,28 @@ def test_arceus_icon():
|
|||
fire_accessor = media.PokemonFormMedia(root, fire_arceus)
|
||||
assert accessor.icon() == fire_accessor.icon()
|
||||
|
||||
@if_available
|
||||
@raises(ValueError)
|
||||
def test_strict_castform():
|
||||
def test_strict_castform(root):
|
||||
"""Castform rainy form overworld with strict -- unavailable"""
|
||||
castform = session.query(tables.PokemonSpecies).filter_by(identifier=u'castform').first()
|
||||
rainy_castform = [f for f in castform.forms if f.form_identifier == 'rainy'][0]
|
||||
print rainy_castform
|
||||
rainy_castform = media.PokemonFormMedia(root, rainy_castform)
|
||||
rainy_castform.overworld('up', strict=True)
|
||||
with pytest.raises(ValueError):
|
||||
castform = session.query(tables.PokemonSpecies).filter_by(identifier=u'castform').first()
|
||||
rainy_castform = [f for f in castform.forms if f.form_identifier == 'rainy'][0]
|
||||
print rainy_castform
|
||||
rainy_castform = media.PokemonFormMedia(root, rainy_castform)
|
||||
rainy_castform.overworld('up', strict=True)
|
||||
|
||||
@if_available
|
||||
@raises(ValueError)
|
||||
def test_strict_exeggcute():
|
||||
def test_strict_exeggcute(root):
|
||||
"""Exeggcutes's female backsprite, with strict -- unavailable"""
|
||||
exeggcute = session.query(tables.PokemonSpecies).filter_by(identifier=u'exeggcute').one()
|
||||
accessor = media.PokemonSpeciesMedia(root, exeggcute)
|
||||
accessor.sprite(female=True, strict=True)
|
||||
with pytest.raises(ValueError):
|
||||
exeggcute = session.query(tables.PokemonSpecies).filter_by(identifier=u'exeggcute').one()
|
||||
accessor = media.PokemonSpeciesMedia(root, exeggcute)
|
||||
accessor.sprite(female=True, strict=True)
|
||||
|
||||
|
||||
|
||||
def get_all_filenames():
|
||||
print 'Reading all filenames...'
|
||||
|
||||
def get_all_filenames(root):
|
||||
all_filenames = set()
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(basedir):
|
||||
for dirpath, dirnames, filenames in os.walk(root):
|
||||
dirnames[:] = [dirname for dirname in dirnames if dirname != '.git']
|
||||
for filename in filenames:
|
||||
path = os.path.join(dirpath, filename)
|
||||
|
@ -123,8 +104,8 @@ def hit(filenames, method, *args, **kwargs):
|
|||
pass
|
||||
return True
|
||||
|
||||
@if_available
|
||||
def check_get_everything():
|
||||
@pytest.mark.skipif("not config.getvalue('all')", reason='`--all` not specified')
|
||||
def test_get_everything(root, pytestconfig):
|
||||
"""
|
||||
For every the accessor method, loop over the Cartesian products of all
|
||||
possible values for its arguments.
|
||||
|
@ -133,13 +114,14 @@ def check_get_everything():
|
|||
|
||||
Well, there are exceptions of course.
|
||||
"""
|
||||
assert pytestconfig.getvalue('all')
|
||||
|
||||
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()
|
||||
filenames = get_all_filenames(root)
|
||||
|
||||
# Some small stuff first
|
||||
|
||||
|
@ -252,26 +234,21 @@ def check_get_everything():
|
|||
assert success
|
||||
|
||||
# Remove exceptions
|
||||
exceptions = [os.path.join(basedir, dirname) for dirname in
|
||||
exceptions = [os.path.join(root, dirname) for dirname in
|
||||
'chrome fonts ribbons'.split()]
|
||||
exceptions.append(os.path.join(basedir, 'items', 'hm-'))
|
||||
exceptions.append(os.path.join(root, 'items', 'hm-'))
|
||||
exceptions = tuple(exceptions)
|
||||
|
||||
for filename in tuple(filenames):
|
||||
unaccessed_filenames = set(filenames)
|
||||
for filename in filenames:
|
||||
if filename.startswith(exceptions):
|
||||
filenames.remove(filename)
|
||||
unaccessed_filenames.remove(filename)
|
||||
|
||||
if len(filenames):
|
||||
print
|
||||
print '-----------------'
|
||||
print 'Unaccessed stuff:'
|
||||
for filename in sorted(filenames):
|
||||
if unaccessed_filenames:
|
||||
print 'Unaccessed files:'
|
||||
for filename in unaccessed_filenames:
|
||||
print filename
|
||||
print len(filenames), 'unaccessed files :('
|
||||
|
||||
assert unaccessed_filenames == set()
|
||||
|
||||
return (not filenames)
|
||||
|
||||
if __name__ == '__main__':
|
||||
result = nose.run(defaultTest=__file__)
|
||||
result = result and check_get_everything()
|
||||
exit(not result)
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
# encoding: utf8
|
||||
from nose.tools import *
|
||||
import unittest
|
||||
|
||||
import pokedex.roomaji
|
||||
from pokedex.tests import positional_params
|
||||
|
||||
|
||||
def test_roomaji():
|
||||
tests = [
|
||||
@positional_params(
|
||||
(u'ヤミカラス', 'yamikarasu'),
|
||||
|
||||
# Elongated vowel
|
||||
|
@ -24,14 +21,13 @@ def test_roomaji():
|
|||
(u'ラティアス', 'ratiasu'),
|
||||
(u'ウィー', 'wii'),
|
||||
(u'セレビィ', 'sereby'),
|
||||
]
|
||||
)
|
||||
def test_roomaji(kana, roomaji):
|
||||
result = pokedex.roomaji.romanize(kana)
|
||||
assert result == roomaji
|
||||
|
||||
for kana, roomaji in tests:
|
||||
result = pokedex.roomaji.romanize(kana)
|
||||
assert_equal(result, roomaji, u"'%s' romanizes correctly" % roomaji)
|
||||
|
||||
def test_roomaji_cs():
|
||||
tests = [
|
||||
@positional_params(
|
||||
(u'ヤミカラス', u'jamikarasu'),
|
||||
|
||||
# Elongated vowel
|
||||
|
@ -49,8 +45,7 @@ def test_roomaji_cs():
|
|||
(u'ラティアス', u'ratiasu'),
|
||||
(u'ウィー', u'wí'),
|
||||
(u'セレビィ', u'serebí'),
|
||||
]
|
||||
|
||||
for kana, roomaji in tests:
|
||||
result = pokedex.roomaji.romanize(kana, 'cs')
|
||||
assert_equal(result, roomaji, u"'%s' romanizes correctly for Czech" % roomaji)
|
||||
)
|
||||
def test_roomaji_cs(kana, roomaji):
|
||||
result = pokedex.roomaji.romanize(kana, 'cs')
|
||||
assert result == roomaji
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# encoding: utf8
|
||||
from nose.tools import *
|
||||
import unittest
|
||||
|
||||
from pokedex.tests import single_params
|
||||
|
||||
from sqlalchemy import Column, Integer, String, create_engine
|
||||
from sqlalchemy.orm import class_mapper, joinedload, sessionmaker
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
@ -10,22 +11,23 @@ from pokedex.db import tables, markdown
|
|||
from pokedex.db.multilang import MultilangScopedSession, MultilangSession, \
|
||||
create_translation_table
|
||||
|
||||
def test_variable_names():
|
||||
@single_params(*dir(tables))
|
||||
def test_variable_names(varname):
|
||||
"""We want pokedex.db.tables to export tables using the class name"""
|
||||
for varname in dir(tables):
|
||||
if not varname[0].isupper():
|
||||
continue
|
||||
table = getattr(tables, varname)
|
||||
try:
|
||||
if not issubclass(table, tables.TableBase) or table is tables.TableBase:
|
||||
continue
|
||||
except TypeError:
|
||||
continue
|
||||
classname = table.__name__
|
||||
if classname and varname[0].isupper():
|
||||
assert varname == classname, '%s refers to %s' % (varname, classname)
|
||||
for table in tables.mapped_classes:
|
||||
assert getattr(tables, table.__name__) is table
|
||||
table = getattr(tables, varname)
|
||||
try:
|
||||
if not issubclass(table, tables.TableBase) or table is tables.TableBase:
|
||||
return
|
||||
except TypeError:
|
||||
return
|
||||
classname = table.__name__
|
||||
if classname and varname[0].isupper():
|
||||
assert varname == classname, '%s refers to %s' % (varname, classname)
|
||||
|
||||
@single_params(*tables.mapped_classes)
|
||||
def test_variable_names_2(table):
|
||||
"""We also want all of the tables exported"""
|
||||
assert getattr(tables, table.__name__) is table
|
||||
|
||||
def test_class_order():
|
||||
"""The declarative classes should be defined in alphabetical order.
|
||||
|
@ -156,52 +158,52 @@ def test_i18n_table_creation():
|
|||
assert foo.name_map[lang_en] == 'different english'
|
||||
assert foo.name_map[lang_ru] == 'new russian'
|
||||
|
||||
def test_texts():
|
||||
classes = []
|
||||
for cls in tables.mapped_classes:
|
||||
classes.append(cls)
|
||||
classes += cls.translation_classes
|
||||
@single_params(*classes)
|
||||
def test_texts(cls):
|
||||
"""Check DB schema for integrity of text columns & translations.
|
||||
|
||||
Mostly protects against copy/paste oversights and rebase hiccups.
|
||||
If there's a reason to relax the tests, do it
|
||||
"""
|
||||
classes = []
|
||||
for cls in tables.mapped_classes:
|
||||
classes.append(cls)
|
||||
classes += cls.translation_classes
|
||||
for cls in classes:
|
||||
if hasattr(cls, 'local_language') or hasattr(cls, 'language'):
|
||||
good_formats = 'markdown plaintext gametext'.split()
|
||||
assert_text = '%s is language-specific'
|
||||
if hasattr(cls, 'local_language') or hasattr(cls, 'language'):
|
||||
good_formats = 'markdown plaintext gametext'.split()
|
||||
assert_text = '%s is language-specific'
|
||||
else:
|
||||
good_formats = 'identifier latex'.split()
|
||||
assert_text = '%s is not language-specific'
|
||||
columns = sorted(cls.__table__.c, key=lambda c: c.name)
|
||||
text_columns = []
|
||||
for column in columns:
|
||||
format = column.info.get('format', None)
|
||||
if format is not None:
|
||||
if format not in good_formats:
|
||||
raise AssertionError(assert_text % column)
|
||||
if (format != 'identifier') and (column.name == 'identifier'):
|
||||
raise AssertionError('%s: identifier column name/type mismatch' % column)
|
||||
if column.info.get('official', None) and format not in 'gametext plaintext':
|
||||
raise AssertionError('%s: official text with bad format' % column)
|
||||
text_columns.append(column)
|
||||
else:
|
||||
good_formats = 'identifier latex'.split()
|
||||
assert_text = '%s is not language-specific'
|
||||
columns = sorted(cls.__table__.c, key=lambda c: c.name)
|
||||
text_columns = []
|
||||
for column in columns:
|
||||
format = column.info.get('format', None)
|
||||
if format is not None:
|
||||
if format not in good_formats:
|
||||
raise AssertionError(assert_text % column)
|
||||
if (format != 'identifier') and (column.name == 'identifier'):
|
||||
raise AssertionError('%s: identifier column name/type mismatch' % column)
|
||||
if column.info.get('official', None) and format not in 'gametext plaintext':
|
||||
raise AssertionError('%s: official text with bad format' % column)
|
||||
text_columns.append(column)
|
||||
else:
|
||||
if isinstance(column.type, tables.Unicode):
|
||||
raise AssertionError('%s: text column without format' % column)
|
||||
if column.name == 'name' and format != 'plaintext':
|
||||
raise AssertionError('%s: non-plaintext name' % column)
|
||||
# No mention of English in the description
|
||||
assert 'English' not in column.info['description'], column
|
||||
# If there's more than one text column in a translation table,
|
||||
# they have to be nullable, to support missing translations
|
||||
if hasattr(cls, 'local_language') and len(text_columns) > 1:
|
||||
for column in text_columns:
|
||||
assert column.nullable
|
||||
if isinstance(column.type, tables.Unicode):
|
||||
raise AssertionError('%s: text column without format' % column)
|
||||
if column.name == 'name' and format != 'plaintext':
|
||||
raise AssertionError('%s: non-plaintext name' % column)
|
||||
# No mention of English in the description
|
||||
assert 'English' not in column.info['description'], column
|
||||
# If there's more than one text column in a translation table,
|
||||
# they have to be nullable, to support missing translations
|
||||
if hasattr(cls, 'local_language') and len(text_columns) > 1:
|
||||
for column in text_columns:
|
||||
assert column.nullable
|
||||
|
||||
def test_identifiers_with_names():
|
||||
@single_params(*tables.mapped_classes)
|
||||
def test_identifiers_with_names(table):
|
||||
"""Test that named tables have identifiers
|
||||
"""
|
||||
for table in sorted(tables.mapped_classes, key=lambda t: t.__name__):
|
||||
for translation_class in table.translation_classes:
|
||||
if hasattr(translation_class, 'name'):
|
||||
assert hasattr(table, 'identifier'), table
|
||||
for translation_class in table.translation_classes:
|
||||
if hasattr(translation_class, 'name'):
|
||||
assert hasattr(table, 'identifier'), table
|
||||
|
|
|
@ -1,150 +1,147 @@
|
|||
# Encoding: UTF-8
|
||||
|
||||
from nose.tools import *
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
import pytest
|
||||
|
||||
from pokedex.tests import positional_params
|
||||
|
||||
from pokedex.db import tables, connect, util, markdown
|
||||
|
||||
class TestStrings(object):
|
||||
def setup(self):
|
||||
self.connection = connect()
|
||||
connection = connect()
|
||||
|
||||
def teardown(self):
|
||||
self.connection.rollback()
|
||||
def test_filter():
|
||||
q = connection.query(tables.PokemonSpecies).filter(
|
||||
tables.PokemonSpecies.name == u"Marowak")
|
||||
assert q.one().identifier == 'marowak'
|
||||
|
||||
def test_filter(self):
|
||||
q = self.connection.query(tables.PokemonSpecies).filter(
|
||||
tables.PokemonSpecies.name == u"Marowak")
|
||||
assert q.one().identifier == 'marowak'
|
||||
def test_languages():
|
||||
q = connection.query(tables.PokemonSpecies).filter(
|
||||
tables.PokemonSpecies.name == u"Mightyena")
|
||||
pkmn = q.one()
|
||||
for lang, name in (
|
||||
('en', u'Mightyena'),
|
||||
('ja', u'グラエナ'),
|
||||
('roomaji', u'Guraena'),
|
||||
('fr', u'Grahyèna'),
|
||||
):
|
||||
language = connection.query(tables.Language).filter_by(
|
||||
identifier=lang).one()
|
||||
assert pkmn.name_map[language] == name
|
||||
|
||||
def test_languages(self):
|
||||
q = self.connection.query(tables.PokemonSpecies).filter(
|
||||
tables.PokemonSpecies.name == u"Mightyena")
|
||||
pkmn = q.one()
|
||||
for lang, name in (
|
||||
('en', u'Mightyena'),
|
||||
('ja', u'グラエナ'),
|
||||
('roomaji', u'Guraena'),
|
||||
('fr', u'Grahyèna'),
|
||||
):
|
||||
language = self.connection.query(tables.Language).filter_by(
|
||||
identifier=lang).one()
|
||||
assert pkmn.name_map[language] == name
|
||||
|
||||
@raises(KeyError)
|
||||
def test_bad_lang(self):
|
||||
q = self.connection.query(tables.PokemonSpecies).filter(
|
||||
def test_bad_lang():
|
||||
with pytest.raises(KeyError):
|
||||
q = connection.query(tables.PokemonSpecies).filter(
|
||||
tables.PokemonSpecies.name == u"Mightyena")
|
||||
pkmn = q.one()
|
||||
pkmn.names["identifier of a language that doesn't exist"]
|
||||
|
||||
def test_mutating(self):
|
||||
item = self.connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
language = self.connection.query(tables.Language).filter_by(
|
||||
identifier=u"de").one()
|
||||
item.name_map[language] = u"foo"
|
||||
assert item.name_map[language] == "foo"
|
||||
item.name_map[language] = u"xyzzy"
|
||||
assert item.name_map[language] == "xyzzy"
|
||||
def test_mutating():
|
||||
item = connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
language = connection.query(tables.Language).filter_by(
|
||||
identifier=u"de").one()
|
||||
item.name_map[language] = u"foo"
|
||||
assert item.name_map[language] == "foo"
|
||||
item.name_map[language] = u"xyzzy"
|
||||
assert item.name_map[language] == "xyzzy"
|
||||
|
||||
def test_mutating_default(self):
|
||||
item = self.connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
item.name = u"foo"
|
||||
assert item.name == "foo"
|
||||
def test_mutating_default():
|
||||
item = connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
item.name = u"foo"
|
||||
assert item.name == "foo"
|
||||
|
||||
def test_string_mapping(self):
|
||||
item = self.connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
assert len(item.name_map) == len(item.names)
|
||||
for lang in item.names:
|
||||
assert item.name_map[lang] == item.names[lang].name
|
||||
assert lang in item.name_map
|
||||
assert "language that doesn't exist" not in item.name_map
|
||||
assert tables.Language() not in item.name_map
|
||||
def test_string_mapping():
|
||||
item = connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
assert len(item.name_map) == len(item.names)
|
||||
for lang in item.names:
|
||||
assert item.name_map[lang] == item.names[lang].name
|
||||
assert lang in item.name_map
|
||||
assert "language that doesn't exist" not in item.name_map
|
||||
assert tables.Language() not in item.name_map
|
||||
|
||||
def test_new_language(self):
|
||||
item = self.connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
language = tables.Language()
|
||||
language.id = -1
|
||||
language.identifier = u'test'
|
||||
language.iso639 = language.iso3166 = u'--'
|
||||
language.official = False
|
||||
self.connection.add(language)
|
||||
item.name_map[language] = u"foo"
|
||||
assert item.name_map[language] == "foo"
|
||||
assert language in item.name_map
|
||||
item.name_map[language] = u"xyzzy"
|
||||
assert item.name_map[language] == "xyzzy"
|
||||
def test_new_language():
|
||||
item = connection.query(tables.Item).filter_by(
|
||||
identifier=u"jade-orb").one()
|
||||
language = tables.Language()
|
||||
language.id = -1
|
||||
language.identifier = u'test'
|
||||
language.iso639 = language.iso3166 = u'--'
|
||||
language.official = False
|
||||
connection.add(language)
|
||||
item.name_map[language] = u"foo"
|
||||
assert item.name_map[language] == "foo"
|
||||
assert language in item.name_map
|
||||
item.name_map[language] = u"xyzzy"
|
||||
assert item.name_map[language] == "xyzzy"
|
||||
|
||||
def test_markdown(self):
|
||||
move = self.connection.query(tables.Move).filter_by(
|
||||
identifier=u"thunderbolt").one()
|
||||
language = self.connection.query(tables.Language).filter_by(
|
||||
identifier=u"en").one()
|
||||
assert '10%' in move.effect.as_text()
|
||||
assert '10%' in move.effect_map[language].as_text()
|
||||
assert '10%' in move.effect.as_html()
|
||||
assert '10%' in move.effect_map[language].as_html()
|
||||
assert '10%' in unicode(move.effect)
|
||||
assert '10%' in unicode(move.effect_map[language])
|
||||
assert '10%' in move.effect.__html__()
|
||||
assert '10%' in move.effect_map[language].__html__()
|
||||
def test_markdown():
|
||||
move = connection.query(tables.Move).filter_by(
|
||||
identifier=u"thunderbolt").one()
|
||||
language = connection.query(tables.Language).filter_by(
|
||||
identifier=u"en").one()
|
||||
assert '10%' in move.effect.as_text()
|
||||
assert '10%' in move.effect_map[language].as_text()
|
||||
assert '10%' in move.effect.as_html()
|
||||
assert '10%' in move.effect_map[language].as_html()
|
||||
assert '10%' in unicode(move.effect)
|
||||
assert '10%' in unicode(move.effect_map[language])
|
||||
assert '10%' in move.effect.__html__()
|
||||
assert '10%' in move.effect_map[language].__html__()
|
||||
|
||||
def test_markdown_string(self):
|
||||
en = util.get(self.connection, tables.Language, 'en')
|
||||
md = markdown.MarkdownString('[]{move:thunderbolt} [paralyzes]{mechanic:paralysis}', self.connection, en)
|
||||
assert unicode(md) == 'Thunderbolt paralyzes'
|
||||
assert md.as_html() == '<p><span>Thunderbolt</span> <span>paralyzes</span></p>'
|
||||
assert md.as_html(object_url=lambda category, obj: "%s/%s" % (category, obj.identifier)) == (
|
||||
'<p><a href="move/thunderbolt">Thunderbolt</a> <span>paralyzes</span></p>')
|
||||
print md.as_html(identifier_url=lambda category, ident: "%s/%s" % (category, ident))
|
||||
assert md.as_html(identifier_url=lambda category, ident: "%s/%s" % (category, ident)) == (
|
||||
'<p><a href="move/thunderbolt">Thunderbolt</a> <a href="mechanic/paralysis">paralyzes</a></p>')
|
||||
def test_markdown_string():
|
||||
en = util.get(connection, tables.Language, 'en')
|
||||
md = markdown.MarkdownString('[]{move:thunderbolt} [paralyzes]{mechanic:paralysis}', connection, en)
|
||||
assert unicode(md) == 'Thunderbolt paralyzes'
|
||||
assert md.as_html() == '<p><span>Thunderbolt</span> <span>paralyzes</span></p>'
|
||||
assert md.as_html(object_url=lambda category, obj: "%s/%s" % (category, obj.identifier)) == (
|
||||
'<p><a href="move/thunderbolt">Thunderbolt</a> <span>paralyzes</span></p>')
|
||||
print md.as_html(identifier_url=lambda category, ident: "%s/%s" % (category, ident))
|
||||
assert md.as_html(identifier_url=lambda category, ident: "%s/%s" % (category, ident)) == (
|
||||
'<p><a href="move/thunderbolt">Thunderbolt</a> <a href="mechanic/paralysis">paralyzes</a></p>')
|
||||
|
||||
def test_markdown_values(self):
|
||||
"""Check all markdown values
|
||||
def markdown_column_params():
|
||||
"""Check all markdown values
|
||||
|
||||
Scans the database schema for Markdown columns, runs through every value
|
||||
in each, and ensures that it's valid Markdown.
|
||||
"""
|
||||
Scans the database schema for Markdown columns, runs through every value
|
||||
in each, and ensures that it's valid Markdown.
|
||||
"""
|
||||
|
||||
# Move effects have their own special wrappers. Explicitly test them separately
|
||||
yield self.check_markdown_column, tables.Move, None, 'effect'
|
||||
yield self.check_markdown_column, tables.Move, None, 'short_effect'
|
||||
# Move effects have their own special wrappers. Explicitly test them separately
|
||||
yield tables.Move, None, 'effect'
|
||||
yield tables.Move, None, 'short_effect'
|
||||
|
||||
for cls in tables.mapped_classes:
|
||||
for translation_cls in cls.translation_classes:
|
||||
for column in translation_cls.__table__.c:
|
||||
if column.info.get('string_getter') == markdown.MarkdownString:
|
||||
yield self.check_markdown_column, cls, translation_cls, column.name
|
||||
for cls in tables.mapped_classes:
|
||||
for translation_cls in cls.translation_classes:
|
||||
for column in translation_cls.__table__.c:
|
||||
if column.info.get('string_getter') == markdown.MarkdownString:
|
||||
yield cls, translation_cls, column.name
|
||||
|
||||
def check_markdown_column(self, parent_class, translation_class, column_name):
|
||||
"""Implementation for the above"""
|
||||
query = self.connection.query(parent_class)
|
||||
if translation_class:
|
||||
query = query.join(translation_class)
|
||||
for item in query:
|
||||
for language, markdown in getattr(item, column_name + '_map').items():
|
||||
@positional_params(*markdown_column_params())
|
||||
def test_markdown_values(parent_class, translation_class, column_name):
|
||||
"""Implementation for the above"""
|
||||
query = connection.query(parent_class)
|
||||
if translation_class:
|
||||
query = query.join(translation_class)
|
||||
for item in query:
|
||||
for language, markdown in getattr(item, column_name + '_map').items():
|
||||
|
||||
if markdown is None:
|
||||
continue
|
||||
if markdown is None:
|
||||
continue
|
||||
|
||||
key = u"Markdown in {0} #{1}'s {2} (lang={3})".format(
|
||||
parent_class.__name__, item.id, column_name, language.identifier)
|
||||
key = u"Markdown in {0} #{1}'s {2} (lang={3})".format(
|
||||
parent_class.__name__, item.id, column_name, language.identifier)
|
||||
|
||||
try:
|
||||
text = markdown.as_text()
|
||||
except NoResultFound:
|
||||
assert False, u"{0} references something that doesn't exist:\n{1}".format(
|
||||
key, markdown.source_text)
|
||||
except AttributeError:
|
||||
print markdown
|
||||
raise
|
||||
try:
|
||||
text = markdown.as_text()
|
||||
except NoResultFound:
|
||||
assert False, u"{0} references something that doesn't exist:\n{1}".format(
|
||||
key, markdown.source_text)
|
||||
except AttributeError:
|
||||
print markdown
|
||||
raise
|
||||
|
||||
error_message = u"{0} leaves syntax cruft:\n{1}"
|
||||
error_message = error_message.format(key, text)
|
||||
error_message = u"{0} leaves syntax cruft:\n{1}"
|
||||
error_message = error_message.format(key, text)
|
||||
|
||||
ok_(not any(char in text for char in '[]{}'), error_message)
|
||||
assert not any(char in text for char in '[]{}'), error_message
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import csv
|
||||
|
||||
from nose.tools import *
|
||||
import pytest
|
||||
|
||||
from pokedex.db import translations, tables
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# encoding: utf8
|
||||
from nose.tools import *
|
||||
import unittest
|
||||
# Encoding: utf8
|
||||
|
||||
import pytest
|
||||
|
||||
from pokedex.tests import single_params
|
||||
from pokedex.db import connect, tables, util
|
||||
|
||||
session = connect()
|
||||
|
@ -18,21 +19,21 @@ def test_get_english_by_identifier():
|
|||
language = util.get(session, tables.Language, 'en')
|
||||
assert language.name == 'English'
|
||||
|
||||
def test_get_pokemon_identifier():
|
||||
for identifier in 'burmy shaymin unown cresselia'.split():
|
||||
poke = util.get(session, tables.PokemonSpecies, identifier=identifier)
|
||||
assert poke.identifier == identifier
|
||||
@single_params(*'burmy shaymin unown cresselia'.split())
|
||||
def test_get_pokemon_identifier(identifier):
|
||||
poke = util.get(session, tables.PokemonSpecies, identifier=identifier)
|
||||
assert poke.identifier == identifier
|
||||
|
||||
def test_get_pokemon_name():
|
||||
for name in 'Burmy Shaymin Unown Cresselia'.split():
|
||||
poke = util.get(session, tables.PokemonSpecies, name=name)
|
||||
assert poke.name == name
|
||||
@single_params(*'Burmy Shaymin Unown Cresselia'.split())
|
||||
def test_get_pokemon_name(name):
|
||||
poke = util.get(session, tables.PokemonSpecies, name=name)
|
||||
assert poke.name == name
|
||||
|
||||
def test_get_pokemon_name_explicit_language():
|
||||
@single_params(*'Cheniti Shaymin Zarbi Cresselia'.split())
|
||||
def test_get_pokemon_name_explicit_language(name):
|
||||
french = util.get(session, tables.Language, 'fr')
|
||||
for name in 'Cheniti Shaymin Zarbi Cresselia'.split():
|
||||
poke = util.get(session, tables.PokemonSpecies, name=name, language=french)
|
||||
assert poke.name_map[french] == name, poke.name_map[french]
|
||||
poke = util.get(session, tables.PokemonSpecies, name=name, language=french)
|
||||
assert poke.name_map[french] == name, poke.name_map[french]
|
||||
|
||||
def test_types_french_order():
|
||||
french = util.get(session, tables.Language, 'fr')
|
||||
|
@ -40,3 +41,9 @@ def test_types_french_order():
|
|||
types = list(util.order_by_name(types, tables.Type, language=french))
|
||||
assert types[0].name_map[french] == 'Acier', types[0].name_map[french]
|
||||
assert types[-1].name_map[french] == 'Vol', types[-1].name_map[french]
|
||||
|
||||
@single_params(*range(1, 10) * 2)
|
||||
def test_get_pokemon_id(id):
|
||||
result = util.get(session, tables.Pokemon, id=id)
|
||||
assert result.id == id
|
||||
assert result.__tablename__ == 'pokemon'
|
||||
|
|
Loading…
Reference in a new issue