EOS/tests/conftest.py
Dominique Lasserre f61665669f Migrate from Flask to FastAPI (#163)
* Migrate from Flask to FastAPI

 * FastAPI migration:
    - Use pydantic model classes as input parameters to the
      data/calculation classes.
    - Interface field names changed to constructor parameter names (for
      simplicity only during transition, should be updated in a followup
      PR).
    - Add basic interface requirements (e.g. some values > 0, etc.).
 * Update tests for new data format.
 * Python requirement down to 3.9 (TypeGuard no longer needed)
 * Makefile: Add helpful targets (e.g. development server with reload)

* Move API doc from README to pydantic model classes (swagger)

 * Link to swagger.io with own openapi.yml.
 * Commit openapi.json and check with pytest for changes so the
   documentation is always up-to-date.

* Streamline docker

* FastAPI: Run startup action on dev server

 * Fix config for /strompreis, endpoint still broken however.

* test_openapi: Compare against docs/.../openapi.json

* Move fastapi to server/ submodule

 * See #187 for new repository structure.
2024-11-15 22:27:25 +01:00

118 lines
3.3 KiB
Python

import logging
import os
import subprocess
import sys
import time
from pathlib import Path
import pytest
from xprocess import ProcessStarter
from akkudoktoreos.config import EOS_DIR, AppConfig, load_config
@pytest.fixture(name="tmp_config")
def load_config_tmp(tmp_path: Path) -> AppConfig:
"""Creates an AppConfig from default.config.json with a tmp output directory."""
config = load_config(tmp_path)
config.directories.output = tmp_path
return config
@pytest.fixture(autouse=True)
def disable_debug_logging():
# Temporarily set logging level higher than DEBUG
logging.disable(logging.DEBUG)
yield
# Re-enable logging back to its original state after the test
logging.disable(logging.NOTSET)
def pytest_addoption(parser):
parser.addoption(
"--full-run", action="store_true", default=False, help="Run with all optimization tests."
)
@pytest.fixture
def is_full_run(request):
yield bool(request.config.getoption("--full-run"))
@pytest.fixture
def server(xprocess, tmp_path: Path):
"""Fixture to start the server.
Provides URL of the server.
"""
class Starter(ProcessStarter):
# assure server to be installed
try:
subprocess.run(
[sys.executable, "-c", "import akkudoktoreos.server"],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
except subprocess.CalledProcessError:
project_dir = Path(__file__).parent.parent
subprocess.run(
[sys.executable, "-m", "pip", "install", "-e", project_dir],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# command to start server process
args = [sys.executable, "-m", "akkudoktoreos.server.fastapi_server"]
env = {EOS_DIR: f"{tmp_path}", **os.environ.copy()}
# startup pattern
pattern = "Application startup complete."
# search the first 30 lines for the startup pattern, if not found
# a RuntimeError will be raised informing the user
max_read_lines = 30
# will wait for 30 seconds before timing out
timeout = 30
# xprocess will now attempt to clean up upon interruptions
terminate_on_interrupt = True
# ensure process is running and return its logfile
logfile = xprocess.ensure("eos", Starter)
# create url/port info to the server
url = "http://127.0.0.1:8503"
yield url
# clean up whole process tree afterwards
xprocess.getinfo("eos").terminate()
@pytest.fixture
def other_timezone():
"""Fixture to temporarily change the timezone.
Restores the original timezone after the test.
"""
original_tz = os.environ.get("TZ", None)
other_tz = "Atlantic/Canary"
if original_tz == other_tz:
other_tz = "Asia/Singapore"
# Change the timezone to another
os.environ["TZ"] = other_tz
time.tzset() # For Unix/Linux to apply the timezone change
yield os.environ["TZ"] # Yield control back to the test case
# Restore the original timezone after the test
if original_tz:
os.environ["TZ"] = original_tz
else:
del os.environ["TZ"]
time.tzset() # Re-apply the original timezone