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