Got nearly 100% test coverage for AnkiServer/collection.py

This commit is contained in:
David Snopek 2013-07-15 15:27:13 +01:00
parent e25cf25684
commit f707c8409c
3 changed files with 149 additions and 2 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
*~
*.pyc
.coverage
AnkiServer.egg-info
development.ini
server.log

View File

@ -22,6 +22,10 @@ class CollectionWrapper(object):
self.setup_new_collection = setup_new_collection
self.__col = None
def __del__(self):
"""Close the collection if the user forgot to do so."""
self.close()
def execute(self, func, args=[], kw={}, waitForReturn=True):
""" Executes the given function with the underlying anki.storage.Collection
object as the first argument and any additional arguments specified by *args
@ -55,11 +59,13 @@ class CollectionWrapper(object):
else:
raise
self.__col = ank.storage.Collection(self.path)
col = anki.storage.Collection(self.path)
# Do any special setup
if self.setup_new_collection is not None:
self.setup_new_collection(self.__col)
self.setup_new_collection(col)
return col
def open(self):
"""Open the collection, or create it if it doesn't exist."""

140
tests/test_collection.py Normal file
View File

@ -0,0 +1,140 @@
import os
import shutil
import tempfile
import unittest
import mock
from mock import MagicMock, sentinel
import AnkiServer
from AnkiServer.collection import CollectionWrapper, CollectionManager
class CollectionWrapperTest(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.collection_path = os.path.join(self.temp_dir, 'collection.anki2');
def tearDown(self):
shutil.rmtree(self.temp_dir)
def test_lifecycle_real(self):
"""Testing common life-cycle with existing and non-existant collections. This
test uses the real Anki objects and actually creates a new collection on disk."""
wrapper = CollectionWrapper(self.collection_path)
self.assertFalse(os.path.exists(self.collection_path))
self.assertFalse(wrapper.opened())
wrapper.open()
self.assertTrue(os.path.exists(self.collection_path))
self.assertTrue(wrapper.opened())
# calling open twice shouldn't break anything
wrapper.open()
wrapper.close()
self.assertTrue(os.path.exists(self.collection_path))
self.assertFalse(wrapper.opened())
# open the same collection again (not a creation)
wrapper = CollectionWrapper(self.collection_path)
self.assertFalse(wrapper.opened())
wrapper.open()
self.assertTrue(wrapper.opened())
wrapper.close()
self.assertFalse(wrapper.opened())
self.assertTrue(os.path.exists(self.collection_path))
def test_del(self):
with mock.patch('anki.storage.Collection') as anki_storage_Collection:
col = anki_storage_Collection.return_value
wrapper = CollectionWrapper(self.collection_path)
wrapper.open()
wrapper = None
col.close.assert_called_with()
def test_setup_func(self):
# Run it when the collection doesn't exist
with mock.patch('anki.storage.Collection') as anki_storage_Collection:
col = anki_storage_Collection.return_value
setup_new_collection = MagicMock()
self.assertFalse(os.path.exists(self.collection_path))
wrapper = CollectionWrapper(self.collection_path, setup_new_collection)
wrapper.open()
anki_storage_Collection.assert_called_with(self.collection_path)
setup_new_collection.assert_called_with(col)
wrapper = None
# Make sure that no collection was actually created
self.assertFalse(os.path.exists(self.collection_path))
# Create a faux collection file
with file(self.collection_path, 'wt') as fd:
fd.write('Collection!')
# Run it when the collection does exist
with mock.patch('anki.storage.Collection'):
setup_new_collection = lambda col: self.fail("Setup function called when collection already exists!")
self.assertTrue(os.path.exists(self.collection_path))
wrapper = CollectionWrapper(self.collection_path, setup_new_collection)
wrapper.open()
anki_storage_Collection.assert_called_with(self.collection_path)
wrapper = None
def test_execute(self):
with mock.patch('anki.storage.Collection') as anki_storage_Collection:
col = anki_storage_Collection.return_value
func = MagicMock()
func.return_value = sentinel.some_object
# check that execute works and auto-creates the collection
wrapper = CollectionWrapper(self.collection_path)
ret = wrapper.execute(func, [1, 2, 3], {'key': 'aoeu'})
self.assertEqual(ret, sentinel.some_object)
anki_storage_Collection.assert_called_with(self.collection_path)
func.assert_called_with(col, 1, 2, 3, key='aoeu')
# check that execute always returns False if waitForReturn=False
func.reset_mock()
ret = wrapper.execute(func, [1, 2, 3], {'key': 'aoeu'}, waitForReturn=False)
self.assertEqual(ret, None)
func.assert_called_with(col, 1, 2, 3, key='aoeu')
class CollectionManagerTest(unittest.TestCase):
def test_lifecycle(self):
with mock.patch('AnkiServer.collection.CollectionManager.collection_wrapper') as CollectionWrapper:
wrapper = MagicMock()
CollectionWrapper.return_value = wrapper
manager = CollectionManager()
# check getting a new collection
ret = manager.get_collection('path1')
CollectionWrapper.assert_called_with(os.path.realpath('path1'), None)
self.assertEqual(ret, wrapper)
# change the return value, so that it would return a new object
new_wrapper = MagicMock()
CollectionWrapper.return_value = new_wrapper
CollectionWrapper.reset_mock()
# get the new wrapper
ret = manager.get_collection('path2')
CollectionWrapper.assert_called_with(os.path.realpath('path2'), None)
self.assertEqual(ret, new_wrapper)
# make sure the wrapper and new_wrapper are different
self.assertNotEqual(wrapper, new_wrapper)
# assert that calling with the first path again, returns the first wrapper
ret = manager.get_collection('path1')
self.assertEqual(ret, wrapper)
manager.shutdown()
wrapper.close.assert_called_with()
new_wrapper.close.assert_called_with()
if __name__ == '__main__':
unittest.main()