From ae80d8b87fec629a7247ba574467d7b52ffb153f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Montan=CC=83ana?= Date: Mon, 12 Jun 2023 10:36:14 +0200 Subject: [PATCH] Begin testing --- .vscode/settings.json | 7 +++- beflask/app.py | 12 +++--- beflask/config.py | 8 ++-- beflask/env.dist | 3 -- dbseed.py | 5 ++- dbseed_docker.py | 5 ++- pyproject.toml | 6 ++- tests/__init__.py | 0 tests/conftest.py | 87 +++++++++++++++++++++++++++++++++++++++++++ tests/test_login.py | 35 +++++++++++++++++ tests/test_main.py | 12 ++++++ 11 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/test_login.py create mode 100644 tests/test_main.py diff --git a/.vscode/settings.json b/.vscode/settings.json index d99f2f3..49867c4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,10 @@ "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" }, - "python.formatting.provider": "none" + "python.formatting.provider": "none", + "python.testing.pytestArgs": [ + "tests" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true } \ No newline at end of file diff --git a/beflask/app.py b/beflask/app.py index 92e6f49..8e5eeca 100644 --- a/beflask/app.py +++ b/beflask/app.py @@ -4,7 +4,7 @@ from flask import Flask from flask_bootstrap import Bootstrap5 from flask_login import LoginManager from flask_socketio import SocketIO -from .config import config, load_env +from .config import config from .models import User, db from .results.main_results import results @@ -19,19 +19,19 @@ login_manager = LoginManager() @login_manager.user_loader def load_user(user_id): - return User.query.get(int(user_id)) + return db.session.get(User, int(user_id)) def make_shell_context(): return {"db": db, "User": User} -def create_app(): +def create_app(config_name=None): + if config_name is None: + config_name = os.environ.get("BEFLASK_ENV", "development") app = Flask(__name__) + app.config.from_object(config[config_name]) bootstrap.init_app(app) - load_env() - config_object = config[os.getenv("BEFLASK_ENV", "development")] - app.config.from_object(config_object) db.init_app(app) login_manager.init_app(app) login_manager.login_view = "main.login" diff --git a/beflask/config.py b/beflask/config.py index 25ceca0..3b87ab2 100644 --- a/beflask/config.py +++ b/beflask/config.py @@ -8,10 +8,9 @@ def get_base_dir(): return os.path.abspath(os.path.dirname(__file__)) -def load_env(): - dotenv_file = ".env" - file_name = os.path.join(get_base_dir(), dotenv_file) - load_dotenv(file_name) +dotenv_file = ".env" +file_name = os.path.join(get_base_dir(), dotenv_file) +load_dotenv(file_name) class Config(object): @@ -40,6 +39,7 @@ class ProductionConfig(Config): class TestingConfig(Config): TESTING = True SQLALCHEMY_DATABASE_URI = "sqlite://" + WTF_CSRF_ENABLED = False SOCKETIO_MESSAGE_QUEUE = None diff --git a/beflask/env.dist b/beflask/env.dist index e8bf39c..fa2a6a8 100644 --- a/beflask/env.dist +++ b/beflask/env.dist @@ -1,5 +1,2 @@ COMPARE=True -DEBUG=True SECRET_KEY=Really-hard-to-guess-string -# possible values: development, testing, productions -BEFLASK_ENV=development diff --git a/dbseed.py b/dbseed.py index c301d59..c83fd4a 100644 --- a/dbseed.py +++ b/dbseed.py @@ -9,7 +9,8 @@ with app.app_context(): b = Benchmark( name="discretizbench", folder="/Users/rmontanana/Code/discretizbench", - description="Experiments with local discretization and Bayesian classifiers", + description="Experiments with local discretization and Bayesian " + "classifiers", ) db.session.add(b) b = Benchmark( @@ -30,7 +31,7 @@ with app.app_context(): admin=True, benchmark_id=1, ) - u.set_password("patata") + u.set_password("galeote") u1 = User( username="guest", email="guest@example.com", diff --git a/dbseed_docker.py b/dbseed_docker.py index 0c9dc0d..9b62da0 100644 --- a/dbseed_docker.py +++ b/dbseed_docker.py @@ -9,7 +9,8 @@ with app.app_context(): b = Benchmark( name="discretizbench", folder="/app/discretizbench", - description="Experiments with local discretization and Bayesian classifiers", + description="Experiments with local discretization and Bayesian " + "classifiers", ) db.session.add(b) b = Benchmark( @@ -30,7 +31,7 @@ with app.app_context(): admin=True, benchmark_id=1, ) - u.set_password("patata") + u.set_password("galeote") u1 = User( username="guest", email="guest@example.com", diff --git a/pyproject.toml b/pyproject.toml index 0731e17..b9f1aac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,14 +37,18 @@ classifiers = [ ] [project.optional-dependencies] -dev = ["black", "pre-commit", "flake8", "mypy"] +dev = ["black", "pre-commit", "flake8", "mypy", "coverage"] [project.urls] Home = "https://github.com/doctorado-ml/beflask" [tool.coverage.run] +branch = true source = ["beflask"] +[tool.pytest.ini_options] +testpaths = ["tests"] + [tool.black] line-length = 79 target_version = ['py38', 'py39', 'py310'] diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..1060fab --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,87 @@ +import pytest +from beflask import app as application +from flask_login import FlaskLoginClient +from beflask.models import Benchmark, User, db + + +class AuthActions(object): + def __init__(self, client): + self._client = client + + def login( + self, username="guest", password="patata", follow_redirects=False + ): + return self._client.post( + "/login", + data={"username": username, "password": password}, + follow_redirects=follow_redirects, + ) + + def logout(self): + return self._client.get("/logout") + + +@pytest.fixture +def auth(client): + return AuthActions(client) + + +@pytest.fixture +def app(): + socketio, app = application.create_app("testing") + app.test_client_class = FlaskLoginClient + with app.app_context(): + db_seed(db) + return socketio, app + + +@pytest.fixture +def client(app): + return app[1].test_client() + + +@pytest.fixture +def runner(app): + return app[1].test_cli_runner() + + +def db_seed(db): + db.drop_all() + db.create_all() + b = Benchmark( + name="discretizbench", + folder="/Users/rmontanana/Code/discretizbench", + description="Experiments with local discretization and Bayesian " + "classifiers", + ) + db.session.add(b) + b = Benchmark( + name="odtebench", + folder="/Users/rmontanana/Code/odtebench", + description="Experiments with STree and Ensemble classifiers", + ) + db.session.add(b) + b = Benchmark( + name="covbench", + folder="/Users/rmontanana/Code/covbench", + description="Experiments with COVID-19 dataset", + ) + db.session.add(b) + u = User( + username="rmontanana", + email="rmontanana@gmail.com", + admin=True, + benchmark_id=1, + ) + u.set_password("patito") + u1 = User( + username="guest", + email="guest@example.com", + admin=False, + benchmark_id=1, + ) + u1.set_password("patata") + db.session.add(b) + db.session.add(u) + db.session.add(u1) + db.session.commit() diff --git a/tests/test_login.py b/tests/test_login.py new file mode 100644 index 0000000..51c9765 --- /dev/null +++ b/tests/test_login.py @@ -0,0 +1,35 @@ +import pytest +from urllib.parse import urlparse +from flask import session, g + + +def test_login(client, auth): + assert client.get("/login").status_code == 200 + response = auth.login() + assert response.headers["Location"] == "/index" + auth.logout() + + response = auth.login(username="rmontanana", password="patito") + assert response.headers["Location"] == "/index" + + with client: + client.get("/index") + assert session["_user_id"] == "1" + assert g._login_user.username == "rmontanana" + auth.logout() + + +def test_login_invalid(client, auth): + response = auth.login( + username="rmontanana", password="patato", follow_redirects=True + ) + assert b"Invalid username or password" in response.data + assert response.status_code == 200 + + +def test_logout(client, auth): + auth.login() + + with client: + auth.logout() + assert "user_id" not in session diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 0000000..52638b6 --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,12 @@ +from beflask import app + + +def test_config(): + assert not app.create_app()[1].testing + assert app.create_app("testing")[1].testing + + +def test_index(client): + response = client.get("/") + # check image is in the response + assert b"img/robert-lukeman-_RBcxo9AU-U-unsplash.jpg" in response.data