claude/skills/test-coverage-advisor/SKILL.md
Reviews test coverage and suggests missing test cases for error paths, edge cases, and business logic. Activates when users write tests or implement new features.
npx skillsauth add kendreaditya/.config test-coverage-advisorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert at comprehensive test coverage in Rust. When you detect tests or new implementations, proactively suggest missing test cases and coverage improvements.
Activate when you notice:
What to Look For: Missing happy path tests
Pattern:
#[test]
fn test_create_user_success() {
let user = User::new("[email protected]".to_string(), 25).unwrap();
assert_eq!(user.email(), "[email protected]");
assert_eq!(user.age(), 25);
}
What to Look For: Functions returning Result but no error tests
Missing Tests:
pub fn validate_email(email: &str) -> Result<(), ValidationError> {
if email.is_empty() {
return Err(ValidationError::Empty);
}
if !email.contains('@') {
return Err(ValidationError::InvalidFormat);
}
Ok(())
}
// ❌ NO TESTS for error cases!
Suggested Tests:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_email_success() {
assert!(validate_email("[email protected]").is_ok());
}
#[test]
fn test_validate_email_empty() {
let result = validate_email("");
assert!(matches!(result, Err(ValidationError::Empty)));
}
#[test]
fn test_validate_email_missing_at_sign() {
let result = validate_email("invalid");
assert!(matches!(result, Err(ValidationError::InvalidFormat)));
}
#[test]
fn test_validate_email_no_domain() {
let result = validate_email("test@");
assert!(matches!(result, Err(ValidationError::InvalidFormat)));
}
}
Suggestion Template:
Your function returns Result but I don't see tests for error cases. Consider adding:
#[test]
fn test_empty_input() {
let result = function("");
assert!(result.is_err());
}
#[test]
fn test_invalid_format() {
let result = function("invalid");
assert!(matches!(result, Err(SpecificError)));
}
What to Look For: Missing boundary tests
Common Edge Cases:
Pattern:
#[test]
fn test_empty_list() {
let result = process_items(vec![]);
assert!(result.is_empty());
}
#[test]
fn test_single_item() {
let result = process_items(vec![item]);
assert_eq!(result.len(), 1);
}
#[test]
fn test_max_size() {
let items = vec![item; 1000];
let result = process_items(items);
assert!(result.len() <= 1000);
}
What to Look For: Async functions without async tests
Pattern:
#[tokio::test]
async fn test_fetch_user_success() {
let repo = setup_test_repo().await;
let user = repo.find_user("123").await.unwrap();
assert_eq!(user.id(), "123");
}
#[tokio::test]
async fn test_fetch_user_not_found() {
let repo = setup_test_repo().await;
let result = repo.find_user("nonexistent").await;
assert!(result.is_err());
}
What to Look For: Multiple similar test cases
Before (Repetitive):
#[test]
fn test_valid_email1() {
assert!(validate_email("[email protected]").is_ok());
}
#[test]
fn test_valid_email2() {
assert!(validate_email("[email protected]").is_ok());
}
#[test]
fn test_invalid_email1() {
assert!(validate_email("invalid").is_err());
}
After (Table-Driven):
#[test]
fn test_email_validation() {
let test_cases = vec![
("[email protected]", true, "Valid email"),
("[email protected]", true, "Valid email with org TLD"),
("invalid", false, "Missing @ sign"),
("test@", false, "Missing domain"),
("@example.com", false, "Missing local part"),
("", false, "Empty string"),
];
for (email, should_pass, description) in test_cases {
let result = validate_email(email);
assert_eq!(
result.is_ok(),
should_pass,
"Failed for {}: {}",
email,
description
);
}
}
// BAD: Testing private fields
#[test]
fn test_internal_state() {
let obj = MyStruct::new();
assert_eq!(obj.internal_counter, 0); // Testing private implementation
}
// GOOD: Testing behavior
#[test]
fn test_public_behavior() {
let obj = MyStruct::new();
assert_eq!(obj.get_count(), 0); // Testing public interface
}
// BAD: No assertion
#[test]
fn test_function() {
function(); // What are we testing?
}
// GOOD: Clear assertion
#[test]
fn test_function() {
let result = function();
assert!(result.is_ok());
}
// BAD: Test does too much
#[test]
fn test_everything() {
// 100 lines of setup
// Multiple operations
// Many assertions
}
// GOOD: Focused tests
#[test]
fn test_create() { /* ... */ }
#[test]
fn test_update() { /* ... */ }
#[test]
fn test_delete() { /* ... */ }
# Using tarpaulin
cargo install cargo-tarpaulin
cargo tarpaulin --out Html
# Using llvm-cov
cargo install cargo-llvm-cov
cargo llvm-cov --html
cargo llvm-cov --open # Open in browser
#[cfg(test)]
mod tests {
use super::*;
// Helper functions
fn setup() -> TestData {
TestData::new()
}
// Success cases
mod success {
use super::*;
#[test]
fn test_valid_input() { /* ... */ }
}
// Error cases
mod errors {
use super::*;
#[test]
fn test_invalid_input() { /* ... */ }
#[test]
fn test_missing_data() { /* ... */ }
}
// Edge cases
mod edge_cases {
use super::*;
#[test]
fn test_empty_input() { /* ... */ }
#[test]
fn test_max_size() { /* ... */ }
}
}
When you see implementations:
When you see tests:
Proactively suggest missing tests to improve robustness.
development
Identify, categorize, and prioritize technical debt. Trigger with "tech debt", "technical debt audit", "what should we refactor", "code health", or when the user asks about code quality, refactoring priorities, or maintenance backlog.
tools
Comprehensive security scanning and vulnerability detection. Includes input validation, path traversal prevention, CVE detection, and secure coding pattern enforcement. Use when: authentication implementation, authorization logic, payment processing, user data handling, API endpoint creation, file upload handling, database queries, external API integration. Skip when: read-only operations on public data, internal development tooling, static documentation, styling changes.
development
Optimizes application performance. Use when performance requirements exist, when you suspect performance regressions, or when Core Web Vitals or load times need improvement. Use when profiling reveals bottlenecks that need fixing.
development
Modernize legacy systems without rewriting from scratch. Use strangler fig, facade, and strategic refactoring.