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