Skip to content

Commit 7cf42f9

Browse files
Use pytest temporary folders and fixtures to create test file hierarchy at test time (#516)
* make test db a fixture that returns a session, use jp_data_dir fixture * Use job_id returned by the db * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * use fixture for root dir * create test dirs by copying test files from static dir into temp dirs instead of uploading test dirs for execution manager test * create test dirs by copying test files from static dir into temp dirs instead of uploading test dirs for scheduler tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * create test dirs by copying test files from static dir into temp dirs instead of uploading test dirs for job files manager tests * make static_test_files_dir fixture session-scoped * add return type annotations to fixtures where return type is not clear * explicitly close db session to ensure all db connections are released * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Assert tmp_path and similar as Path type --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 953aea6 commit 7cf42f9

12 files changed

+209
-132
lines changed

conftest.py

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,73 @@
1-
import os
21
from pathlib import Path
32

43
import pytest
4+
from sqlalchemy import create_engine
5+
from sqlalchemy.orm import Session, sessionmaker
56

6-
from jupyter_scheduler.orm import create_session, create_tables
7+
from jupyter_scheduler.orm import Base
78
from jupyter_scheduler.scheduler import Scheduler
89
from jupyter_scheduler.tests.mocks import MockEnvironmentManager
910

10-
pytest_plugins = ("jupyter_server.pytest_plugin",)
11+
pytest_plugins = ("jupyter_server.pytest_plugin", "pytest_jupyter.jupyter_server")
1112

12-
HERE = Path(__file__).parent.resolve()
13-
DB_FILE_PATH = f"{HERE}/jupyter_scheduler/tests/testdb.sqlite"
14-
DB_URL = f"sqlite:///{DB_FILE_PATH}"
1513

16-
TEST_ROOT_DIR = f"{HERE}/jupyter_scheduler/tests/test_root_dir"
14+
@pytest.fixture(scope="session")
15+
def static_test_files_dir() -> Path:
16+
return Path(__file__).parent.resolve() / "jupyter_scheduler" / "tests" / "static"
1717

1818

1919
@pytest.fixture
20-
def jp_server_config(jp_server_config):
20+
def jp_scheduler_root_dir(tmp_path: Path) -> Path:
21+
root_dir = tmp_path / "workspace_root"
22+
root_dir.mkdir()
23+
return root_dir
24+
25+
26+
@pytest.fixture
27+
def jp_scheduler_output_dir(jp_scheduler_root_dir: Path) -> Path:
28+
output_dir = jp_scheduler_root_dir / "jobs"
29+
output_dir.mkdir()
30+
return output_dir
31+
32+
33+
@pytest.fixture
34+
def jp_scheduler_staging_dir(jp_data_dir: Path) -> Path:
35+
staging_area = jp_data_dir / "scheduler_staging_area"
36+
staging_area.mkdir()
37+
return staging_area
38+
39+
40+
@pytest.fixture
41+
def jp_scheduler_db_url(jp_scheduler_staging_dir: Path) -> str:
42+
db_file_path = jp_scheduler_staging_dir / "scheduler.sqlite"
43+
return f"sqlite:///{db_file_path}"
44+
45+
46+
@pytest.fixture
47+
def jp_scheduler_db(jp_scheduler_db_url):
48+
engine = create_engine(jp_scheduler_db_url, echo=False)
49+
Base.metadata.create_all(engine)
50+
Session = sessionmaker(bind=engine)
51+
session = Session()
52+
yield session
53+
session.close()
54+
55+
56+
@pytest.fixture
57+
def jp_scheduler(jp_scheduler_db_url, jp_scheduler_root_dir, jp_scheduler_db):
58+
return Scheduler(
59+
db_url=jp_scheduler_db_url,
60+
root_dir=str(jp_scheduler_root_dir),
61+
environments_manager=MockEnvironmentManager(),
62+
)
63+
64+
65+
@pytest.fixture
66+
def jp_server_config(jp_scheduler_db_url, jp_server_config):
2167
return {
2268
"ServerApp": {"jpserver_extensions": {"jupyter_scheduler": True}},
2369
"SchedulerApp": {
24-
"db_url": DB_URL,
70+
"db_url": jp_scheduler_db_url,
2571
"drop_tables": True,
2672
"environment_manager_class": "jupyter_scheduler.tests.mocks.MockEnvironmentManager",
2773
},
@@ -30,23 +76,3 @@ def jp_server_config(jp_server_config):
3076
},
3177
"Scheduler": {"task_runner_class": "jupyter_scheduler.tests.mocks.MockTaskRunner"},
3278
}
33-
34-
35-
@pytest.fixture(autouse=True)
36-
def setup_db():
37-
create_tables(DB_URL, True)
38-
yield
39-
if os.path.exists(DB_FILE_PATH):
40-
os.remove(DB_FILE_PATH)
41-
42-
43-
@pytest.fixture
44-
def jp_scheduler_db():
45-
return create_session(DB_URL)
46-
47-
48-
@pytest.fixture
49-
def jp_scheduler():
50-
return Scheduler(
51-
db_url=DB_URL, root_dir=str(TEST_ROOT_DIR), environments_manager=MockEnvironmentManager()
52-
)
Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,60 @@
1+
import shutil
12
from pathlib import Path
3+
from typing import Tuple
24

35
import pytest
4-
from sqlalchemy import create_engine
5-
from sqlalchemy.orm import sessionmaker
66

7-
from conftest import DB_URL
87
from jupyter_scheduler.executors import DefaultExecutionManager
98
from jupyter_scheduler.orm import Job
109

11-
JOB_ID = "69856f4e-ce94-45fd-8f60-3a587457fce7"
12-
NOTEBOOK_NAME = "side_effects.ipynb"
13-
SIDE_EFECT_FILE_NAME = "output_side_effect.txt"
1410

15-
NOTEBOOK_DIR = Path(__file__).resolve().parent / "test_staging_dir" / "job-4"
16-
NOTEBOOK_PATH = NOTEBOOK_DIR / NOTEBOOK_NAME
17-
SIDE_EFFECT_FILE = NOTEBOOK_DIR / SIDE_EFECT_FILE_NAME
11+
@pytest.fixture
12+
def staging_dir_with_side_effects(
13+
static_test_files_dir, jp_scheduler_staging_dir
14+
) -> Tuple[Path, Path]:
15+
notebook_file_path = static_test_files_dir / "side_effects.ipynb"
16+
side_effect_file_path = static_test_files_dir / "output_side_effect.txt"
17+
job_staging_dir = jp_scheduler_staging_dir / "job-4"
18+
19+
job_staging_dir.mkdir()
20+
shutil.copy2(notebook_file_path, job_staging_dir)
21+
shutil.copy2(side_effect_file_path, job_staging_dir)
22+
23+
return (notebook_file_path, side_effect_file_path)
1824

1925

2026
@pytest.fixture
21-
def load_job(jp_scheduler_db):
22-
with jp_scheduler_db() as session:
23-
job = Job(
24-
runtime_environment_name="abc",
25-
input_filename=NOTEBOOK_NAME,
26-
job_id=JOB_ID,
27-
)
28-
session.add(job)
29-
session.commit()
30-
31-
32-
def test_add_side_effects_files(jp_scheduler_db, load_job):
27+
def side_effects_job_record(staging_dir_with_side_effects, jp_scheduler_db) -> str:
28+
notebook_name = staging_dir_with_side_effects[0].name
29+
job = Job(
30+
runtime_environment_name="abc",
31+
input_filename=notebook_name,
32+
)
33+
jp_scheduler_db.add(job)
34+
jp_scheduler_db.commit()
35+
36+
return job.job_id
37+
38+
39+
def test_add_side_effects_files(
40+
side_effects_job_record,
41+
staging_dir_with_side_effects,
42+
jp_scheduler_root_dir,
43+
jp_scheduler_db_url,
44+
jp_scheduler_db,
45+
):
46+
job_id = side_effects_job_record
47+
staged_notebook_file_path = staging_dir_with_side_effects[0]
48+
staged_notebook_dir = staged_notebook_file_path.parent
49+
side_effect_file_name = staging_dir_with_side_effects[1].name
50+
3351
manager = DefaultExecutionManager(
34-
job_id=JOB_ID,
35-
root_dir=str(NOTEBOOK_DIR),
36-
db_url=DB_URL,
37-
staging_paths={"input": str(NOTEBOOK_PATH)},
52+
job_id=job_id,
53+
root_dir=jp_scheduler_root_dir,
54+
db_url=jp_scheduler_db_url,
55+
staging_paths={"input": staged_notebook_file_path},
3856
)
39-
manager.add_side_effects_files(str(NOTEBOOK_DIR))
57+
manager.add_side_effects_files(staged_notebook_dir)
4058

41-
with jp_scheduler_db() as session:
42-
job = session.query(Job).filter(Job.job_id == JOB_ID).one()
43-
assert SIDE_EFECT_FILE_NAME in job.packaged_files
59+
job = jp_scheduler_db.query(Job).filter(Job.job_id == job_id).one()
60+
assert side_effect_file_name in job.packaged_files

0 commit comments

Comments
 (0)