Почему println! не выводит текст в юнит-тестах Rust?
Причина: тесты по умолчанию подавляют вывод
Вы столкнулись с ожидаемым поведением Rust — это не баг, а особенность системы тестирования. Когда вы запускаете тесты командой cargo test, все вызовы println! внутри успешных тестов автоматически подавляются. Вывод появляется только для провалившихся тестов. Это сделано для того, чтобы консоль не засорялась отладочной информацией при прогоне сотен тестов.
Решение 1: Запускайте тесты с флагом --nocapture
Самый простой способ увидеть вывод println! — передать флаг --nocapture (или --show-output):
cargo test -- --nocapture
Теперь ваш тест выведет:
running 1 test
Результат: 5
test tests::test_add ... ok
Флаг -- отделяет аргументы для cargo test от аргументов для самого тестового раннера.
Решение 2: Используйте макрос eprintln! для stderr
Если вы хотите видеть вывод только при ошибках, используйте eprintln! — он пишет в stderr и не подавляется:
#[test]
fn test_add() {
let result = add(2, 3);
eprintln!("Отладка: результат = {}", result);
assert_eq!(result, 5);
}
При запуске cargo test вывод будет:
running 1 test
Отладка: результат = 5
test tests::test_add ... ok
Решение 3: Создайте тест, который заведомо провалится
Если нужно быстро проверить вывод без изменения флагов, добавьте временный assert!(false):
#[test]
fn debug_test() {
println!("Значение: {}", 42);
assert!(false); // Теперь вывод появится
}
Почему это так работает?
- Производительность: Вывод в консоль — медленная операция. При 10 000 тестах подавление вывода ускоряет прогон.
- Чистота: Вы видите только результаты тестов (ok/fail), а не мешанину из отладочных сообщений.
- CI/CD: В системах непрерывной интеграции (GitHub Actions, Jenkins) подавленный вывод не засоряет логи.
Важно: не используйте println! для ассертов
Помните, что println! не влияет на результат теста. Если вам нужно проверить значение, используйте assert_eq! или assert!. Например:
#[test]
fn test_add() {
let result = add(2, 3);
println!("Отладка: {}", result); // Вывод только с --nocapture
assert_eq!(result, 5); // Реальная проверка
}
<<Альтернативный подход: логирование через библиотеку log
Если вам нужно более гибкое управление выводом, используйте крейт log с env_logger. Это позволит включать/отключать отладку без изменения кода тестов:
// Cargo.toml
[dependencies]
log = "0.4"
env_logger = "0.10"
// В тесте:
#[test]
fn test_with_log() {
env_logger::init(); // Инициализация один раз
log::info!("Результат: {}", add(2, 3));
assert_eq!(add(2, 3), 5);
}
Запускайте с переменной окружения:
RUST_LOG=info cargo test -- --nocapture
Для VSCode и IntelliJ
В редакторах кода можно добавить --nocapture в конфигурацию запуска тестов. В VSCode откройте .vscode/settings.json и добавьте:
"rust-analyzer.runnables.extraArgs": ["--nocapture"]
Когда использовать каждый метод?
- --nocapture: Быстрая отладка одного теста.
- eprintln!: Постоянная отладка, видимая всегда.
- log: Профессиональные проекты с уровнями логирования.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги