Rust टेस्ट में println! काम क्यों नहीं करता? पूरी जानकारी

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

परिचय: "गूंगा" println! — Rust सीखने वालों की आम समस्या

\n\n

आप अपना पहला Rust unit test लिख रहे हैं। सब कुछ सही है: एक struct बनाया, method implement किया, और फिर — जाँच का पल। आपने println! डाला test में, यह देखने के लिए कि data सही है या नहीं। cargo test चलाया... और सिर्फ एक सूखी लाइन दिखी: "test result: ok. 1 passed; 0 failed"। कोई "Hello, world!" नहीं, कोई intermediate value नहीं। आपका println! बस गायब हो गया।

\n\n

परिचित लग रहा है? स्वागत है क्लब में। Stack Overflow पर इस सवाल के हज़ारों व्यूज़ हैं, और यह Rust testing सीखने वालों के लिए एक बड़ी रुकावट है। इस article में हम सिर्फ "use --nocapture" नहीं कहेंगे। हम समझेंगे कि ऐसा क्यों होता है, test runner में capture (आउटपुट कैप्चर) कैसे काम करता है, और unit testing के सिद्धांतों को तोड़े बिना code को कैसे debug करें।

\n\n

Rust test में println! को क्यों "बंद" कर देता है?

\n\n

यह कोई bug नहीं है, न ही language designers की कोई बुरी नीयत। यह एक सोचा-समझा architectural decision है। जब आप cargo test चलाते हैं, तो Rust tests को clean और predictable बनाता है। सोचिए, अगर आपके 500 tests हों और हर एक stdout में 10 lines debug output डाले, तो आपका terminal गड़बड़ हो जाएगा, और असली errors को debug मैसेज से अलग पहचानना मुश्किल हो जाएगा।

\n\n

डिफ़ॉल्ट रूप से, test runner (test library) पूरे standard output (std::io::stdout()) और standard error output (std::io::stderr()) को इंटरसेप्ट कर लेता है। यह system descriptors के level पर होता है। println! stdout में ही लिखता है, इसलिए इसका आउटपुट runner के "ब्लैक बॉक्स" में चला जाता है। आउटपुट तभी दिखता है जब test फेल होता है — ताकि आप देख सकें कि क्या गलत हुआ।

\n\n

Code में यह कैसा दिखता है?

\n\n

आइए एक सरल उदाहरण देखें जो इस समस्या को दिखाता है:

\n\n
// src/lib.rs\npub fn add_two(a: i32) -> i32 {\n    a + 2\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_add_two() {\n        println!("मैं चल रहा हूँ, लेकिन मुझे देखा नहीं जा सकता!");\n        let result = add_two(2);\n        println!("परिणाम: {}", result);\n        assert_eq!(result, 4);\n    }\n}
\n\n

चलाते हैं:

\n\n
$ cargo test\n   Compiling my_project v0.1.0\n    Finished test [unoptimized + debuginfo] target(s) in 0.5s\n     Running unittests src/lib.rs (target/debug/deps/my_project-abc123)\n\nrunning 1 test\ntest tests::test_add_two ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
\n\n

जैसा कि आप देख सकते हैं, println! का कोई भी message नहीं दिखा। Test पास हो गया, और runner ने सोचा कि आपको दिखाने के लिए कुछ नहीं है।

\n\n

println! को कैसे "जगाएं"? तरीके और सावधानियाँ

\n\n

तीन मुख्य तरीके हैं, और हर एक अपनी स्थिति के लिए उपयुक्त है।

\n\n

तरीका 1: --nocapture फ्लैग (सबसे आसान और लोकप्रिय)

\n\n

यह वही है जो आपको Stack Overflow के पहले जवाब में मिलेगा। --nocapture फ्लैग वर्तमान रन में सभी tests के लिए output capture को बंद कर देता है।

\n\n
$ cargo test -- --nocapture
\n\n

डबल डैश -- पर ध्यान दें। यह cargo के arguments और test binary के arguments को अलग करता है। -- के बाद सब कुछ test runner को जाता है।

\n\n

अब आउटपुट ऐसा होगा:

\n\n
$ cargo test -- --nocapture\n   Compiling my_project v0.1.0\n    Finished test [unoptimized + debuginfo] target(s) in 0.5s\n     Running unittests src/lib.rs (target/debug/deps/my_project-abc123)\n\nrunning 1 test\nमैं चल रहा हूँ, लेकिन मुझे देखा नहीं जा सकता!\nपरिणाम: 4\ntest tests::test_add_two ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered                

ब्लॉग

पुस्तक अनुशंसाएँ