Rust में उन्नत परीक्षण: यूनिट से E2E तक
\nपरीक्षण Rust पर विश्वसनीय सिस्टम सॉफ्टवेयर विकास का एक अनिवार्य हिस्सा है। यदि बुनियादी अवधारणाएँ (#[test] के साथ सरल परीक्षण लिखना) सभी को ज्ञात हैं, तो उन्नत तकनीकें - मॉक के साथ काम करना, पैरामीटराइज़ेशन, कस्टम एट्रीब्यूट्स और E2E-परीक्षणों का आयोजन - एक अलग विश्लेषण की आवश्यकता है। इस लेख में, हम देखेंगे कि यूनिट, इंटीग्रेशन और एंड-टू-एंड दृष्टिकोणों का उपयोग करके Rust परीक्षण को पेशेवर स्तर पर कैसे लाया जाए।
1. यूनिट-परीक्षण: मॉक, पैरामीटराइज़ेशन और कस्टम एट्रीब्यूट्स
\nRust में यूनिट-टेस्ट आमतौर पर कोड के समान फ़ाइल में, मॉड्यूल tests में लिखे जाते हैं। हालाँकि, उन्नत स्तर पर, परीक्षण किए जा रहे कोड को बाहरी निर्भरताओं से अलग करने की आवश्यकता उत्पन्न होती है।
ट्रेट्स के साथ मॉक-ऑब्जेक्ट्स
\nRust में मॉक बनाने के लिए, आमतौर पर ट्रेट्स का उपयोग किया जाता है। आप एक ट्रेट परिभाषित करते हैं, इसे वास्तविक ऑब्जेक्ट और परीक्षण मॉक के लिए लागू करते हैं। लोकप्रिय क्रेट्स: mockall और mockito (HTTP के लिए)।
use mockall::automock;\n\n#[automock]\ntrait Database {\n fn get_user(&self, id: u32) -> String;\n}\n\nfn process_user(db: &dyn Database, id: u32) -> String {\n let user = db.get_user(id);\n format!("User: {}", user)\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_process_user() {\n let mut mock = MockDatabase::new();\n mock.expect_get_user()\n .with(predicate::eq(42))\n .returning(|_| "Alice".to_string());\n assert_eq!(process_user(&mock, 42), "User: Alice");\n }\n}\n\nपैरामीटराइज़्ड टेस्ट
\nएक ही परीक्षण को विभिन्न इनपुट डेटा के साथ दोहराना एक सामान्य कार्य है। क्रेट rstest एक सुंदर समाधान प्रदान करता है।
use rstest::rstest;\n\n#[rstest]\n#[case(2, 3, 5)]\n#[case(0, 0, 0)]\n#[case(-1, 1, 0)]\nfn test_add(#[case] a: i32, #[case] b: i32, #[case] expected: i32) {\n assert_eq!(a + b, expected);\n}\n\nकस्टम टेस्ट एट्रीब्यूट्स
\nकभी-कभी परीक्षण से पहले या बाद में तर्क की आवश्यकता होती है। आप प्रक्रियात्मक मैक्रोज़ के माध्यम से अपने स्वयं के एट्रीब्यूट्स बना सकते हैं, लेकिन आरंभीकरण के लिए क्रेट test-case या ctor का उपयोग करना आसान है।
// लॉगर आरंभीकरण के लिए ctor के साथ उदाहरण\n#[cfg(test)]\nmod tests {\n use ctor::ctor;\n\n #[ctor]\n fn init() {\n // सभी परीक्षणों से पहले एक बार आरंभीकरण\n }\n}\n\n2. इंटीग्रेशन परीक्षण: संगठन और बाहरी निर्भरताओं के साथ कार्य
\nRust में इंटीग्रेशन टेस्ट प्रोजेक्ट की रूट लेवल पर tests/ फ़ोल्डर में स्थित होते हैं। वहाँ प्रत्येक फ़ाइल एक अलग क्रेट है। उन्नत तकनीकों में सामान्य मॉड्यूल और वास्तविक DB या API के साथ परीक्षण शामिल हैं।
इंटीग्रेशन टेस्ट के लिए सामान्य उपयोगिताएँ
\nकोड को दोहराने से बचने के लिए (उदाहरण के लिए, टेस्ट सर्वर सेटअप), tests/ के अंदर एक मॉड्यूल common बनाएँ।
// tests/common/mod.rs\npub fn setup_test_db() -> String {\n // टेस्ट DB सेटअप\n "connected".to_string()\n}\n\n// tests/integration_test.rs\nmod common;\n\n#[test]\nfn test_db_connection() {\n let db = common::setup_test_db();\n assert_eq!(db, "connected");\n}\n\nHTTP अनुरोधों के साथ कार्य
\nHTTP क्लाइंट के परीक्षण के लिए mockito का उपयोग करें - यह एक स्थानीय मॉक-सर्वर शुरू करता है।
use mockito::{mock, server_url};\n\n#[tokio::test]\nasync fn test_api_call() {\n let _m = mock("GET", "/users/1")\n .with_status(200)\n .with_body(r#"{"id":1,"name":"Alice"}"#)\n .create();\n\n let client = reqwest::Client::new();\n let resp = client.get(&format!("{}/users/1", server_url()))\n .send()\n .await\n .unwrap();\n assert!(resp.status().is_success());\n}\n\n3. E2E-परीक्षण: एप्लिकेशन का पूरा चक्र
\nएंड-टू-एंड टेस्ट पूरे सिस्टम के कामकाज की जाँच करते हैं: लॉन्च से लेकर...