symbolic_testutils/
lib.rs

1use std::fs::File;
2use std::io::prelude::*;
3use std::path::{Path, PathBuf};
4use std::{fmt, io};
5
6use difference::Changeset;
7
8/// Loads the file at the given location and returns its contents as string.
9fn load_file<P: AsRef<Path>>(path: P) -> io::Result<String> {
10    let mut file = File::open(path)?;
11    let mut buffer = String::new();
12    file.read_to_string(&mut buffer)?;
13    Ok(buffer)
14}
15
16/// Resolves the full path to a fixture file.
17pub fn fixture_path<S: AsRef<str>>(file_name: S) -> PathBuf {
18    Path::new("..")
19        .join("testutils")
20        .join("fixtures")
21        .join(file_name.as_ref())
22}
23
24/// Loads the fixture file with the given name and returns its contents
25/// as String.
26pub fn load_fixture<S: AsRef<str>>(file_name: S) -> io::Result<String> {
27    load_file(fixture_path(file_name))
28}
29
30/// Asserts that the given object matches the snapshot saved in the snapshot
31/// file. The object is serialized using the Debug trait.
32///
33/// If the value differs from the snapshot, the assertion fails and prints
34/// a colored diff output.
35pub fn assert_snapshot<S: AsRef<str>, T: fmt::Debug>(snapshot_name: S, val: &T) {
36    assert_snapshot_plain(snapshot_name, &format!("{:#?}", val));
37}
38
39/// Asserts that the given string matches the snapshot saved in the snapshot
40/// file. The given string will be used as plain output and directly compared
41/// with the stored snapshot.
42///
43/// If the value differs from the snapshot, the assertion fails and prints
44/// a colored diff output. One trailing newline in the snapshot output is
45/// ignored by default.
46pub fn assert_snapshot_plain<S: AsRef<str>>(snapshot_name: S, output: &str) {
47    let name = snapshot_name.as_ref();
48
49    let snapshot_path = Path::new("tests").join("snapshots").join(name);
50    let snapshot = load_file(snapshot_path).unwrap_or_else(|_| "".into());
51
52    let expected = if snapshot.ends_with('\n') && !output.ends_with('\n') {
53        &snapshot[0..snapshot.len() - 1]
54    } else {
55        &snapshot
56    };
57
58    assert!(
59        expected == output,
60        "Value does not match stored snapshot {}:\n{}\n{}",
61        name,
62        Changeset::new("- snapshot", "+ actual output", "\n"),
63        Changeset::new(expected, &output, "\n")
64    );
65}