Skip to content
This repository has been archived by the owner on Jan 7, 2019. It is now read-only.

Commit

Permalink
All tests are now passing with the new Twisted trial runner.
Browse files Browse the repository at this point in the history
  • Loading branch information
gtaylor committed Sep 28, 2013
1 parent 7be4b44 commit cae324b
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 89 deletions.
8 changes: 7 additions & 1 deletion run_tests.sh
@@ -1,2 +1,8 @@
#!/bin/bash
PYTHONPATH=. nosetests -s --nologcapture
PYTHONPATH=. trial \
src.accounts.tests \
src.game.parents.base_objects.tests \
src.daemons.server.commands.tests \
src.daemons.server.objects.tests \
src.daemons.server.objects.parent_loader.tests

1 change: 1 addition & 0 deletions src/accounts/account_store.py
@@ -1,3 +1,4 @@
# -*- test-case-name: src.accounts.tests -*-
"""
Lower level account management.
"""
Expand Down
11 changes: 5 additions & 6 deletions src/accounts/db_io.py
Expand Up @@ -31,16 +31,18 @@ class DBManager(object):
" FROM dott_accounts"
)

def __init__(self, store, db_name=None):
def __init__(self, store, db_name=None, db_user=None):
"""
:keyword AccountStore store: The account store this instance manages.
:keyword str db_name: Overrides the DB name for the object DB. Currently
just used for unit testing.
:keyword str db_name: Overrides the DB user for the object DB. Currently
just used for unit testing.
"""

self.store = store

self._db_name = db_name or settings.DATABASE_NAME
self._db_user = db_user or settings.DATABASE_USERNAME
# This eventually contains a txpostgres Connection object, which is
# where we can query.
self._db = None
Expand All @@ -56,10 +58,7 @@ def prepare_and_load(self):
self.store._accounts = {}
# Instantiate the connection to Postgres.
self._db = txPGDictConnection()
yield self._db.connect(
user=settings.DATABASE_USERNAME,
database=self._db_name
)
yield self._db.connect(user=self._db_user, database=self._db_name)

@inlineCallbacks
def get_account_count(self):
Expand Down
5 changes: 0 additions & 5 deletions src/accounts/tests.py
Expand Up @@ -55,12 +55,7 @@ class ValidatorTests(DottTestCase):
Tests some account-related validators. These mostly come into play
during registration and login, but they are of general use.
"""
def setUp(self):
pass

def tearDown(self):
pass

def test_email_validator(self):
"""
Tests the email validation function.
Expand Down
15 changes: 14 additions & 1 deletion src/daemons/server/commands/tests.py
@@ -1,16 +1,22 @@
from twisted.internet.defer import inlineCallbacks
from src.utils.test_utils import DottTestCase
from src.daemons.server.commands.parser import CommandParser, ParsedCommand
from src.daemons.server.commands.cmdtable import CommandTable, DuplicateCommandException
from src.daemons.server.commands.command import BaseCommand


class CommandTableTests(DottTestCase):

@inlineCallbacks
def setUp(self):
super(CommandTableTests, self).setUp()
yield super(CommandTableTests, self).setUp()

self.table = CommandTable()

@inlineCallbacks
def tearDown(self):
yield super(CommandTableTests, self).tearDown()

del self.table

def test_add_and_lookup(self):
Expand Down Expand Up @@ -75,10 +81,17 @@ def test_add_duplicate_alias(self):


class CommandParserTests(DottTestCase):

@inlineCallbacks
def setUp(self):
yield super(CommandParserTests, self).setUp()

self.parser = CommandParser()

@inlineCallbacks
def tearDown(self):
yield super(CommandParserTests, self).tearDown()

del self.parser

def test_simple_command(self):
Expand Down
13 changes: 5 additions & 8 deletions src/daemons/server/objects/parent_loader/tests.py
@@ -1,13 +1,10 @@
import unittest
from src.daemons.server.objects.parent_loader.loader import ParentLoader
from src.utils.test_utils import DottTestCase

class ParentLoaderTests(unittest.TestCase):
def setUp(self):
self.loader = ParentLoader()

def tearDown(self):
del self.loader
class ParentLoaderTests(DottTestCase):

def test_simple_load(self):
parent = self.loader.load_parent('src.game.parents.base_objects.room.RoomObject')
loader = self.object_store.parent_loader

parent = loader.load_parent('src.game.parents.base_objects.room.RoomObject')
self.assertEqual(parent.__name__, 'RoomObject')
15 changes: 0 additions & 15 deletions src/daemons/server/objects/tests.py
Expand Up @@ -14,21 +14,6 @@ class InMemoryObjectStoreTests(DottTestCase):
Testing of the ObjectStore storage backend.
"""

def test_starter_room_creation(self):
"""
Makes sure the default DB is created with one room. Check some
of the default values on it.
"""

num_objects = len(self.object_store._objects)
# There should only be one object at this point.
self.assertEqual(num_objects, 1)

# Get the starter room instance.
room_id, room = self.object_store._objects.items()[0]
# It should have been created with the standard room parent.
self.assertEqual(room.parent, settings.ROOM_PARENT)

@inlineCallbacks
def test_create_room(self):
"""
Expand Down
67 changes: 44 additions & 23 deletions src/game/parents/base_objects/base.py
@@ -1,10 +1,16 @@
"""
Contains base level parents that aren't to be used directly.
"""

from twisted.internet.defer import inlineCallbacks, returnValue
from fuzzywuzzy import fuzz
from fuzzywuzzy.process import WRatio
from fuzzywuzzy import utils as fuzz_utils

#from src.utils import logger
from src.daemons.server.protocols.proxyamp import EmitToObjectCmd


#noinspection PyShadowingBuiltins
class BaseObject(object):
"""
This is the base parent for every in-game "object". Rooms, Players, and
Expand Down Expand Up @@ -65,6 +71,12 @@ def __init__(self, mud_service, id, parent, name, description=None,

assert isinstance(self._attributes, dict)

def __str__(self):
return "<%s: %s (#%d)>" % (self.__class__.__name__, self.name, self.id)

def __repr__(self):
return self.__str__()

#
## Begin properties.
#
Expand Down Expand Up @@ -122,7 +134,6 @@ def set_location(self, obj_or_id):
# Already an int, assume this is an object ID.
self.location_id = obj_or_id
elif isinstance(obj_or_id, basestring):
# TODO: This should be removable in the future.
raise Exception("BaseObject.set_location() can't accept strings: %s" % obj_or_id)
else:
# Looks like a BaseObject sub-class. Grab the object ID.
Expand All @@ -148,11 +159,10 @@ def set_attributes(self, attrib_dict):
if not isinstance(attrib_dict, dict):
raise Exception(
"BaseObject.set_attributes() passed an invalid type: %s (%s)" % (
attrib_dict, type(attrib_dict)
))
attrib_dict, type(attrib_dict)))
else:
# Looks like a BaseObject sub-class. Grab the object ID.
self.attributes = attrib_dict
self._attributes = attrib_dict
attributes = property(get_attributes, set_attributes)

def get_zone(self):
Expand All @@ -168,6 +178,7 @@ def get_zone(self):
return self._object_store.get_object(self.zone_id)
else:
return None

def set_zone(self, obj_or_id):
"""
Sets this object's zone.
Expand All @@ -181,7 +192,6 @@ def set_zone(self, obj_or_id):
# Already an int, assume this is an object ID.
self.zone_id = obj_or_id
elif isinstance(obj_or_id, basestring):
# TODO: This should be removable in the future.
raise Exception("BaseObject.set_zone() can't accept strings: %s" % obj_or_id)
elif obj_or_id is None:
self.zone_id = None
Expand Down Expand Up @@ -280,7 +290,7 @@ def emit_to_contents(self, message, exclude=None):
:param str message: The message to emit to any object within
this one.
:keyword BaseObject exclude: A list of objects who are to be
:param BaseObject exclude: A list of objects who are to be
excluded from the emit list. These objects will not see the emit.
"""

Expand All @@ -299,6 +309,8 @@ def move_to(self, destination_obj, force_look=True):
Moves this object to the given destination.
:param BaseObject destination_obj: Where to move this object to.
:param bool force_look: If True, the object will run the "look"
command between movements.
"""

old_location_obj = self.location
Expand Down Expand Up @@ -345,7 +357,7 @@ def get_description(self, invoker, from_inside=False):
Returns the description of this object.
:param BaseObject invoker: The object asking for the description.
:keyword bool from_inside: If True, use an internal description instead
:param bool from_inside: If True, use an internal description instead
of the normal description, if available. For example, the inside
of a vehicle should have a different description than the outside.
"""
Expand Down Expand Up @@ -400,7 +412,7 @@ def get_appearance_contents_and_exits(self, invoker, from_inside=False):
Returns the contents and exits display for the object.
:param BaseObject invoker: The object asking for the appearance.
:keyword bool from_inside: Show the contents/exits as if the invoker
:param bool from_inside: Show the contents/exits as if the invoker
was inside this object.
:rtype: str
:returns: The contents/exits display.
Expand Down Expand Up @@ -460,33 +472,42 @@ def get_appearance(self, invoker):

return "%s\n%s\n%s" % (name, desc, contents)

def _find_name_or_alias_match(self, objects, desc):
def _find_name_or_alias_match(self, objects, query):
"""
Performs name and alias matches on a list of objects. Returns the
best match, or ``None`` if nothing was found.
:param iterable objects: A list of ``BaseObject`` sub-class instances
to attempt to match to.
:param str desc: The string to match against.
:param str query: The string to match against.
"""

ratio = 0
result = None
if not objects:
return None

for obj in objects:
# Start by checking all objects for an alias match.
aliases = [alias.lower() for alias in obj.aliases]
if desc.lower() in aliases:
if query.lower() in aliases:
# If a match is found, return immediately on said match.
return obj

# No alias match found, so now we fuzzy match
r = fuzz.partial_ratio(desc, obj.name)
#noinspection PyChainedComparisons
if r > 50 and r > ratio:
ratio = r
result = obj
processor = lambda x: fuzz_utils.full_process(x)
scorer = WRatio
results = list()

for choice in objects:
processed = processor(choice.name)
score = scorer(query, processed)
result = (choice, score)
if score > 0:
results.append(result)

return result
if not results:
return None
else:
results.sort(key=lambda i: i[1], reverse=True)
return results[0][0]

def _find_object_id_match(self, desc):
"""
Expand Down Expand Up @@ -518,13 +539,13 @@ def _find_object_id_match(self, desc):
# are in the same place.
#noinspection PyUnresolvedReferences
location_match = self.location.id == obj.location.id or \
self.location.id == obj.id
self.location.id == obj.id
if location_match:
# Locations match. Good to go.
return obj
elif obj.base_type == 'room':
#noinspection PyUnresolvedReferences
if self.location and self.location.id == obj.id:
if self.location and self.location.id == obj.id:
# Non-admin is looking at their current location, which
# is a room.
return obj
Expand Down
3 changes: 2 additions & 1 deletion src/game/parents/base_objects/tests.py
Expand Up @@ -35,11 +35,12 @@ def test_get_location(self):
"""
Tests the objects' get_location function
"""

obj1 = yield self.object_store.create_object(settings.ROOM_PARENT, name='obj1')
self.assertEqual(obj1.get_location(), None)

obj2 = yield self.object_store.create_object(
settings.BASE_PARENT,
settings.THING_PARENT,
location_id=obj1.id,
name='obj2')
self.assertEqual(obj2.get_location(), obj1)
Expand Down

0 comments on commit cae324b

Please sign in to comment.