Skip to content

Commit 13bd892

Browse files
committed
tests: improve tests with parametrize and monkeypatch
1 parent fb946a3 commit 13bd892

7 files changed

Lines changed: 311 additions & 824 deletions

tests/test_cli.py

Lines changed: 121 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -3,160 +3,151 @@
33
from pathlib import Path
44
from unittest.mock import patch
55

6+
import pytest
67
import uvicorn
78
from fastapi_cli.cli import app
89
from typer.testing import CliRunner
910

10-
from tests.utils import changing_dir
11-
1211
runner = CliRunner()
1312

1413
assets_path = Path(__file__).parent / "assets"
1514

1615

16+
@pytest.fixture(autouse=True)
17+
def assets(monkeypatch: pytest.MonkeyPatch):
18+
monkeypatch.chdir(assets_path)
19+
20+
1721
def test_dev() -> None:
18-
with changing_dir(assets_path):
19-
with patch.object(uvicorn, "run") as mock_run:
20-
result = runner.invoke(app, ["dev", "single_file_app.py"])
21-
assert result.exit_code == 0, result.output
22-
assert mock_run.called
23-
assert mock_run.call_args
24-
assert mock_run.call_args.kwargs == {
25-
"app": "single_file_app:app",
26-
"host": "127.0.0.1",
27-
"port": 8000,
28-
"reload": True,
29-
"workers": None,
30-
"root_path": "",
31-
"proxy_headers": True,
32-
}
33-
assert "Using import string single_file_app:app" in result.output
34-
assert (
35-
"╭────────── FastAPI CLI - Development mode ───────────╮" in result.output
36-
)
37-
assert "│ Serving at: http://127.0.0.1:8000" in result.output
38-
assert "│ API docs: http://127.0.0.1:8000/docs" in result.output
39-
assert "│ Running in development mode, for production use:" in result.output
40-
assert "│ fastapi run" in result.output
22+
with patch.object(uvicorn, "run") as mock_run:
23+
result = runner.invoke(app, ["dev", "single_file_app.py"])
24+
assert result.exit_code == 0, result.output
25+
assert mock_run.called
26+
assert mock_run.call_args
27+
assert mock_run.call_args.kwargs == {
28+
"app": "single_file_app:app",
29+
"host": "127.0.0.1",
30+
"port": 8000,
31+
"reload": True,
32+
"workers": None,
33+
"root_path": "",
34+
"proxy_headers": True,
35+
}
36+
assert "Using import string single_file_app:app" in result.output
37+
assert "╭────────── FastAPI CLI - Development mode ───────────╮" in result.output
38+
assert "│ Serving at: http://127.0.0.1:8000" in result.output
39+
assert "│ API docs: http://127.0.0.1:8000/docs" in result.output
40+
assert "│ Running in development mode, for production use:" in result.output
41+
assert "│ fastapi run" in result.output
4142

4243

4344
def test_dev_args() -> None:
44-
with changing_dir(assets_path):
45-
with patch.object(uvicorn, "run") as mock_run:
46-
result = runner.invoke(
47-
app,
48-
[
49-
"dev",
50-
"single_file_app.py",
51-
"--host",
52-
"192.168.0.2",
53-
"--port",
54-
"8080",
55-
"--no-reload",
56-
"--root-path",
57-
"/api",
58-
"--app",
59-
"api",
60-
"--no-proxy-headers",
61-
],
62-
)
63-
assert result.exit_code == 0, result.output
64-
assert mock_run.called
65-
assert mock_run.call_args
66-
assert mock_run.call_args.kwargs == {
67-
"app": "single_file_app:api",
68-
"host": "192.168.0.2",
69-
"port": 8080,
70-
"reload": False,
71-
"workers": None,
72-
"root_path": "/api",
73-
"proxy_headers": False,
74-
}
75-
assert "Using import string single_file_app:api" in result.output
76-
assert (
77-
"╭────────── FastAPI CLI - Development mode ───────────╮" in result.output
45+
with patch.object(uvicorn, "run") as mock_run:
46+
result = runner.invoke(
47+
app,
48+
[
49+
"dev",
50+
"single_file_app.py",
51+
"--host",
52+
"192.168.0.2",
53+
"--port",
54+
"8080",
55+
"--no-reload",
56+
"--root-path",
57+
"/api",
58+
"--app",
59+
"api",
60+
"--no-proxy-headers",
61+
],
7862
)
79-
assert "│ Serving at: http://192.168.0.2:8080" in result.output
80-
assert "│ API docs: http://192.168.0.2:8080/docs" in result.output
81-
assert "│ Running in development mode, for production use:" in result.output
82-
assert "│ fastapi run" in result.output
63+
assert result.exit_code == 0, result.output
64+
assert mock_run.called
65+
assert mock_run.call_args
66+
assert mock_run.call_args.kwargs == {
67+
"app": "single_file_app:api",
68+
"host": "192.168.0.2",
69+
"port": 8080,
70+
"reload": False,
71+
"workers": None,
72+
"root_path": "/api",
73+
"proxy_headers": False,
74+
}
75+
assert "Using import string single_file_app:api" in result.output
76+
assert "╭────────── FastAPI CLI - Development mode ───────────╮" in result.output
77+
assert "│ Serving at: http://192.168.0.2:8080" in result.output
78+
assert "│ API docs: http://192.168.0.2:8080/docs" in result.output
79+
assert "│ Running in development mode, for production use:" in result.output
80+
assert "│ fastapi run" in result.output
8381

8482

8583
def test_run() -> None:
86-
with changing_dir(assets_path):
87-
with patch.object(uvicorn, "run") as mock_run:
88-
result = runner.invoke(app, ["run", "single_file_app.py"])
89-
assert result.exit_code == 0, result.output
90-
assert mock_run.called
91-
assert mock_run.call_args
92-
assert mock_run.call_args.kwargs == {
93-
"app": "single_file_app:app",
94-
"host": "0.0.0.0",
95-
"port": 8000,
96-
"reload": False,
97-
"workers": None,
98-
"root_path": "",
99-
"proxy_headers": True,
100-
}
101-
assert "Using import string single_file_app:app" in result.output
102-
assert (
103-
"╭─────────── FastAPI CLI - Production mode ───────────╮" in result.output
104-
)
105-
assert "│ Serving at: http://0.0.0.0:8000" in result.output
106-
assert "│ API docs: http://0.0.0.0:8000/docs" in result.output
107-
assert "│ Running in production mode, for development use:" in result.output
108-
assert "│ fastapi dev" in result.output
84+
with patch.object(uvicorn, "run") as mock_run:
85+
result = runner.invoke(app, ["run", "single_file_app.py"])
86+
assert result.exit_code == 0, result.output
87+
assert mock_run.called
88+
assert mock_run.call_args
89+
assert mock_run.call_args.kwargs == {
90+
"app": "single_file_app:app",
91+
"host": "0.0.0.0",
92+
"port": 8000,
93+
"reload": False,
94+
"workers": None,
95+
"root_path": "",
96+
"proxy_headers": True,
97+
}
98+
assert "Using import string single_file_app:app" in result.output
99+
assert "╭─────────── FastAPI CLI - Production mode ───────────╮" in result.output
100+
assert "│ Serving at: http://0.0.0.0:8000" in result.output
101+
assert "│ API docs: http://0.0.0.0:8000/docs" in result.output
102+
assert "│ Running in production mode, for development use:" in result.output
103+
assert "│ fastapi dev" in result.output
109104

110105

111106
def test_run_args() -> None:
112-
with changing_dir(assets_path):
113-
with patch.object(uvicorn, "run") as mock_run:
114-
result = runner.invoke(
115-
app,
116-
[
117-
"run",
118-
"single_file_app.py",
119-
"--host",
120-
"192.168.0.2",
121-
"--port",
122-
"8080",
123-
"--no-reload",
124-
"--workers",
125-
"2",
126-
"--root-path",
127-
"/api",
128-
"--app",
129-
"api",
130-
"--no-proxy-headers",
131-
],
132-
)
133-
assert result.exit_code == 0, result.output
134-
assert mock_run.called
135-
assert mock_run.call_args
136-
assert mock_run.call_args.kwargs == {
137-
"app": "single_file_app:api",
138-
"host": "192.168.0.2",
139-
"port": 8080,
140-
"reload": False,
141-
"workers": 2,
142-
"root_path": "/api",
143-
"proxy_headers": False,
144-
}
145-
assert "Using import string single_file_app:api" in result.output
146-
assert (
147-
"╭─────────── FastAPI CLI - Production mode ───────────╮" in result.output
107+
with patch.object(uvicorn, "run") as mock_run:
108+
result = runner.invoke(
109+
app,
110+
[
111+
"run",
112+
"single_file_app.py",
113+
"--host",
114+
"192.168.0.2",
115+
"--port",
116+
"8080",
117+
"--no-reload",
118+
"--workers",
119+
"2",
120+
"--root-path",
121+
"/api",
122+
"--app",
123+
"api",
124+
"--no-proxy-headers",
125+
],
148126
)
149-
assert "│ Serving at: http://192.168.0.2:8080" in result.output
150-
assert "│ API docs: http://192.168.0.2:8080/docs" in result.output
151-
assert "│ Running in production mode, for development use:" in result.output
152-
assert "│ fastapi dev" in result.output
127+
assert result.exit_code == 0, result.output
128+
assert mock_run.called
129+
assert mock_run.call_args
130+
assert mock_run.call_args.kwargs == {
131+
"app": "single_file_app:api",
132+
"host": "192.168.0.2",
133+
"port": 8080,
134+
"reload": False,
135+
"workers": 2,
136+
"root_path": "/api",
137+
"proxy_headers": False,
138+
}
139+
assert "Using import string single_file_app:api" in result.output
140+
assert "╭─────────── FastAPI CLI - Production mode ───────────╮" in result.output
141+
assert "│ Serving at: http://192.168.0.2:8080" in result.output
142+
assert "│ API docs: http://192.168.0.2:8080/docs" in result.output
143+
assert "│ Running in production mode, for development use:" in result.output
144+
assert "│ fastapi dev" in result.output
153145

154146

155147
def test_run_error() -> None:
156-
with changing_dir(assets_path):
157-
result = runner.invoke(app, ["run", "non_existing_file.py"])
158-
assert result.exit_code == 1, result.output
159-
assert "Path does not exist non_existing_file.py" in result.output
148+
result = runner.invoke(app, ["run", "non_existing_file.py"])
149+
assert result.exit_code == 1, result.output
150+
assert "Path does not exist non_existing_file.py" in result.output
160151

161152

162153
def test_dev_help() -> None:

tests/test_requirements.py

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,33 @@
55
from fastapi_cli.exceptions import FastAPICLIException
66
from typer.testing import CliRunner
77

8-
from .utils import changing_dir
9-
108
runner = CliRunner()
119

1210
assets_path = Path(__file__).parent / "assets"
1311

1412

15-
def test_no_uvicorn() -> None:
13+
def test_no_uvicorn(monkeypatch: pytest.MonkeyPatch) -> None:
1614
import fastapi_cli.cli
17-
import uvicorn
18-
19-
fastapi_cli.cli.uvicorn = None # type: ignore[attr-defined, assignment]
20-
21-
with changing_dir(assets_path):
22-
result = runner.invoke(fastapi_cli.cli.app, ["dev", "single_file_app.py"])
23-
assert result.exit_code == 1
24-
assert result.exception is not None
25-
assert (
26-
"Could not import Uvicorn, try running 'pip install uvicorn'"
27-
in result.exception.args[0]
28-
)
2915

30-
fastapi_cli.cli.uvicorn = uvicorn # type: ignore[attr-defined]
16+
monkeypatch.setattr(fastapi_cli.cli, "uvicorn", None)
17+
monkeypatch.chdir(assets_path)
18+
result = runner.invoke(fastapi_cli.cli.app, ["dev", "single_file_app.py"])
19+
assert result.exit_code == 1
20+
assert result.exception is not None
21+
assert (
22+
"Could not import Uvicorn, try running 'pip install uvicorn'"
23+
in result.exception.args[0]
24+
)
3125

3226

33-
def test_no_fastapi() -> None:
27+
def test_no_fastapi(monkeypatch: pytest.MonkeyPatch) -> None:
3428
import fastapi_cli.discover
35-
from fastapi import FastAPI
3629

37-
fastapi_cli.discover.FastAPI = None # type: ignore[attr-defined, assignment]
38-
with changing_dir(assets_path):
39-
with pytest.raises(FastAPICLIException) as exc_info:
40-
get_import_string(path=Path("single_file_app.py"))
41-
assert "Could not import FastAPI, try running 'pip install fastapi'" in str(
42-
exc_info.value
43-
)
30+
monkeypatch.setattr(fastapi_cli.discover, "FastAPI", None)
31+
monkeypatch.chdir(assets_path)
4432

45-
fastapi_cli.discover.FastAPI = FastAPI # type: ignore[attr-defined]
33+
with pytest.raises(FastAPICLIException) as exc_info:
34+
get_import_string(path=Path("single_file_app.py"))
35+
assert "Could not import FastAPI, try running 'pip install fastapi'" in str(
36+
exc_info.value
37+
)

0 commit comments

Comments
 (0)