Coverage for tests/test_utils_cli.py: 100%
39 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-11 09:18 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-11 09:18 +0000
1import io 1abcdefghijklmn
2import logging 1abcdefghijklmn
3import sys 1abcdefghijklmn
4from logging.config import dictConfig 1abcdefghijklmn
6from pytest import LogCaptureFixture, MonkeyPatch 1abcdefghijklmn
8from fastapi_cli.utils.cli import ( 1abcdefghijklmn
9 CustomFormatter,
10 get_uvicorn_log_config,
11 should_use_rich_logs,
12)
15def test_get_uvicorn_config_uses_custom_formatter() -> None: 1abcdefghijklmn
16 config = get_uvicorn_log_config() 1456789!#$%'()*
18 assert config["formatters"]["default"]["()"] is CustomFormatter 1456789!#$%'()*
19 assert config["formatters"]["access"]["()"] is CustomFormatter 1456789!#$%'()*
20 assert config["loggers"]["uvicorn"]["propagate"] is False 1456789!#$%'()*
23def test_should_use_rich_logs_is_false_without_tty( 1abcdefghijklmn
24 monkeypatch: MonkeyPatch,
25) -> None:
26 monkeypatch.setattr(sys, "stdout", io.StringIO()) 1+,-./:;=?@[]^_
28 assert should_use_rich_logs() is False 1+,-./:;=?@[]^_
31def test_custom_formatter() -> None: 1abcdefghijklmn
32 formatter = CustomFormatter() 1CDEFGHIJKLMNOP
34 record = logging.LogRecord( 1CDEFGHIJKLMNOP
35 name="uvicorn.access",
36 level=logging.INFO,
37 pathname="",
38 lineno=0,
39 msg="%(client_addr)s - '%(request_line)s' %(status_code)s",
40 args={
41 "client_addr": "127.0.0.1",
42 "request_line": "GET / HTTP/1.1",
43 "status_code": 200,
44 },
45 exc_info=None,
46 )
48 formatted = formatter.formatMessage(record) 1CDEFGHIJKLMNOP
50 # the log level is shown as a colored bar bullet, like `fastapi cloud logs`
51 assert "▕" in formatted 1CDEFGHIJKLMNOP
52 assert "127.0.0.1" in formatted 1CDEFGHIJKLMNOP
53 assert "GET / HTTP/1.1" in formatted 1CDEFGHIJKLMNOP
54 assert "200" in formatted 1CDEFGHIJKLMNOP
57def test_custom_formatter_shutdown_prepends_newline() -> None: 1abcdefghijklmn
58 formatter = CustomFormatter() 1QRSTUVWXYZ0123
60 record = logging.LogRecord( 1QRSTUVWXYZ0123
61 name="uvicorn.error",
62 level=logging.INFO,
63 pathname="",
64 lineno=0,
65 msg="Shutting down",
66 args=(),
67 exc_info=None,
68 )
70 formatted = formatter.formatMessage(record) 1QRSTUVWXYZ0123
72 assert formatted.startswith("\n") 1QRSTUVWXYZ0123
73 assert "Shutting down" in formatted 1QRSTUVWXYZ0123
76def test_log_config_does_not_disable_existing_loggers( 1abcdefghijklmn
77 caplog: LogCaptureFixture,
78) -> None:
79 logger1 = logging.getLogger(__name__) 1opqrstuvwxyzAB
80 logger1.setLevel(logging.INFO) 1opqrstuvwxyzAB
81 logger1.info("Message before configuration") 1opqrstuvwxyzAB
83 dictConfig(get_uvicorn_log_config()) 1opqrstuvwxyzAB
85 logger2 = logging.getLogger(__name__) 1opqrstuvwxyzAB
87 logger1.info("Message after configuration from logger1") # Should not appear 1opqrstuvwxyzAB
88 logger2.info("Message from logger2") 1opqrstuvwxyzAB
90 assert "Message before configuration" in caplog.text 1opqrstuvwxyzAB
91 assert "Message after configuration from logger1" in caplog.text 1opqrstuvwxyzAB
92 assert "Message from logger2" in caplog.text 1opqrstuvwxyzAB