Compare commits
2 commits
7ee8398718
...
7002986cb7
Author | SHA1 | Date | |
---|---|---|---|
7002986cb7 | |||
2edeac0d83 |
|
@ -5,6 +5,12 @@ All notable changes to WuttJamaican will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## v0.13.1 (2024-08-27)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- add common `DataTestCase` for use in other packages
|
||||||
|
|
||||||
## v0.13.0 (2024-08-26)
|
## v0.13.0 (2024-08-26)
|
||||||
|
|
||||||
### Feat
|
### Feat
|
||||||
|
|
|
@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "WuttJamaican"
|
name = "WuttJamaican"
|
||||||
version = "0.13.0"
|
version = "0.13.1"
|
||||||
description = "Base package for Wutta Framework"
|
description = "Base package for Wutta Framework"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
|
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
|
||||||
|
|
|
@ -30,22 +30,27 @@ import tempfile
|
||||||
import warnings
|
import warnings
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from wuttjamaican.conf import WuttaConfig
|
||||||
|
|
||||||
class FileConfigTestCase(TestCase):
|
|
||||||
|
class FileTestCase(TestCase):
|
||||||
"""
|
"""
|
||||||
Common base class for test suites which write temporary files, for
|
Base class for test suites which (may) write temporary files, for
|
||||||
sake of testing the config constructor etc.
|
sake of testing the config constructor etc. It inherits from
|
||||||
|
:class:`python:unittest.TestCase`.
|
||||||
|
|
||||||
This inherits from :class:`python:unittest.TestCase` and adds the
|
This class creates a temporary folder on setup, and removes it on
|
||||||
following features:
|
teardown. See below for features exposed to work with the folder.
|
||||||
|
|
||||||
Creates a temporary folder on setup, and removes it on teardown.
|
|
||||||
Adds the :meth:`write_file()` method to help with creating
|
|
||||||
temporary files.
|
|
||||||
|
|
||||||
.. attribute:: tempdir
|
.. attribute:: tempdir
|
||||||
|
|
||||||
Path to the temporary folder created during setup.
|
Path to the temporary folder created during setup.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you subclass this and need to override setup/teardown,
|
||||||
|
please be sure to call the corresponding methods for this
|
||||||
|
class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -54,8 +59,6 @@ class FileConfigTestCase(TestCase):
|
||||||
|
|
||||||
def setup_files(self):
|
def setup_files(self):
|
||||||
"""
|
"""
|
||||||
Setup logic specific to the ``FileConfigTestCase``.
|
|
||||||
|
|
||||||
This creates the temporary folder.
|
This creates the temporary folder.
|
||||||
"""
|
"""
|
||||||
self.tempdir = tempfile.mkdtemp()
|
self.tempdir = tempfile.mkdtemp()
|
||||||
|
@ -73,8 +76,6 @@ class FileConfigTestCase(TestCase):
|
||||||
|
|
||||||
def teardown_files(self):
|
def teardown_files(self):
|
||||||
"""
|
"""
|
||||||
Teardown logic specific to the ``FileConfigTestCase``.
|
|
||||||
|
|
||||||
This removes the temporary folder.
|
This removes the temporary folder.
|
||||||
"""
|
"""
|
||||||
shutil.rmtree(self.tempdir)
|
shutil.rmtree(self.tempdir)
|
||||||
|
@ -105,3 +106,73 @@ class FileConfigTestCase(TestCase):
|
||||||
Note that this will be created *underneath* :attr:`tempdir`.
|
Note that this will be created *underneath* :attr:`tempdir`.
|
||||||
"""
|
"""
|
||||||
return tempfile.mkdtemp(dir=self.tempdir)
|
return tempfile.mkdtemp(dir=self.tempdir)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: deprecate / remove this
|
||||||
|
FileConfigTestCase = FileTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class DataTestCase(FileTestCase):
|
||||||
|
"""
|
||||||
|
Base class for test suites requiring a full (typical) database.
|
||||||
|
|
||||||
|
It inherits from :class:`FileTestCase` so also has the
|
||||||
|
file-related methods.
|
||||||
|
|
||||||
|
This uses a SQLite in-memory database and creates all tables for
|
||||||
|
the app model. The running test has these attributes:
|
||||||
|
|
||||||
|
.. attribute:: config
|
||||||
|
|
||||||
|
Reference to the config object.
|
||||||
|
|
||||||
|
.. attribute:: app
|
||||||
|
|
||||||
|
Reference to the app handler.
|
||||||
|
|
||||||
|
.. attribute:: session
|
||||||
|
|
||||||
|
Open session for the test DB.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you subclass this and need to override setup/teardown,
|
||||||
|
please be sure to call the corresponding methods for this
|
||||||
|
class.
|
||||||
|
|
||||||
|
However you do *not* need to call the file-related setup or
|
||||||
|
teardown methods, as this class handles that automatically.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
""" """
|
||||||
|
self.setup_db()
|
||||||
|
|
||||||
|
def setup_db(self):
|
||||||
|
"""
|
||||||
|
Perform config/app/db setup operations for the test.
|
||||||
|
"""
|
||||||
|
self.setup_files()
|
||||||
|
self.config = self.make_config(defaults={
|
||||||
|
'wutta.db.default.url': 'sqlite://',
|
||||||
|
})
|
||||||
|
self.app = self.config.get_app()
|
||||||
|
|
||||||
|
# init db
|
||||||
|
model = self.app.model
|
||||||
|
model.Base.metadata.create_all(bind=self.config.appdb_engine)
|
||||||
|
self.session = self.app.make_session()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
""" """
|
||||||
|
self.teardown_db()
|
||||||
|
|
||||||
|
def teardown_db(self):
|
||||||
|
"""
|
||||||
|
Perform config/app/db teardown operations for the test.
|
||||||
|
"""
|
||||||
|
self.teardown_files()
|
||||||
|
|
||||||
|
def make_config(self, **kwargs):
|
||||||
|
""" """
|
||||||
|
return WuttaConfig(**kwargs)
|
||||||
|
|
|
@ -15,10 +15,10 @@ from wuttjamaican import app
|
||||||
from wuttjamaican.progress import ProgressBase
|
from wuttjamaican.progress import ProgressBase
|
||||||
from wuttjamaican.conf import WuttaConfig
|
from wuttjamaican.conf import WuttaConfig
|
||||||
from wuttjamaican.util import UNSPECIFIED
|
from wuttjamaican.util import UNSPECIFIED
|
||||||
from wuttjamaican.testing import FileConfigTestCase
|
from wuttjamaican.testing import FileTestCase
|
||||||
|
|
||||||
|
|
||||||
class TestAppHandler(FileConfigTestCase):
|
class TestAppHandler(FileTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.setup_files()
|
self.setup_files()
|
||||||
|
|
|
@ -10,10 +10,10 @@ import pytest
|
||||||
from wuttjamaican import conf
|
from wuttjamaican import conf
|
||||||
from wuttjamaican.exc import ConfigurationError
|
from wuttjamaican.exc import ConfigurationError
|
||||||
from wuttjamaican.app import AppHandler
|
from wuttjamaican.app import AppHandler
|
||||||
from wuttjamaican.testing import FileConfigTestCase
|
from wuttjamaican.testing import FileTestCase
|
||||||
|
|
||||||
|
|
||||||
class TestWuttaConfig(FileConfigTestCase):
|
class TestWuttaConfig(FileTestCase):
|
||||||
|
|
||||||
def test_contstructor_basic(self):
|
def test_contstructor_basic(self):
|
||||||
config = conf.WuttaConfig()
|
config = conf.WuttaConfig()
|
||||||
|
@ -505,7 +505,7 @@ class TestGenericDefaultFiles(TestCase):
|
||||||
self.assertEqual(len(files), 0)
|
self.assertEqual(len(files), 0)
|
||||||
|
|
||||||
|
|
||||||
class TestGetConfigPaths(FileConfigTestCase):
|
class TestGetConfigPaths(FileTestCase):
|
||||||
|
|
||||||
def test_winsvc(self):
|
def test_winsvc(self):
|
||||||
myconf = self.write_file('my.conf', """
|
myconf = self.write_file('my.conf', """
|
||||||
|
@ -523,7 +523,7 @@ winsvc.RattailFileMonitor = /path/to/other/file
|
||||||
self.assertEqual(files, [])
|
self.assertEqual(files, [])
|
||||||
|
|
||||||
|
|
||||||
class TestMakeConfig(FileConfigTestCase):
|
class TestMakeConfig(FileTestCase):
|
||||||
|
|
||||||
# nb. we use appname='wuttatest' in this suite to avoid any
|
# nb. we use appname='wuttatest' in this suite to avoid any
|
||||||
# "valid" default config files, env vars etc. which may be present
|
# "valid" default config files, env vars etc. which may be present
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
# -*- coding: utf-8; -*-
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from wuttjamaican import people as mod
|
from wuttjamaican import people as mod
|
||||||
from wuttjamaican.conf import WuttaConfig
|
from wuttjamaican.testing import DataTestCase
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
@ -12,41 +10,29 @@ except ImportError:
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
|
||||||
class TestPeopleHandler(TestCase):
|
class TestPeopleHandler(DataTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def make_handler(self):
|
||||||
self.config = WuttaConfig()
|
return mod.PeopleHandler(self.config)
|
||||||
self.app = self.config.get_app()
|
|
||||||
self.handler = mod.PeopleHandler(self.config)
|
|
||||||
|
|
||||||
self.engine = sa.create_engine('sqlite://')
|
|
||||||
self.app.model.Base.metadata.create_all(bind=self.engine)
|
|
||||||
self.session = self.make_session()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.session.close()
|
|
||||||
self.app.model.Base.metadata.drop_all(bind=self.engine)
|
|
||||||
|
|
||||||
def make_session(self):
|
|
||||||
return self.app.make_session(bind=self.engine)
|
|
||||||
|
|
||||||
def test_get_person(self):
|
def test_get_person(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
myperson = model.Person(full_name='Barny Rubble')
|
myperson = model.Person(full_name='Barny Rubble')
|
||||||
self.session.add(myperson)
|
self.session.add(myperson)
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
|
handler = self.make_handler()
|
||||||
|
|
||||||
# empty obj is ignored
|
# empty obj is ignored
|
||||||
person = self.handler.get_person(None)
|
person = handler.get_person(None)
|
||||||
self.assertIsNone(person)
|
self.assertIsNone(person)
|
||||||
|
|
||||||
# person is returned as-is
|
# person is returned as-is
|
||||||
person = self.handler.get_person(myperson)
|
person = handler.get_person(myperson)
|
||||||
self.assertIs(person, myperson)
|
self.assertIs(person, myperson)
|
||||||
|
|
||||||
# find person from user
|
# find person from user
|
||||||
myuser = model.User(username='barney', person=myperson)
|
myuser = model.User(username='barney', person=myperson)
|
||||||
self.session.add(myuser)
|
self.session.add(myuser)
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
person = self.handler.get_person(myuser)
|
person = handler.get_person(myuser)
|
||||||
self.assertIs(person, myperson)
|
self.assertIs(person, myperson)
|
||||||
|
|
Loading…
Reference in a new issue