Testing Enums within matches


#1

Hi

Perhaps I’m thinking about testing wrong here? But I’m trying to write a couple of tests on an Enum for my CLI. One is a valid action and one is invalid. I have a impl frm_Str() method which uses a match to confirm that the passed in action is valid, if valid it returns the type of enum. If it fails it returns Err(format!("Unknown action: {}", e)).

These are my tests:

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn valid_action() {

        let action : ActionKind = "gray".parse().unwrap();
        assert_eq!( action, ActionKind::Gray );
    }

    #[test]
    fn invalid_action() {

        let invalid : ActionKind = "invalid".parse().unwrap();
        assert_eq!( invalid, Err );
    }
}

The enum and impl is:

#[derive(Debug, PartialEq)]
pub enum ActionKind {
    Gray,
    Thumb,
    Rotate,
    Crop
}

impl FromStr for ActionKind {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "gray" => Ok(ActionKind::Gray),
            "thumb" => Ok(ActionKind::Thumb),
            "rotate" => Ok(ActionKind::Rotate),
            "crop" => Ok(ActionKind::Crop),
            e @ _ => Err(format!("Unknown action: {}", e)),
        }
    }
} 

So, am I testing things that don’t need to be tested here? :confused: and if I’m not, how should I write a test to confirm that the commands are handled properly? (i.e if it’s valid it returns the Enum, if invalid it Err)


#2

Is your concern here that the above test doesn’t compile? The problem is the

assert_eq!( invalid, Err );

line, which is a syntax error. If you want to compare with a value, then you need to use something like this:

#[test]
fn invalid_action() {
    let invalid: Result<ActionKind, _> = "invalid".parse();
    let msg = String::from("Unknown action: invalid");
    assert_eq!(invalid, Err(msg));
}

Note that I’ve changed two things:

  1. I’ve removed the call to unwrap since the parsing fails and unwrap would thus start a panic.
  2. I’ve replaced Err with a proper error value: Err by itself it not a value, you must use it with a string to get a value.

If you don’t want to check the precise error message, then you could use

#[test]
fn invalid_action() {
    let invalid: Result<ActionKind, _> = "invalid".parse();
    assert!(invalid.is_err());
}

instead.

With those changes, I think your tests are fine: the type checking will ensure that your parse method returns a proper Result<ActionKind, String>, but the tests are still needed to ensure that the function implements the correct logic, e.g., that is parses "crop" and not "invalid".


#3

Thanks, that did work for me and I have been unsure when dealing with more complex types the best way to test these kind of scenarios. :slight_smile: