reorganized unit tests and fixed bug in cache handling

This commit is contained in:
Emmanuel Viennet 2021-07-20 18:32:04 +03:00
parent 3876b02626
commit d30c071c5d
10 changed files with 63 additions and 66 deletions

View File

@ -117,7 +117,7 @@ Pour créer un utilisateur "super admin", c'est à dire admin dans tous les dép
## Tests
python -m unittest tests.test_users
pytest tests/unit/test_users.py
# TODO

View File

@ -24,36 +24,20 @@ from config import Config
from app.scodoc import notesdb as ndb
from app.scodoc import sco_cache
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
db = SQLAlchemy()
migrate = Migrate()
login = LoginManager()
login.login_view = "auth.login"
login.login_message = "Please log in to access this page."
mail = Mail()
bootstrap = Bootstrap(app)
bootstrap = Bootstrap()
moment = Moment()
cache = Cache(config={"CACHE_TYPE": "MemcachedCache"}) # XXX TODO: configuration file
@app.before_request
def open_dept_db_connection():
# current_app.logger.info("open_dept_db_connection")
if hasattr(g, "scodoc_dept") and not hasattr(g, "db_conn") and g.scodoc_dept:
g.db_conn = ndb.open_dept_connection()
@app.teardown_request
def close_dept_db_connection():
# current_app.logger.info("close_dept_db_connection")
if hasattr(g, "db_conn"):
ndb.close_dept_connection()
def create_app(config_class=Config):
print("create_app")
app = Flask(__name__, static_url_path="/ScoDoc/static", static_folder="static")
app.logger.setLevel(logging.DEBUG)
app.config.from_object(config_class)

View File

@ -156,7 +156,7 @@ def scodoc7func(context):
elif not hasattr(g, "scodoc_dept"):
g.scodoc_dept = None
# --- Open DB connection
app.open_dept_db_connection()
app.views.open_dept_db_connection()
# --- Emulate Zope's REQUEST
REQUEST = ZRequest()
g.zrequest = REQUEST
@ -227,10 +227,10 @@ class ScoDoc7Context(object):
def __init__(self, name=""):
self.name = name
logging.getLogger(__name__).info("created %s" % self)
# logging.getLogger(__name__).info("created %s" % self)
def populate(self, globals_dict):
logging.getLogger(__name__).info("populating context %s" % self)
# logging.getLogger(__name__).info("populating context %s" % self)
for k in globals_dict:
if (not k.startswith("_")) and (
isinstance(globals_dict[k], types.FunctionType)

View File

@ -75,7 +75,7 @@ class ScoDocCache:
@classmethod
def _get_key(cls, oid):
return g.scodoc_dept + "_" + cls.prefix + oid
return g.scodoc_dept + "_" + cls.prefix + "_" + oid
@classmethod
def get(cls, oid):
@ -84,16 +84,10 @@ class ScoDocCache:
@classmethod
def set(cls, oid, value):
"""Store evaluation"""
return CACHE.set(cls._get_key(oid), value, timeout=cls.timeout)
@classmethod
def get_cached(cls, oid):
"""get cached object. Clients should use .get()
This function is usefull for tests, because get() may be
overloaded by subclasses.
"""
return ScoDocCache.get(oid)
"""Store value"""
key = cls._get_key(oid)
log(f"CACHE key={key}, timeout={cls.timeout}")
return CACHE.set(key, value, timeout=cls.timeout)
@classmethod
def delete(cls, oid):
@ -103,7 +97,10 @@ class ScoDocCache:
@classmethod
def delete_many(cls, oids):
"""Remove multiple keys at once"""
CACHE.delete_many([cls._get_key(oid) for oid in oids])
# delete_many seems bugged:
# CACHE.delete_many([cls._get_key(oid) for oid in oids])
for oid in oids:
cls.delete(oid)
class EvaluationCache(ScoDocCache):
@ -190,13 +187,13 @@ class NotesTableCache(ScoDocCache):
prefix = "NT"
@classmethod
def get(cls, formsemestre_id):
def get(cls, formsemestre_id, compute=True):
"""Returns NotesTable for this formsemestre
If not in cache, build it and cache it.
If not in cache and compute is True, build it and cache it.
"""
key = cls._get_key(formsemestre_id)
nt = CACHE.get(key)
if nt:
if nt or not compute:
return nt
from app.scodoc import notes_table

View File

@ -8,7 +8,7 @@ import psycopg2
import psycopg2.extras
from flask import current_app
from app import app, db
from app import db
from app.auth.models import User, Role

View File

@ -2,6 +2,8 @@
"""ScoDoc Flask views
"""
from flask import Blueprint
from flask import g
from app.scodoc import notesdb as ndb
scodoc_bp = Blueprint("scodoc", __name__)
scolar_bp = Blueprint("scolar", __name__)
@ -10,6 +12,19 @@ users_bp = Blueprint("users", __name__)
absences_bp = Blueprint("absences", __name__)
essais_bp = Blueprint("essais", __name__)
from app.views import scodoc, notes, scolar, absences, users, essais
scolar.context.Notes = notes.context # XXX transitoire #sco8
@scodoc_bp.before_app_request
def open_dept_db_connection():
# current_app.logger.info("open_dept_db_connection")
if hasattr(g, "scodoc_dept") and not hasattr(g, "db_conn") and g.scodoc_dept:
g.db_conn = ndb.open_dept_connection()
@scodoc_bp.teardown_app_request
def close_dept_db_connection(arg):
# current_app.logger.info("close_dept_db_connection")
if hasattr(g, "db_conn"):
ndb.close_dept_connection()
from app.views import scodoc, notes, scolar, absences, users, essais

View File

@ -7,7 +7,7 @@ BASEDIR = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(BASEDIR, ".env"))
class ConfigClass(object):
class Config:
"""General configuration. Mostly loaded from environment via .env"""
SECRET_KEY = os.environ.get("SECRET_KEY") or "un-grand-secret-introuvable"
@ -30,6 +30,9 @@ class ConfigClass(object):
BOOTSTRAP_SERVE_LOCAL = os.environ.get("BOOTSTRAP_SERVE_LOCAL")
# for ScoDoc 7 compat (à changer)
INSTANCE_HOME = os.environ.get("INSTANCE_HOME", "/opt/scodoc")
SCODOC_VAR_DIR = os.path.join(
os.environ.get("INSTANCE_HOME", "/opt/scodoc"), "var", "scodoc"
)
# For legacy ScoDoc7 installs: postgresql user
SCODOC7_SQL_USER = os.environ.get("SCODOC7_SQL_USER", "www-data")
@ -37,10 +40,3 @@ class ConfigClass(object):
# STATIC_URL_PATH = "/ScoDoc/static"
# static_folder = "stat"
# SERVER_NAME = os.environ.get("SERVER_NAME")
def __init__(self):
"""Used to build some config variable at startup time"""
self.SCODOC_VAR_DIR = os.path.join(self.INSTANCE_HOME, "var", "scodoc")
Config = ConfigClass()

View File

@ -1,2 +1,2 @@
#
import tests.test_users
import tests.unit.test_users

View File

@ -1,20 +1,29 @@
import pytest
from app import app, db
from flask import g
import app as myapp
from app import db, create_app
from app.auth.models import User, Role, Permission
from app.scodoc import sco_bulletins_standard
from app.scodoc import notesdb as ndb
@pytest.fixture
@pytest.fixture()
def test_client():
# Setup
app.config["TESTING"] = True
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite://"
myapp.Config.TESTING = True
myapp.Config.SQLALCHEMY_DATABASE_URI = "sqlite://"
apptest = create_app()
# Run tests:
with app.test_client() as client:
with app.app_context():
with apptest.test_client() as client:
with apptest.app_context():
db.create_all()
Role.insert_roles()
g.scodoc_dept = "RT"
g.db_conn = ndb.open_dept_connection()
yield client
# Teardown:
db.session.remove()
db.drop_all()
ndb.close_dept_connection()
# Teardown:
db.session.remove()
db.drop_all()

View File

@ -4,14 +4,14 @@
-écriture de test_users avec pytest.
Usage:
Usage: pytest tests/unit/test_users.py
"""
import pytest
from tests.conftest import test_client
from flask import current_app
from app import app, db
from app import db
from app.auth.models import User, Role, Permission
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
@ -19,10 +19,6 @@ from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
DEPT = "XX"
def test_test(test_client):
assert 1 == 1
def test_password_hashing(test_client):
u = User(user_name="susan")
db.session.add(u)