Skip to main content

jugar_probar/
harness.rs

1//! Test harness for running test suites.
2
3use std::time::{Duration, Instant};
4
5/// A test suite containing multiple tests
6#[derive(Debug, Clone)]
7pub struct TestSuite {
8    /// Suite name
9    pub name: String,
10    /// Tests in this suite
11    pub tests: Vec<TestCase>,
12}
13
14impl TestSuite {
15    /// Create a new test suite
16    #[must_use]
17    pub fn new(name: impl Into<String>) -> Self {
18        Self {
19            name: name.into(),
20            tests: Vec::new(),
21        }
22    }
23
24    /// Add a test case
25    pub fn add_test(&mut self, test: TestCase) {
26        self.tests.push(test);
27    }
28
29    /// Get the number of tests
30    #[must_use]
31    pub fn test_count(&self) -> usize {
32        self.tests.len()
33    }
34}
35
36/// A single test case
37#[derive(Debug, Clone)]
38pub struct TestCase {
39    /// Test name
40    pub name: String,
41    /// Test timeout in milliseconds
42    pub timeout_ms: u64,
43}
44
45impl TestCase {
46    /// Create a new test case
47    #[must_use]
48    pub fn new(name: impl Into<String>) -> Self {
49        Self {
50            name: name.into(),
51            timeout_ms: 30000, // 30 second default
52        }
53    }
54
55    /// Set timeout
56    #[must_use]
57    pub const fn with_timeout(mut self, ms: u64) -> Self {
58        self.timeout_ms = ms;
59        self
60    }
61}
62
63/// Result of running a single test
64#[derive(Debug, Clone)]
65pub struct TestResult {
66    /// Test name
67    pub name: String,
68    /// Whether test passed
69    pub passed: bool,
70    /// Error message if failed
71    pub error: Option<String>,
72    /// Test duration
73    pub duration: Duration,
74}
75
76impl TestResult {
77    /// Create a passing test result
78    #[must_use]
79    pub fn pass(name: impl Into<String>) -> Self {
80        Self {
81            name: name.into(),
82            passed: true,
83            error: None,
84            duration: Duration::ZERO,
85        }
86    }
87
88    /// Create a failing test result
89    #[must_use]
90    pub fn fail(name: impl Into<String>, error: impl Into<String>) -> Self {
91        Self {
92            name: name.into(),
93            passed: false,
94            error: Some(error.into()),
95            duration: Duration::ZERO,
96        }
97    }
98
99    /// Set duration
100    #[must_use]
101    pub const fn with_duration(mut self, duration: Duration) -> Self {
102        self.duration = duration;
103        self
104    }
105}
106
107/// Results from running a test suite
108#[derive(Debug, Clone)]
109pub struct SuiteResults {
110    /// Suite name
111    pub suite_name: String,
112    /// Individual test results
113    pub results: Vec<TestResult>,
114    /// Total duration
115    pub duration: Duration,
116}
117
118impl SuiteResults {
119    /// Check if all tests passed
120    #[must_use]
121    pub fn all_passed(&self) -> bool {
122        self.results.iter().all(|r| r.passed)
123    }
124
125    /// Count passed tests
126    #[must_use]
127    pub fn passed_count(&self) -> usize {
128        self.results.iter().filter(|r| r.passed).count()
129    }
130
131    /// Count failed tests
132    #[must_use]
133    pub fn failed_count(&self) -> usize {
134        self.results.iter().filter(|r| !r.passed).count()
135    }
136
137    /// Get total test count
138    #[must_use]
139    pub fn total(&self) -> usize {
140        self.results.len()
141    }
142
143    /// Get failed tests
144    #[must_use]
145    pub fn failures(&self) -> Vec<&TestResult> {
146        self.results.iter().filter(|r| !r.passed).collect()
147    }
148}
149
150/// Test harness for running suites
151#[derive(Debug, Default)]
152pub struct TestHarness {
153    /// Whether to stop on first failure
154    pub fail_fast: bool,
155    /// Whether to run tests in parallel
156    pub parallel: bool,
157}
158
159impl TestHarness {
160    /// Create a new test harness
161    #[must_use]
162    pub fn new() -> Self {
163        Self::default()
164    }
165
166    /// Enable fail-fast mode
167    #[must_use]
168    pub const fn with_fail_fast(mut self) -> Self {
169        self.fail_fast = true;
170        self
171    }
172
173    /// Enable parallel execution
174    #[must_use]
175    pub const fn with_parallel(mut self) -> Self {
176        self.parallel = true;
177        self
178    }
179
180    /// Run a test suite
181    #[must_use]
182    pub fn run(&self, suite: &TestSuite) -> SuiteResults {
183        let start = Instant::now();
184        let results = Vec::new();
185
186        // In a full implementation, this would actually run the tests
187        // For now, return empty results for an empty suite
188
189        SuiteResults {
190            suite_name: suite.name.clone(),
191            results,
192            duration: start.elapsed(),
193        }
194    }
195}