Skills Plugins MCP Prompt Model 博客 我的中心

rust-testing

Rust测试模式,包括单元测试、集成测试、异步测试、基于属性的测试、模拟和覆盖率。遵循TDD方法学。

DeepseekModel Curated skill Quality Excellent · 90 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-zh-cn-skills-rust-testing-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name rust-testing description Rust测试模式,包括单元测试、集成测试、异步测试、基于属性的测试、模拟和覆盖率。遵循TDD方法学。 origin ECC Rust 测试模式 遵循 TDD 方法论编写可靠、可维护测试的全面 Rust 测试模式。 何时使用 编写新的 Rust 函数、方法或特征 为现有代码添加测试覆盖率 为性能关键代码创建基准测试 为输入验证实现基于属性的测试 在 Rust 项目中遵循 TDD 工作流 工作原理 识别目标代码 — 找到要测试的函数、特征或模块 编写测试 — 在 #[cfg(test)] 模块中使用 #[test] ,使用 rstest 进行参数化测试,或使用 proptest 进行基于属性的测试 模拟依赖项 — 使用 mockall 来隔离被测单元 运行测试 (RED) — 验证测试是否按预期失败 实现 (GREEN) — 编写最少代码以通过测试 重构 — 改进代码同时保持测试通过 检查覆盖率 — 使用 cargo-llvm-cov,目标 80% 以上 Rust 的 TDD 工作流 RED-GREEN-REFACTOR 循环 RED → 先写一个失败的测试 GREEN → 编写最少代码使测试通过 REFACTOR → 重构代码,同时保持测试通过 REPEAT → 继续下一个需求 Rust 中的分步 TDD // RED: Write test first, use todo!() as placeholder pub fn add (a: i32 , b: i32 ) -> i32 { todo!() } #[cfg(test)] mod tests { use super::*; #[test] fn test_add () { assert_eq! ( add ( 2 , 3 ), 5 ); } } // cargo test → panics at 'not yet implemented' // GREEN: Replace todo!() with minimal implementation pub fn add (a: i32 , b: i32 ) -> i32 { a + b } // cargo test → PASS, then REFACTOR while keeping tests green 单元测试 模块级测试组织 // src/user.rs pub struct User { pub name: String , pub email: String , } impl User { pub fn new (name: impl Into < String >, email: impl Into < String >) -> Result < Self , String > { let email = email. into (); if !email. contains ( '@' ) { return Err ( format! ( "invalid email: {email}" )); } Ok ( Self { name: name. into (), email }) } pub fn display_name (& self ) -> & str { & self .name } } #[cfg(test)] mod tests { use super::*; #[test] fn creates_user_with_valid_email () { let user = User:: new ( "Alice" , "alice@example.com" ). unwrap (); assert_eq! (user. display_name (), "Alice" ); assert_eq! (user.email, "alice@example.com" ); } #[test] fn rejects_invalid_email () { let result = User:: new ( "Bob" , "not-an-email" ); assert! (result. is_err ()); assert! (result. unwrap_err (). contains ( "invalid email" )); } } 断言宏 assert_eq! ( 2 + 2 , 4 ); // Equality assert_ne! ( 2 + 2 , 5 ); // Inequality assert! ( vec! [ 1 , 2 , 3 ]. contains (& 2 )); // Boolean assert_eq! (value, 42 , "expected 42 but got {value}" ); // Custom message assert! (( 0.1_f64 + 0.2 - 0.3 ). abs () < f64 ::EPSILON); // Float comparison 错误与 Panic 测试 测试 Result 返回值 #[test] fn parse_returns_error_for_invalid_input () { let result = parse_config ( "}{invalid" ); assert! (result. is_err ()); // Assert specific error variant let err = result. unwrap_err (); assert! (matches!(err, ConfigError:: ParseError (_))); } #[test] fn parse_succeeds_for_valid_input () -> Result <(), Box < dyn std::error::Error>> { let config = parse_config ( r#"{"port": 8080}"# )?; assert_eq! (config.port, 8080 ); Ok (()) // Test fails if any ? returns Err } 测试 Panic #[test] #[should_panic] fn panics_on_empty_input () { process (&[]); } #[test] #[should_panic(expected = "index out of bounds" )] fn panics_with_specific_message () { let v : Vec < i32 > = vec! []; let _ = v[ 0 ]; } 集成测试 文件结构 my_crate/ ├── src/ │ └── lib.rs ├── tests/ # 集成测试 │ ├── api_test.rs # 每个文件都是一个独立的测试二进制文件 │ ├── db_test.rs │ └── common/ # 共享测试工具 │ └── mod.rs 编写集成测试 // tests/api_test.rs use my_crate::{App, Config}; #[test] fn full_request_lifecycle () { let config = Config:: test_default (); let app = App:: new (config); let response = app. handle_request ( "/health" ); assert_eq! (response.status, 200 ); assert_eq! (response.body, "OK" ); } 异步测试 使用 Tokio #[tokio::test] async fn fetches_data_successfully () { let client = TestClient:: new (). await ; let result = client. get ( "/data" ). await ; assert! (result. is_ok ()); assert_eq! (result. unwrap ().items. len (), 3 ); } #[tokio::test] async fn handles_timeout () { use std::time::Duration; let result = tokio::time:: timeout ( Duration:: from_millis ( 100 ), slow_operation (), ). await ; assert! (result. is_err (), "should have timed out" ); } 测试组织模式 使用 rstest 进行参数化测试 use rstest::{rstest, fixture}; #[rstest] #[case( "hello" , 5)] #[case( "" , 0)] #[case( "rust" , 4)] fn test_string_length ( #[case] input: & str , #[case] expected: usize ) { assert_eq! (input. len (), expected); } // Fixtures #[fixture] fn test_db () -> TestDb { TestDb:: new_in_memory () } #[rstest] fn test_insert (test_db: TestDb) { test_db. insert ( "key" , "value" ); assert_eq! (test_db. get ( "key" ), Some ( "value" . into ())); } 测试辅助函数 #[cfg(test)] mod tests { use super::*; /// Creates a test user with sensible defaults. fn make_user (name: & str ) -> User { User:: new (name, & format! ( "{name}@test.com" )). unwrap () } #[test] fn user_display () { let user = make_user ( "alice" ); assert_eq! (user. display_name (), "alice" ); } } 使用 proptest 进行基于属性的测试 基本属性测试 use proptest::prelude::*; proptest! { #[test] fn encode_decode_roundtrip (input in ".*" ) { let encoded = encode (&input); let decoded = decode (&encoded). unwrap (); assert_eq! (input, decoded); } #[test] fn sort_preserves_length ( mut vec in prop::collection:: vec (any::< i32 >(), 0 .. 100 )) { let original_len = vec. len (); vec. sort (); assert_eq! (vec. len (), original_len); } #[test] fn sort_produces_ordered_output ( mut vec in prop::collection:: vec (any::< i32 >(), 0 .. 100 )) { vec. sort (); for window in vec. windows ( 2 ) { assert! (window[ 0 ] <= window[ 1 ]); } } } 自定义策略 use proptest::prelude::*; fn valid_email () -> impl Strategy <Value = String > { ( "[a-z]{1,10}" , "[a-z]{1,5}" ) . prop_map (|(user, domain)| format! ( "{user}@{domain}.com" )) } proptest! { #[test] fn accepts_valid_emails (email in valid_email ()) { assert! (User:: new ( "Test" , &email). is_ok ()); } } 使用 mockall 进行模拟 基于特征的模拟 use mockall::{automock, predicate::eq}; #[automock] trait UserRepository { fn find_by_id (& self , id: u64 ) -> Option <User>; fn save (& self , user: &User) -> Result <(), StorageError>; } #[test] fn service_returns_user_when_found () { let mut mock = MockUserRepository:: new (); mock. expect_find_by_id () . with ( eq ( 42 )) . times ( 1 ) . returning (|_| Some (User { id: 42 , name: "Alice" . into () })); let service = UserService:: new ( Box :: new (mock)); let user = service. get_user ( 42 ). unwrap (); assert_eq! (user.name, "Alice" ); } #[test] fn service_returns_none_when_not_found () { let mut mock = MockUserRepository:: new (); mock. expect_find_by_id () . returning (|_| None ); let service = UserService:: new ( Box :: new (mock)); assert! (service. get_user ( 99 ). is_none ()); } 文档测试 可执行的文档 /// Adds two numbers together. /// /// # Examples /// /// ``` /// use my_crate::add; /// /// assert_eq!(add(2, 3), 5); /// assert_eq!(add(-1, 1), 0); /// ``` pub fn add (a: i32 , b: i32 ) -> i32 { a + b } /// Parses a config string. /// /// # Errors /// /// Returns `Err` if the input is not valid TOML. /// /// ```no_run /// use my_crate::parse_config; /// /// let config = parse_config(r#"port = 8080"#).unwrap(); /// assert_eq!(config.port, 8080); /// ``` /// /// ```no_run /// use my_crate::parse_config; /// /// assert!(parse_config("}{invalid").is_err());
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。