You have to write a file parser. The first test is:
use std::path::{PathBuf, Path};
#[derive(Default, Debug, PartialEq)]
struct Matrix { rows: usize, cols: usize, data: Vec<i32> }
impl<P: AsRef<Path>> From<P> for Matrix { fn from(_: P) -> Self { Default::default() } }
fn create_empty_file() -> PathBuf { "".into() }
#[test]
fn should_parse_empty_file() {
let empty = create_empty_file();
let matrix: Matrix = Matrix::from(empty);
assert_eq!(matrix, Default::default())
}
Ok, create_empty_file()
should do a lot of job and can be reused in
other tests and fixtures: it's a good candidate to be a fixture.
Let's rewrite previous example by use rstest
: we'll use empty
for
fixture instead of create_empty_file()
because when we use as fixture
will be an object instead an action.
use std::path::{PathBuf, Path};
use rstest::*;
#[derive(Default, Debug, PartialEq)]
struct Matrix { rows: usize, cols: usize, data: Vec<i32> }
impl<P: AsRef<Path>> From<P> for Matrix { fn from(_: P) -> Self { Default::default() } }
#[fixture]
fn empty() -> PathBuf {
let path = "empty_file".into();
std::fs::File::create(&path).expect("Cannot open");
path
}
#[rstest]
fn should_parse_empty_file(empty: PathBuf) {
let matrix: Matrix = Matrix::from(empty);
assert_eq!(matrix, Default::default())
}
Now our Matrix
's From
trait is a little bit more generic and can
take every struct that implement AsRef<Path>
like PathBuf
do. So we
can generalize our test too:
use std::path::{PathBuf, Path};
use rstest::*;
#[derive(Default, Debug, PartialEq)]
struct Matrix { rows: usize, cols: usize, data: Vec<i32> }
impl<P: AsRef<Path>> From<P> for Matrix { fn from(_: P) -> Self { Default::default() } }
#[rstest]
fn should_parse_empty_file<P>(empty: P)
where P: AsRef<Path>
{
let matrix: Matrix = Matrix::from(empty);
assert_eq!(matrix, Default::default())
}
Our test is neat and clear but we have a big issue to fix: we cannot
leave "empty_file"
on our disk, we must remove it we are done!
That is a job for Rust ownership!!
We should just wrap PathBuf
in out TempFile
struct and implement
both Drop
and AsRef<Path>
traits. We'll use Drop
to delete it.
use std::path::{PathBuf, Path};
use rstest::*;
struct TempFile(PathBuf);
impl Drop for TempFile {fn drop(&mut self) {
std::fs::remove_file(&self.0).unwrap();
}
}
impl AsRef<Path> for TempFile {
fn as_ref(&self) -> &Path {
&self.0
}
}
#[fixture]
fn empty() -> TempFile {
let path = "empty_file".into();
std::fs::File::create(&path).expect("Cannot open");
TempFile(path)
}