forked from ScoDoc/ScoDoc
reorganized unit tests and fixed bug in cache handling
This commit is contained in:
parent
3876b02626
commit
d30c071c5d
@ -117,7 +117,7 @@ Pour créer un utilisateur "super admin", c'est à dire admin dans tous les dép
|
|||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
python -m unittest tests.test_users
|
pytest tests/unit/test_users.py
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
@ -24,36 +24,20 @@ from config import Config
|
|||||||
from app.scodoc import notesdb as ndb
|
from app.scodoc import notesdb as ndb
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc import sco_cache
|
||||||
|
|
||||||
app = Flask(__name__)
|
db = SQLAlchemy()
|
||||||
app.config.from_object(Config)
|
migrate = Migrate()
|
||||||
|
|
||||||
db = SQLAlchemy(app)
|
|
||||||
migrate = Migrate(app, db)
|
|
||||||
login = LoginManager()
|
login = LoginManager()
|
||||||
login.login_view = "auth.login"
|
login.login_view = "auth.login"
|
||||||
login.login_message = "Please log in to access this page."
|
login.login_message = "Please log in to access this page."
|
||||||
mail = Mail()
|
mail = Mail()
|
||||||
bootstrap = Bootstrap(app)
|
bootstrap = Bootstrap()
|
||||||
moment = Moment()
|
moment = Moment()
|
||||||
|
|
||||||
cache = Cache(config={"CACHE_TYPE": "MemcachedCache"}) # XXX TODO: configuration file
|
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):
|
def create_app(config_class=Config):
|
||||||
|
print("create_app")
|
||||||
app = Flask(__name__, static_url_path="/ScoDoc/static", static_folder="static")
|
app = Flask(__name__, static_url_path="/ScoDoc/static", static_folder="static")
|
||||||
app.logger.setLevel(logging.DEBUG)
|
app.logger.setLevel(logging.DEBUG)
|
||||||
app.config.from_object(config_class)
|
app.config.from_object(config_class)
|
||||||
|
@ -156,7 +156,7 @@ def scodoc7func(context):
|
|||||||
elif not hasattr(g, "scodoc_dept"):
|
elif not hasattr(g, "scodoc_dept"):
|
||||||
g.scodoc_dept = None
|
g.scodoc_dept = None
|
||||||
# --- Open DB connection
|
# --- Open DB connection
|
||||||
app.open_dept_db_connection()
|
app.views.open_dept_db_connection()
|
||||||
# --- Emulate Zope's REQUEST
|
# --- Emulate Zope's REQUEST
|
||||||
REQUEST = ZRequest()
|
REQUEST = ZRequest()
|
||||||
g.zrequest = REQUEST
|
g.zrequest = REQUEST
|
||||||
@ -227,10 +227,10 @@ class ScoDoc7Context(object):
|
|||||||
|
|
||||||
def __init__(self, name=""):
|
def __init__(self, name=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
logging.getLogger(__name__).info("created %s" % self)
|
# logging.getLogger(__name__).info("created %s" % self)
|
||||||
|
|
||||||
def populate(self, globals_dict):
|
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:
|
for k in globals_dict:
|
||||||
if (not k.startswith("_")) and (
|
if (not k.startswith("_")) and (
|
||||||
isinstance(globals_dict[k], types.FunctionType)
|
isinstance(globals_dict[k], types.FunctionType)
|
||||||
|
@ -75,7 +75,7 @@ class ScoDocCache:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_key(cls, oid):
|
def _get_key(cls, oid):
|
||||||
return g.scodoc_dept + "_" + cls.prefix + oid
|
return g.scodoc_dept + "_" + cls.prefix + "_" + oid
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, oid):
|
def get(cls, oid):
|
||||||
@ -84,16 +84,10 @@ class ScoDocCache:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set(cls, oid, value):
|
def set(cls, oid, value):
|
||||||
"""Store evaluation"""
|
"""Store value"""
|
||||||
return CACHE.set(cls._get_key(oid), value, timeout=cls.timeout)
|
key = cls._get_key(oid)
|
||||||
|
log(f"CACHE key={key}, timeout={cls.timeout}")
|
||||||
@classmethod
|
return CACHE.set(key, value, timeout=cls.timeout)
|
||||||
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)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete(cls, oid):
|
def delete(cls, oid):
|
||||||
@ -103,7 +97,10 @@ class ScoDocCache:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def delete_many(cls, oids):
|
def delete_many(cls, oids):
|
||||||
"""Remove multiple keys at once"""
|
"""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):
|
class EvaluationCache(ScoDocCache):
|
||||||
@ -190,13 +187,13 @@ class NotesTableCache(ScoDocCache):
|
|||||||
prefix = "NT"
|
prefix = "NT"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, formsemestre_id):
|
def get(cls, formsemestre_id, compute=True):
|
||||||
"""Returns NotesTable for this formsemestre
|
"""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)
|
key = cls._get_key(formsemestre_id)
|
||||||
nt = CACHE.get(key)
|
nt = CACHE.get(key)
|
||||||
if nt:
|
if nt or not compute:
|
||||||
return nt
|
return nt
|
||||||
from app.scodoc import notes_table
|
from app.scodoc import notes_table
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import psycopg2
|
|||||||
import psycopg2.extras
|
import psycopg2.extras
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from app import app, db
|
from app import db
|
||||||
from app.auth.models import User, Role
|
from app.auth.models import User, Role
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
"""ScoDoc Flask views
|
"""ScoDoc Flask views
|
||||||
"""
|
"""
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
from flask import g
|
||||||
|
from app.scodoc import notesdb as ndb
|
||||||
|
|
||||||
scodoc_bp = Blueprint("scodoc", __name__)
|
scodoc_bp = Blueprint("scodoc", __name__)
|
||||||
scolar_bp = Blueprint("scolar", __name__)
|
scolar_bp = Blueprint("scolar", __name__)
|
||||||
@ -10,6 +12,19 @@ users_bp = Blueprint("users", __name__)
|
|||||||
absences_bp = Blueprint("absences", __name__)
|
absences_bp = Blueprint("absences", __name__)
|
||||||
essais_bp = Blueprint("essais", __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
|
||||||
|
12
config.py
12
config.py
@ -7,7 +7,7 @@ BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
|||||||
load_dotenv(os.path.join(BASEDIR, ".env"))
|
load_dotenv(os.path.join(BASEDIR, ".env"))
|
||||||
|
|
||||||
|
|
||||||
class ConfigClass(object):
|
class Config:
|
||||||
"""General configuration. Mostly loaded from environment via .env"""
|
"""General configuration. Mostly loaded from environment via .env"""
|
||||||
|
|
||||||
SECRET_KEY = os.environ.get("SECRET_KEY") or "un-grand-secret-introuvable"
|
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")
|
BOOTSTRAP_SERVE_LOCAL = os.environ.get("BOOTSTRAP_SERVE_LOCAL")
|
||||||
# for ScoDoc 7 compat (à changer)
|
# for ScoDoc 7 compat (à changer)
|
||||||
INSTANCE_HOME = os.environ.get("INSTANCE_HOME", "/opt/scodoc")
|
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
|
# For legacy ScoDoc7 installs: postgresql user
|
||||||
SCODOC7_SQL_USER = os.environ.get("SCODOC7_SQL_USER", "www-data")
|
SCODOC7_SQL_USER = os.environ.get("SCODOC7_SQL_USER", "www-data")
|
||||||
@ -37,10 +40,3 @@ class ConfigClass(object):
|
|||||||
# STATIC_URL_PATH = "/ScoDoc/static"
|
# STATIC_URL_PATH = "/ScoDoc/static"
|
||||||
# static_folder = "stat"
|
# static_folder = "stat"
|
||||||
# SERVER_NAME = os.environ.get("SERVER_NAME")
|
# 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()
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#
|
#
|
||||||
import tests.test_users
|
import tests.unit.test_users
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
import pytest
|
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.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():
|
def test_client():
|
||||||
# Setup
|
# Setup
|
||||||
app.config["TESTING"] = True
|
myapp.Config.TESTING = True
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite://"
|
myapp.Config.SQLALCHEMY_DATABASE_URI = "sqlite://"
|
||||||
|
apptest = create_app()
|
||||||
# Run tests:
|
# Run tests:
|
||||||
with app.test_client() as client:
|
with apptest.test_client() as client:
|
||||||
with app.app_context():
|
with apptest.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
Role.insert_roles()
|
Role.insert_roles()
|
||||||
|
g.scodoc_dept = "RT"
|
||||||
|
g.db_conn = ndb.open_dept_connection()
|
||||||
yield client
|
yield client
|
||||||
|
ndb.close_dept_connection()
|
||||||
# Teardown:
|
# Teardown:
|
||||||
db.session.remove()
|
db.session.remove()
|
||||||
db.drop_all()
|
db.drop_all()
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
Ré-écriture de test_users avec pytest.
|
Ré-écriture de test_users avec pytest.
|
||||||
|
|
||||||
Usage:
|
Usage: pytest tests/unit/test_users.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from tests.conftest import test_client
|
from tests.conftest import test_client
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from app import app, db
|
from app import db
|
||||||
from app.auth.models import User, Role, Permission
|
from app.auth.models import User, Role, Permission
|
||||||
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
|
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"
|
DEPT = "XX"
|
||||||
|
|
||||||
|
|
||||||
def test_test(test_client):
|
|
||||||
assert 1 == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_password_hashing(test_client):
|
def test_password_hashing(test_client):
|
||||||
u = User(user_name="susan")
|
u = User(user_name="susan")
|
||||||
db.session.add(u)
|
db.session.add(u)
|
||||||
|
Loading…
Reference in New Issue
Block a user