Skip to main content

use_test_outcome/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4/// Stable vocabulary for completed test outcomes.
5#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
6pub enum TestOutcome {
7    Passed,
8    Failed,
9    Skipped,
10    Errored,
11    ExpectedFailure,
12    UnexpectedPass,
13}
14
15impl TestOutcome {
16    pub const fn is_success(self) -> bool {
17        matches!(self, Self::Passed | Self::ExpectedFailure)
18    }
19
20    pub const fn is_failure(self) -> bool {
21        matches!(self, Self::Failed | Self::Errored | Self::UnexpectedPass)
22    }
23
24    pub const fn is_terminal(self) -> bool {
25        match self {
26            Self::Passed
27            | Self::Failed
28            | Self::Skipped
29            | Self::Errored
30            | Self::ExpectedFailure
31            | Self::UnexpectedPass => true,
32        }
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::TestOutcome;
39
40    #[test]
41    fn classifies_success_outcomes() {
42        assert!(TestOutcome::Passed.is_success());
43        assert!(TestOutcome::ExpectedFailure.is_success());
44        assert!(!TestOutcome::Skipped.is_success());
45    }
46
47    #[test]
48    fn classifies_failure_outcomes() {
49        assert!(TestOutcome::Failed.is_failure());
50        assert!(TestOutcome::Errored.is_failure());
51        assert!(TestOutcome::UnexpectedPass.is_failure());
52        assert!(!TestOutcome::ExpectedFailure.is_failure());
53    }
54
55    #[test]
56    fn all_outcomes_are_terminal() {
57        let outcomes = [
58            TestOutcome::Passed,
59            TestOutcome::Failed,
60            TestOutcome::Skipped,
61            TestOutcome::Errored,
62            TestOutcome::ExpectedFailure,
63            TestOutcome::UnexpectedPass,
64        ];
65
66        assert!(outcomes.into_iter().all(TestOutcome::is_terminal));
67    }
68}