cli_testing_specialist/generator/test_generator_trait.rs
1use crate::error::Result;
2use crate::types::analysis::CliAnalysis;
3use crate::types::test_case::TestCategory;
4
5/// Common interface for all test generators
6///
7/// This trait provides a unified interface for generating tests in different formats:
8/// - BatsGenerator: Generates BATS shell test scripts
9/// - AssertCmdGenerator: Generates Rust tests using assert_cmd crate
10/// - SnapboxGenerator: Generates snapshot tests (future implementation)
11///
12/// Design rationale:
13/// - Maintainability: Single source of truth for test generation logic
14/// - Extensibility: Easy to add new test formats (e.g., pytest, Go tests)
15/// - Consistency: All generators follow the same pattern
16pub trait TestGenerator {
17 /// Generate tests for a specific category
18 ///
19 /// # Arguments
20 ///
21 /// * `analysis` - CLI analysis results containing subcommands, options, etc.
22 /// * `category` - Test category (basic, security, help, etc.)
23 ///
24 /// # Returns
25 ///
26 /// Generated test code as a String
27 ///
28 /// # Example
29 ///
30 /// ```ignore
31 /// let generator = AssertCmdGenerator::new()?;
32 /// let test_code = generator.generate(&analysis, TestCategory::Basic)?;
33 /// ```
34 fn generate(&self, analysis: &CliAnalysis, category: TestCategory) -> Result<String>;
35
36 /// Generate all test categories
37 ///
38 /// Convenience method to generate tests for all standard categories.
39 ///
40 /// # Arguments
41 ///
42 /// * `analysis` - CLI analysis results
43 ///
44 /// # Returns
45 ///
46 /// Map of category name to generated test code
47 fn generate_all(&self, analysis: &CliAnalysis) -> Result<Vec<(TestCategory, String)>> {
48 let categories = TestCategory::standard_categories();
49 let mut results = Vec::new();
50
51 for category in categories {
52 let test_code = self.generate(analysis, category)?;
53 results.push((category, test_code));
54 }
55
56 Ok(results)
57 }
58
59 /// Get the file extension for generated test files
60 ///
61 /// # Returns
62 ///
63 /// File extension (e.g., "bats", "rs", "snap")
64 fn file_extension(&self) -> &str;
65
66 /// Get the generator name
67 ///
68 /// # Returns
69 ///
70 /// Human-readable name (e.g., "BATS", "assert_cmd", "snapbox")
71 fn name(&self) -> &str;
72}
73
74/// Factory function to create a test generator by name
75///
76/// # Arguments
77///
78/// * `format` - Generator format name ("bats", "assert_cmd", "snapbox")
79///
80/// # Returns
81///
82/// Boxed TestGenerator instance
83///
84/// # Example
85///
86/// ```ignore
87/// let generator = create_generator("assert_cmd")?;
88/// let test_code = generator.generate(&analysis, TestCategory::Security)?;
89/// ```
90pub fn create_generator(format: &str) -> Result<Box<dyn TestGenerator>> {
91 match format.to_lowercase().as_str() {
92 "bats" => {
93 // Use existing BatsGenerator (to be refactored to implement TestGenerator)
94 Err(crate::error::CliTestError::InvalidFormat(
95 "BATS generator not yet refactored to use TestGenerator trait".to_string(),
96 ))
97 }
98 "assert_cmd" | "assert-cmd" => {
99 // Create AssertCmdGenerator
100 Err(crate::error::CliTestError::InvalidFormat(
101 "AssertCmdGenerator not yet implemented".to_string(),
102 ))
103 }
104 "snapbox" => {
105 // Future implementation
106 Err(crate::error::CliTestError::InvalidFormat(
107 "Snapbox generator not yet implemented".to_string(),
108 ))
109 }
110 _ => Err(crate::error::CliTestError::InvalidFormat(format!(
111 "Unknown generator format: {}",
112 format
113 ))),
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_create_generator_invalid_format() {
123 let result = create_generator("invalid");
124 assert!(result.is_err());
125 }
126
127 #[test]
128 fn test_create_generator_not_implemented() {
129 // These should fail until implemented
130 assert!(create_generator("bats").is_err());
131 assert!(create_generator("assert_cmd").is_err());
132 assert!(create_generator("snapbox").is_err());
133 }
134}