use crate::state::TestStatus;
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Serialize, Default)]
#[serde(default)]
pub struct TestMeta {
pub name: Option<String>,
pub summary: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub tags: Vec<String>,
pub owner: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub links: Vec<String>,
}
impl TestMeta {
pub fn is_empty(&self) -> bool {
self.name.is_none() && self.summary.is_none() && self.tags.is_empty()
}
pub fn from_file_meta(file_meta: &crate::parser::ast::FileMeta) -> Self {
Self {
name: file_meta.name.clone(),
summary: file_meta.summary.clone(),
tags: file_meta.tags.clone(),
owner: file_meta.owner.clone(),
links: file_meta.links.clone(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct TestResult {
pub name: String,
pub status: TestStatus,
pub duration_ms: u64,
pub grpc_duration_ms: Option<u64>,
pub error_message: Option<String>,
pub execution_time: i64,
#[serde(default, skip_serializing_if = "TestMeta::is_empty")]
pub meta: TestMeta,
}
impl TestResult {
pub fn pass(name: impl Into<String>, duration_ms: u64, grpc_duration_ms: Option<u64>) -> Self {
Self {
name: name.into(),
status: TestStatus::Pass,
duration_ms,
grpc_duration_ms,
error_message: None,
execution_time: crate::time::now_timestamp(),
meta: TestMeta::default(),
}
}
pub fn pass_with_meta(
name: impl Into<String>,
duration_ms: u64,
grpc_duration_ms: Option<u64>,
meta: TestMeta,
) -> Self {
Self {
name: name.into(),
status: TestStatus::Pass,
duration_ms,
grpc_duration_ms,
error_message: None,
execution_time: crate::time::now_timestamp(),
meta,
}
}
pub fn fail(
name: impl Into<String>,
error_message: String,
duration_ms: u64,
grpc_duration_ms: Option<u64>,
) -> Self {
Self {
name: name.into(),
status: TestStatus::Fail,
duration_ms,
grpc_duration_ms,
error_message: Some(error_message),
execution_time: crate::time::now_timestamp(),
meta: TestMeta::default(),
}
}
pub fn fail_with_meta(
name: impl Into<String>,
error_message: String,
duration_ms: u64,
grpc_duration_ms: Option<u64>,
meta: TestMeta,
) -> Self {
Self {
name: name.into(),
status: TestStatus::Fail,
duration_ms,
grpc_duration_ms,
error_message: Some(error_message),
execution_time: crate::time::now_timestamp(),
meta,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_test_result_pass() {
let result = TestResult::pass("test.gctf", 100, Some(50));
assert_eq!(result.name, "test.gctf");
assert_eq!(result.status, TestStatus::Pass);
assert_eq!(result.duration_ms, 100);
assert_eq!(result.grpc_duration_ms, Some(50));
assert!(result.error_message.is_none());
}
#[test]
fn test_test_result_pass_no_grpc() {
let result = TestResult::pass("test.gctf", 100, None);
assert_eq!(result.name, "test.gctf");
assert_eq!(result.status, TestStatus::Pass);
assert!(result.grpc_duration_ms.is_none());
}
#[test]
fn test_test_result_fail() {
let result = TestResult::fail("test.gctf", "error message".to_string(), 100, Some(50));
assert_eq!(result.name, "test.gctf");
assert_eq!(result.status, TestStatus::Fail);
assert_eq!(result.duration_ms, 100);
assert_eq!(result.grpc_duration_ms, Some(50));
assert_eq!(result.error_message, Some("error message".to_string()));
}
#[test]
fn test_test_result_clone() {
let result = TestResult::pass("test.gctf", 100, Some(50));
let cloned = result.clone();
assert_eq!(result.name, cloned.name);
assert_eq!(result.status, cloned.status);
}
#[test]
fn test_test_result_debug() {
let result = TestResult::pass("test.gctf", 100, Some(50));
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("test.gctf"));
assert!(debug_str.contains("Pass"));
}
}