How do you test for a specific Rust error?

Following solution doesn't require PartialEq trait to be implemented. For instance std::io::Error does not implement this, and more general solution is required.

In these cases, you can borrow a macro assert_matches from matches crate. It works by giving more succinct way to pattern match, the macro is so short you can just type it too:

macro_rules! assert_err {
    ($expression:expr, $($pattern:tt)+) => {
        match $expression {
            $($pattern)+ => (),
            ref e => panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), e),
        }
    }
}

// Example usages:
assert_err!(your_func(), Err(Error::UrlParsingFailed(_)));
assert_err!(your_func(), Err(Error::CanonicalizationFailed(_)));
assert_err!(your_func(), Err(Error::FileOpenFailed(er)) if er.kind() == ErrorKind::NotFound);

Full playground buildable example, with example Error enum:

#[derive(Debug)]
pub enum Error {
    UrlCreationFailed,
    CanonicalizationFailed(std::io::Error),
    FileOpenFailed(std::io::Error),
    UrlParsingFailed(url::ParseError),
}

pub fn your_func() -> Result<(), Error> {
    Ok(())
}

#[cfg(test)]
mod test {
    use std::io::ErrorKind;
    use super::{your_func, Error};

    macro_rules! assert_err {
        ($expression:expr, $($pattern:tt)+) => {
            match $expression {
                $($pattern)+ => (),
                ref e => panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), e),
            }
        }
    }

    #[test]
    fn test_failures() {
        // Few examples are here:
        assert_err!(your_func(), Err(Error::UrlParsingFailed(_)));
        assert_err!(your_func(), Err(Error::CanonicalizationFailed(_)));
        assert_err!(your_func(), Err(Error::FileOpenFailed(er)) if er.kind() == ErrorKind::NotFound);
    }

}

You can directly compare the returned Err variant if it impl Debug + PartialEq:

#[derive(Debug, PartialEq)]
enum MyError {
    TooBig,
    TooSmall,
}

pub fn encode(&self, decoded: &'a Bytes) -> Result<&'a Bytes, MyError> {
    if decoded.len() > self.length() as usize {
        Err(MyError::TooBig)
    } else {
        Ok(&decoded)
    }
}
assert_eq!(fixed.encode(&[1]), Err(MyError::TooBig));