Skip to content

Commit

Permalink
Display the pretty difference when a test fails
Browse files Browse the repository at this point in the history
  • Loading branch information
codingkarthik committed Feb 10, 2025
1 parent 0926e1a commit 2157b43
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 15 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ndc-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ serde = { workspace = true }
serde_json = { workspace = true, features = ["preserve_order"] }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "parking_lot"] }
url = { workspace = true }
pretty_assertions = "1.4.1"
20 changes: 12 additions & 8 deletions ndc-test/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ use serde::Deserialize;
pub struct ConnectorError {
pub status: reqwest::StatusCode,
pub error_response: ndc_models::ErrorResponse,
pub raw_response: serde_json::Value,
}

impl fmt::Display for ConnectorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ConnectorError {{ status: {0}, error_response.message: {1} }}",
self.status, self.error_response.message
"ConnectorError {{ status: {0}, error_response.message: {1}, raw_response: {2} }}",
self.status, self.error_response.message, self.raw_response
)
}
}
Expand All @@ -39,6 +40,7 @@ impl fmt::Display for InvalidConnectorError {
pub enum Error {
Reqwest(reqwest::Error),
Serde(serde_json::Error),
SerdeWithMessage(serde_json::Error, String),
Io(std::io::Error),
ConnectorError(ConnectorError),
InvalidConnectorError(InvalidConnectorError),
Expand All @@ -50,8 +52,9 @@ impl fmt::Display for Error {
let (module, e) = match self {
Error::Reqwest(e) => ("reqwest", e.to_string()),
Error::Serde(e) => ("serde", e.to_string()),
Error::SerdeWithMessage(e, message) => ("serde", format!("{}: {}", message, e)),
Error::Io(e) => ("IO", e.to_string()),
Error::ConnectorError(e) => ("response", format!("status code {}", e.status)),
Error::ConnectorError(e) => ("response", format!("status code {} error {}", e.status, e.raw_response.to_string())),
Error::InvalidConnectorError(e) => ("response", format!("status code {}", e.status)),
Error::InvalidBaseURL => ("url", "invalid base URL".into()),
};
Expand All @@ -64,6 +67,7 @@ impl error::Error for Error {
match self {
Error::Reqwest(e) => Some(e),
Error::Serde(e) => Some(e),
Error::SerdeWithMessage(e, _) => Some(e),
Error::Io(e) => Some(e),
Error::ConnectorError(_) | Error::InvalidConnectorError(_) | Error::InvalidBaseURL => {
None
Expand Down Expand Up @@ -211,14 +215,14 @@ fn construct_error(
let connector_error = ConnectorError {
status: response_status,
error_response,
raw_response: response_content,
};
Error::ConnectorError(connector_error)
}
// If we can't read the error response, respond as-is.
Err(_) => Error::InvalidConnectorError(InvalidConnectorError {
status: response_status,
content: response_content,
}),
Err(e) => {
let message = format!("failed to deserialize error response: {}", e);
Error::SerdeWithMessage(e, message)
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions ndc-test/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub type OtherError = Box<dyn std::error::Error + Send + Sync>;
pub enum Error {
#[error("error communicating with the connector: {0}")]
CommunicationError(#[from] super::client::Error),
#[error("error communicating with the connector: {0} ")]
CommunicationErrorWithContent(super::client::Error),
#[error("error generating test data: {0}")]
StrategyError(#[from] rand::Error),
#[error("error parsing semver range: {0}")]
Expand Down Expand Up @@ -60,8 +62,8 @@ pub enum Error {
CannotOpenSnapshotFile(std::io::Error),
#[error("error (de)serializing data structure: {0:?}")]
SerdeError(#[from] serde_json::Error),
#[error("snapshot did not match file {0}: {1}")]
ResponseDidNotMatchSnapshot(std::path::PathBuf, String),
#[error("snapshot did not match file {0}: {2}")]
ResponseDidNotMatchSnapshot(std::path::PathBuf, String, String),
#[error("cannot open benchmark directory: {0:?}")]
CannotOpenBenchmarkDirectory(std::io::Error),
#[error("cannot open benchmark report: {0:?}")]
Expand Down
17 changes: 13 additions & 4 deletions ndc-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Connector for client::Configuration {
}

async fn query(&self, request: models::QueryRequest) -> Result<models::QueryResponse> {
Ok(client::query_post(self, request).await?)
Ok(client::query_post(self, request).await.map_err(Error::CommunicationErrorWithContent)?)
}

async fn mutation(&self, request: models::MutationRequest) -> Result<models::MutationResponse> {
Expand Down Expand Up @@ -134,7 +134,7 @@ pub async fn test_snapshots_in_directory_with<
C: Connector,
R: Reporter,
Req: DeserializeOwned,
Res: DeserializeOwned + serde::Serialize + PartialEq,
Res: DeserializeOwned + serde::Serialize + PartialEq + std::fmt::Debug,
F: Future<Output = Result<Res>>,
>(
reporter: &mut R,
Expand All @@ -160,9 +160,18 @@ pub async fn test_snapshots_in_directory_with<
.map_err(Error::CannotOpenSnapshotFile)?;
let request = serde_json::from_reader(request_file)?;

let response = f(request).await?;
let response = f(request).await;

snapshot_test(snapshot_path, &response)
match response {
Ok(response) => snapshot_test(snapshot_path, &response),
Err(e) => {
Err(e)
}
}



// snapshot_test(snapshot_path, &response)
}
}
);
Expand Down
9 changes: 8 additions & 1 deletion ndc-test/src/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,24 @@ impl<'a, C: Connector> Connector for SnapshottingConnector<'a, C> {

pub fn snapshot_test<R>(snapshot_path: &Path, expected: &R) -> Result<()>
where
R: serde::Serialize + serde::de::DeserializeOwned + PartialEq,
R: serde::Serialize + serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
{
if snapshot_path.exists() {
let snapshot_file = File::open(snapshot_path).map_err(Error::CannotOpenSnapshotFile)?;
let snapshot: R = serde_json::from_reader(snapshot_file)?;
let compare: pretty_assertions::Comparison<R, R> = pretty_assertions::Comparison::new(&snapshot, expected);




if snapshot != *expected {
println!("Expected: {:?}", expected);
let actual = serde_json::to_string_pretty(&expected)?;

return Err(Error::ResponseDidNotMatchSnapshot(
snapshot_path.to_path_buf(),
actual,
format!("{}", compare),
));
}
} else {
Expand Down

0 comments on commit 2157b43

Please sign in to comment.