#100DaysOfCode in Python Transcripts
Chapter: Days 10-12: Testing your code with pytest
Lecture: Mocking user input and exceptions

Login or purchase this course to watch this video and the rest of the course contents.
0:00 The second thing I want to test is the guess method.
0:02 It takes a user input and input is not static,
0:06 you can change and it can be random.
0:08 Even worse, when you run this program
0:10 it's waiting at the prompt to get input
0:11 so your test would hang, quickly demo this.
0:17 Let's make a game object, and run it.
0:26 Actually it's not hanging, it's throwing an error,
0:29 pretty soon, reading from standard input
0:31 output is captured, so that's cool.
0:33 And look at the output, it's pretty verbose
0:35 which is a nice feature of pytest.
0:38 But anyway, we definitely don't want to use input
0:40 literally in tests, so I'm going to use patch again.
0:44 And I'm going to patch the built-ins input,
0:50 and this is another way of marking.
0:52 Here I can give it side effects.
0:56 And a list of expected returns in a row.
1:00 Because I'm having all these exceptions here,
1:02 I'm going to give it a bunch of inputs
1:04 to go through all these scenarios and see
1:06 if each scenario throws the value error
1:09 or accepts the guess as a correct one.
1:11 And will also show you how you can check for
1:14 exceptions in pytest which are important
1:17 because raising exceptions is a common Python pattern.
1:21 So what we're doing here is setting up
1:23 a sequence of return values as if input was
1:26 called that many times.
1:28 So it will return a 11, then 12 as a string,
1:31 then bob, then 12,
1:36 then five minus one, 21
1:40 seven and None.
1:43 And those are the values that we're going to work with,
1:45 and you have to give it an argument,
1:47 it can be called anything.
1:49 And now we have some return data from input to work with.
1:52 So I'm making a game, and again,
1:54 the constructor sets defaults
1:56 for all the internal variables,
1:57 so that should be fine,
1:59 and then I can start to make assertions.
2:02 And the first two side effects or returns are good.
2:10 and again I will show you guess,
2:11 so guess goes through getting an input,
2:14 looking for all the bad inputs and raise a value error
2:17 if so, and if it's good it ends up adding
2:19 it to it's internal set which is the underscore guesses,
2:23 and returning the guess.
2:24 So 11 is good,
2:30 12 is a string should be fine
2:33 because that can be converted into a int.
2:36 The second one, bob, is not a number.
2:38 And the way in pytest to check if an exception is raised
2:42 is to use pytest, and you need to import that,
2:48 and do a with pytest.raises,
2:51 the name of the exception and then the statement
2:57 that would trigger that exception.
2:59 So the next return value from input in the row
3:03 is bob's string, if I call guess with that
3:06 it should raise a value error
3:07 and we're telling pytest to check if
3:10 it actually raises that exception.
3:12 And the same is true for the next one with is 12.
3:16 If I guess again, the guess is already in the guesses set
3:20 and the function manually raises a value error.
3:23 I can just copy this and it will be the same.
3:26 So every new call of guess triggers this input statement
3:31 or call, which triggers a new value in the return list.
3:35 So 12 is done, five should be fine.
3:42 Right let's run what we have so far
3:44 because it's a lot of code and see if it works.
3:50 All right that looks good.
3:51 So now let's do the complete list again.
3:55 And after five comes minus one and 21
3:59 which should be two exceptions because
4:00 they are out of range.
4:08 Another good one, and finally None should not be a good one,
4:15 that falls into this one, if not guess
4:17 raise a value error, please enter a number.
4:19 So we wrap up with...
4:24 So that's save, Control + Z, pytest
4:29 you're still happy.
4:30 I mean if it would say...
4:34 Game guess returns None when given None it will fail.
4:41 So we have please enter a number
4:43 so it actually raised a value error,
4:45 and it was not catching that.
4:47 Here I do, and it works.
4:52 So that's how I use mocking to circumvent
4:56 this input function waiting for input.
4:59 I'm going through all these scenarios
5:01 by giving various side effects.
5:03 Next up, validate guess.