Lesson 9 — Testing, Logging, and Debugging
🎯 Learning Objectives
- Hiểu cách viết test trong Rust (unit, integration).
- Biết cách sử dụng crate log, env_logger cho logging.
- Làm quen với kỹ thuật debug: macro
dbg!, logging có cấp độ, và test assert.
✅ Explanation & Key Concepts
- Unit test: kiểm tra từng hàm/module, nằm trong cùng file với code.
- Integration test: kiểm tra hành vi tổng thể, nằm trong
tests/folder.
- Dùng crate
log(API) và backend nhưenv_logger. - Gọi
env_logger::init()trongmain. - Mức log:
error,warn,info,debug,trace.
💻 Example Implementation
Cargo.toml
[package]
name = "lesson09_testing_logging"
version = "0.1.0"
edition = "2024"
[dependencies]
log = "0.4"
env_logger = "0.11"
[dev-dependencies]
once_cell = "1"
src/main.rs
// cargo-deps: log="0.4", env_logger="0.11", once_cell="1" use log::{info, debug, error}; fn add(a: i32, b: i32) -> i32 { info!("Adding {a} and {b}"); a + b } fn divide(a: i32, b: i32) -> Option<i32> { if b == 0 { None } else { Some(a / b) } } fn main() { env_logger::init(); info!("Starting app"); let sum = add(4, 5); debug!("Sum = {sum}"); match divide(10, 0) { Some(v) => info!("Result = {v}"), None => error!("Division failed"), } dbg!(sum); } #[cfg(test)] mod tests { use super::*; use once_cell::sync::Lazy; static INIT: Lazy<()> = Lazy::new(|| { let _ = env_logger::builder().is_test(true).try_init(); }); #[test] fn test_add() { Lazy::force(&INIT); assert_eq!(add(2, 3), 5); } #[test] fn test_divide_by_zero() { Lazy::force(&INIT); assert_eq!(divide(10, 0), None); } }
🛠️ Hands-on Exercises
- Basic: Viết test cho hàm
multiplyvà kiểm tra kết quả đúng. - Intermediate: Dùng
env_loggerđể log khi test chạy (sử dụngonce_cellđể init logger 1 lần). - Challenge: Tạo custom macro
check!(nhưassert!nhưng log thêm info khi fail).
🐞 Common Pitfalls & Debugging Tips
- Quên gọi
env_logger::init()→ không thấy log. - Không set
RUST_BACKTRACE=1khi debug panic. - Ghi log quá nhiều (
trace!) gây noise và giảm performance.
🔄 Migration Notes (Rust 2024+)
- Crate
logvàenv_loggervẫn ổn định. - Có thể dùng
tracingcrate cho log nâng cao. - Rust 2024 cải thiện macro hygiene, giúp macro custom an toàn hơn.
📚 References
❓ Q & A — Câu hỏi thường gặp
Q1. Testing trong Rust khác gì so với ngôn ngữ khác?
- Rust biên dịch test cùng binary và chạy bằng
cargo test. Trình biên dịch tối ưu để test không ảnh hưởng đến bản release.
Q2. Vì sao nên dùng log thay vì println!?
loghỗ trợ nhiều cấp độ log, có thể lọc linh hoạt, định dạng rõ ràng — phù hợp cho production.
Q3. Làm sao debug hiệu quả mà không ảnh hưởng hiệu năng?
- Dùng
dbg!trong quá trình phát triển, sau đó chuyển sangdebug!hoặcinfo!có thể lọc qua biến môi trường (RUST_LOG=debug).
📖 Glossary of Terms
- Unit test: kiểm tra logic nhỏ, nằm trong file code.
- Integration test: test tổng thể, nằm trong thư mục
tests/. - Logger: hệ thống ghi log với cấp độ.
- dbg!: macro in giá trị + vị trí khi chạy.
🌿 Wisdom Note
Debugging cũng vậy: nhận ra điều mình chưa biết là khởi đầu của hiểu biết.