## TL;DR
Call `caplog.set_level(logging.INFO)` (or the level you need) at the start of the test, then assert on `caplog.records` or `caplog.text`. The caplog handler listens at WARNING by default, so anything logged below that never reaches the fixture, which is the cause in most cases.

## Problem
A test uses the `caplog` fixture but `caplog.text` is empty or missing records even though the code under test calls `logger.info(...)` or similar.

## Steps
1. Set the capture level explicitly as the first line of the test:
   ```python
   import logging

   def test_logs_something(caplog):
       with caplog.at_level(logging.INFO):
           run_the_code()
       assert "expected message" in caplog.text
   ```
   (`caplog.at_level` is a context manager; `caplog.set_level` outside it works too.)
   Expected: `caplog.text` now contains the logged message.
2. If records are still missing, check the logger name your code uses and set the level on it:
   ```python
   with caplog.at_level(logging.DEBUG, logger="myapp.worker"):
       run_the_code()
   ```
   Expected: records from that named logger appear in `caplog.records`.
3. If a library configures logging itself (dictConfig or basicConfig at import), its handlers may swallow records before they propagate. Move the `caplog.set_level` call to after the import of the module under test, or clear pre-existing handlers in a fixture.
   Expected: after moving the level call past the import and config, records appear.
4. Confirm propagation is not disabled: the logger your code uses must propagate to the root logger where caplog listens. If the library sets `propagate = False`, `caplog.at_level(..., logger="that.name")` adds the handler directly to the named logger instead.
   Expected: `caplog.records` is non-empty for that logger.

## When to use
- `caplog.text` empty while the code definitely logs.
- INFO or DEBUG logs missing but WARNING logs appear.
- Third-party library logs not showing up in tests.

## When not to use
- You want live log output during the run (use `-o log_cli=true` instead).
- Logs from subprocesses (caplog only sees the test process).
- You are testing `print()` output (use `capsys`).

## Tool compatibility
- pytest 8.x built-in `caplog` fixture; the `at_level` context manager is available since pytest 3.4.
- Standard library `logging`; no plugins needed.

## Variant phrasings
### caplog.text is empty in pytest
Almost always the level: default capture is WARNING. Set it lower as above.
### caplog not capturing logger.info messages
Same fix; also verify the logger name matches the one your code writes to.

## Why it happens
caplog works by adding a handler to the root logger, but that handler and the logger levels default to WARNING. `logger.info()` calls are filtered before they ever reach the handler, so nothing is captured.

## Edge cases
- `logging.config.dictConfig` with `disable_existing_loggers: True` can detach pytest's handler; set levels after the config runs.
- Logs emitted at import time (module top level) happen before caplog exists; move the logging call into a function or perform the import inside the test.
- `caplog` and `log_cli` are independent; one showing output does not mean the other captured it.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_xa8lvy2rpw391nentMkGew
