WEBVTT 1 00:00:00.290 --> 00:00:02.179 Hi guys and welcome back. 2 00:00:02.179 --> 00:00:04.081 In this video, we're going to be learning 3 00:00:04.081 --> 00:00:06.743 about patching and mocking. 4 00:00:07.708 --> 00:00:10.610 Let's start by creating a new file 5 00:00:10.610 --> 00:00:13.700 that we're gonna call page.py, 6 00:00:13.700 --> 00:00:16.740 and here we're gonna import the requests module. 7 00:00:16.740 --> 00:00:17.970 So, if you don't have it installed, 8 00:00:17.970 --> 00:00:19.520 just go over to your settings, 9 00:00:19.520 --> 00:00:21.112 open your project interpreter settings, 10 00:00:21.112 --> 00:00:24.473 and instal the requests module. 11 00:00:26.160 --> 00:00:29.729 This module here just allows us to get a web page 12 00:00:29.729 --> 00:00:32.940 and look at its contents basically. 13 00:00:32.940 --> 00:00:35.610 So, it allows us to make web requests. 14 00:00:35.610 --> 00:00:38.090 Now that that's installed, we can go to okay 15 00:00:38.090 --> 00:00:40.302 and this should disappear at the redline, 16 00:00:40.302 --> 00:00:42.120 and then we're gonna create a class. 17 00:00:42.120 --> 00:00:43.630 That I'm gonna call PageRequester, 18 00:00:43.630 --> 00:00:45.798 and it's gonna be a very useless class, 19 00:00:45.798 --> 00:00:47.920 but nonetheless it's gonna allow us 20 00:00:47.920 --> 00:00:50.490 to learn about testing. 21 00:00:50.490 --> 00:00:52.990 So, we're gonna get the PageRequester class 22 00:00:52.990 --> 00:00:54.555 and it has an init method. 23 00:00:54.555 --> 00:00:57.980 This one receives a string and URL. 24 00:00:57.980 --> 00:01:00.113 We can say that this is a string there, 25 00:01:00.113 --> 00:01:02.760 and then it has a get method 26 00:01:02.760 --> 00:01:05.653 that all it does is it calls the requests module. 27 00:01:09.690 --> 00:01:13.460 And it gives you back the content of the response. 28 00:01:13.460 --> 00:01:17.163 Now you may think that this is a useless example, 29 00:01:17.163 --> 00:01:22.163 but very often what you'll see is that your classes 30 00:01:22.810 --> 00:01:26.660 get very long, and as your classes get longer and longer, 31 00:01:26.660 --> 00:01:29.660 understanding them becomes naturally more difficult. 32 00:01:29.660 --> 00:01:30.830 There is more code to read, 33 00:01:30.830 --> 00:01:33.540 you have to be jumping from one place to another and so on. 34 00:01:33.540 --> 00:01:38.130 So, it's often a good idea to split out the code 35 00:01:38.130 --> 00:01:41.330 in your classes, take it out, put it inside another file, 36 00:01:41.330 --> 00:01:43.580 create a function for it or potentially another class 37 00:01:43.580 --> 00:01:47.300 if it's necessary, and test that separately 38 00:01:47.300 --> 00:01:49.230 from this class. 39 00:01:49.230 --> 00:01:53.000 This class now where we've taken all of the code 40 00:01:53.000 --> 00:01:55.610 that actually goes and gets the URL and so forth, 41 00:01:55.610 --> 00:01:58.443 we've taken all that into a new file, the requests module. 42 00:01:58.443 --> 00:02:00.640 Now this class is very simple. 43 00:02:00.640 --> 00:02:02.500 All we have to do is make sure that 44 00:02:02.500 --> 00:02:04.622 the URL is stored in the class, 45 00:02:04.622 --> 00:02:09.622 and that the get method calls the requests module. 46 00:02:10.050 --> 00:02:13.675 So, we can go ahead and write our tests for it. 47 00:02:13.675 --> 00:02:15.610 Let's create a new file that I'm gonna 48 00:02:15.610 --> 00:02:18.531 call testpage.py, 49 00:02:18.531 --> 00:02:22.453 and once again we will begin by doing from unittest, 50 00:02:23.610 --> 00:02:24.443 import TestCase. 51 00:02:25.340 --> 00:02:28.812 We will do from unittest.mock import patch, 52 00:02:28.812 --> 00:02:32.210 and from page import PageRequester. 53 00:02:32.210 --> 00:02:35.300 Then we'll create our test PageRequester, 54 00:02:35.300 --> 00:02:37.400 which is a test case, 55 00:02:37.400 --> 00:02:41.107 and we are gonna set up the method here 56 00:02:41.107 --> 00:02:43.833 to do self.page is PageRequester, 57 00:02:43.833 --> 00:02:48.393 and we will pass in google.com, just a simple page there. 58 00:02:49.310 --> 00:02:52.830 Now what we want to do is 59 00:02:52.830 --> 00:02:57.830 we want to make sure that when we call self.page.get, 60 00:02:58.860 --> 00:03:00.750 it calls the requests module. 61 00:03:00.750 --> 00:03:04.580 We do not want to have a test 62 00:03:04.580 --> 00:03:07.770 that actually gets google.com. 63 00:03:07.770 --> 00:03:11.364 Here's why, so we'll say test_make_request, 64 00:03:11.364 --> 00:03:15.333 and we're gonna do with patch of requests.get 65 00:03:16.487 --> 00:03:19.450 as mocked get, and what this does is it goes 66 00:03:19.450 --> 00:03:23.220 into the requests module, looks at 67 00:03:23.220 --> 00:03:26.628 or rather it goes into the requests import, 68 00:03:26.628 --> 00:03:28.861 which is what we've imported here, 69 00:03:28.861 --> 00:03:33.497 and if we use requests.get anywhere in our application, 70 00:03:33.497 --> 00:03:37.270 is going to be replaced by whatever 71 00:03:37.270 --> 00:03:40.080 this patch function returns. 72 00:03:40.080 --> 00:03:43.150 So, it's gonna get replaced by a mock 73 00:03:43.150 --> 00:03:46.160 and I'll show you what a mock is in just a moment. 74 00:03:46.160 --> 00:03:49.681 So, what we want to do once we've patched requests.get, 75 00:03:49.681 --> 00:03:53.440 we just want to say self.page.get. 76 00:03:53.440 --> 00:03:56.207 And then mocked_get.assert_called. 77 00:03:58.183 --> 00:04:02.043 All right so now let's get into why we're doing this. 78 00:04:03.280 --> 00:04:06.920 When we write the requests module, 79 00:04:06.920 --> 00:04:09.130 so whoever wrote the requests module, 80 00:04:09.130 --> 00:04:11.890 he wrote tests for the requests module. 81 00:04:11.890 --> 00:04:15.950 You don't have to use the requests code 82 00:04:15.950 --> 00:04:18.056 and make sure that it works. 83 00:04:18.056 --> 00:04:22.885 If we write this test without patching requests.get, 84 00:04:22.885 --> 00:04:25.738 really we're testing two things. 85 00:04:25.738 --> 00:04:27.930 The first thing we're doing is we are testing 86 00:04:27.930 --> 00:04:30.480 that our function calls the requests module 87 00:04:30.480 --> 00:04:32.600 because that's really what it does. 88 00:04:32.600 --> 00:04:34.880 But the second thing is we're testing that 89 00:04:34.880 --> 00:04:36.421 the requests module also works, 90 00:04:36.421 --> 00:04:39.951 because we're actually interacting with the requests module. 91 00:04:39.951 --> 00:04:43.279 If you patch it, you are never interacting 92 00:04:43.279 --> 00:04:45.620 with the requests module. 93 00:04:45.620 --> 00:04:47.170 All you're doing is you're interacting 94 00:04:47.170 --> 00:04:49.451 with this mock that we're creating. 95 00:04:49.451 --> 00:04:51.641 That means that there is a separation 96 00:04:51.641 --> 00:04:53.550 between the requests module code 97 00:04:53.550 --> 00:04:58.550 that we are not testing, and our code that we are testing. 98 00:04:58.810 --> 00:05:03.378 And on the line between those two is this mock. 99 00:05:03.378 --> 00:05:06.421 By checking that we are calling the requests module, 100 00:05:06.421 --> 00:05:08.574 that is everything we need to check, 101 00:05:08.574 --> 00:05:11.390 because the requests module is tested separately 102 00:05:11.390 --> 00:05:13.340 and we don't have to test it ourselves. 103 00:05:14.730 --> 00:05:17.760 Now there is a thing that our function does, 104 00:05:17.760 --> 00:05:21.112 sorry that our method does, that isn't tested by that one, 105 00:05:21.112 --> 00:05:24.610 and it is that it gets the content of the response. 106 00:05:24.610 --> 00:05:28.620 So, we do have to write a test for this specific thing. 107 00:05:28.620 --> 00:05:31.850 Make sure that whatever we get back, 108 00:05:31.850 --> 00:05:35.080 we are accessing the content property of that. 109 00:05:35.080 --> 00:05:39.000 This mock here that we've used 110 00:05:39.000 --> 00:05:42.761 does not have a content property. 111 00:05:42.761 --> 00:05:46.680 And I will show you exactly how I know that. 112 00:05:46.680 --> 00:05:48.947 Going to type response is that 113 00:05:48.947 --> 00:05:52.230 and we'll see print response. 114 00:05:52.230 --> 00:05:54.190 Now we're gonna run this test here, 115 00:05:54.190 --> 00:05:57.363 so we'll right-click it and press run these tests, 116 00:05:58.700 --> 00:06:00.530 and you see that what you get back 117 00:06:00.530 --> 00:06:04.860 when you do this patch is something called a magic mock. 118 00:06:04.860 --> 00:06:08.167 This is part of the Python unit test module. 119 00:06:08.167 --> 00:06:13.167 Whenever you access anything inside the magic mock, 120 00:06:14.700 --> 00:06:16.950 it will allow you to access it. 121 00:06:16.950 --> 00:06:21.950 So, for example you can say print response.rolf. 122 00:06:22.170 --> 00:06:25.300 Let's run this again, and notice that 123 00:06:25.300 --> 00:06:27.310 it is totally okay with it. 124 00:06:27.310 --> 00:06:30.883 And what you get back is another magic mock. 125 00:06:32.420 --> 00:06:36.640 When you do magic mock dot anything, 126 00:06:36.640 --> 00:06:39.480 the magic mock automatically creates the property, 127 00:06:39.480 --> 00:06:43.617 and gives it the value of another magic mock. 128 00:06:43.617 --> 00:06:46.400 So, really with this test here, 129 00:06:46.400 --> 00:06:50.880 we're not testing that we get a valid content thing 130 00:06:50.880 --> 00:06:53.560 from our response. 131 00:06:53.560 --> 00:06:58.560 We are not checking that this stuff here is working. 132 00:06:58.610 --> 00:07:00.154 We're just checking that we are getting 133 00:07:00.154 --> 00:07:02.193 something from the requests module. 134 00:07:03.540 --> 00:07:06.170 If you want to patch this 135 00:07:06.170 --> 00:07:09.290 and make it return something that has a content property, 136 00:07:09.290 --> 00:07:11.400 so that you can then make sure that you are getting 137 00:07:11.400 --> 00:07:12.499 the content property back, 138 00:07:12.499 --> 00:07:16.880 you have to do that separately without using the magic mock. 139 00:07:16.880 --> 00:07:20.539 So, let's write a test for content returned 140 00:07:20.539 --> 00:07:24.250 and here we need to define an inner class 141 00:07:24.250 --> 00:07:26.690 that is going to be a fake response. 142 00:07:26.690 --> 00:07:29.170 So, we're gonna say requests module, 143 00:07:29.170 --> 00:07:32.420 when I call the get method instead of returning 144 00:07:32.420 --> 00:07:35.290 the real response from google.com, 145 00:07:35.290 --> 00:07:38.160 give me this fake response. 146 00:07:38.160 --> 00:07:40.287 So, we will define the init method here 147 00:07:40.287 --> 00:07:44.363 and we will say self.content is hello. 148 00:07:45.360 --> 00:07:48.780 And this is a fake response that we've used in here, 149 00:07:48.780 --> 00:07:53.780 and now we'll say with patch requests.get, 150 00:07:53.830 --> 00:07:57.827 and the return value is gonna be a FakeResponse. 151 00:07:59.560 --> 00:08:01.260 And what this does is, 152 00:08:01.260 --> 00:08:06.260 when you do requests.get like this, 153 00:08:06.510 --> 00:08:09.180 you're gonna get back a FakeResponse object 154 00:08:09.180 --> 00:08:10.580 that we've created just now. 155 00:08:11.417 --> 00:08:16.417 That means that when you do result equals self.page.get, 156 00:08:16.771 --> 00:08:19.132 what's happening is self.page.get 157 00:08:19.132 --> 00:08:22.200 is calling requests.get, 158 00:08:22.200 --> 00:08:26.540 and this stuff here will be your FakeResponse object 159 00:08:26.540 --> 00:08:28.700 and then you're accessing the content property 160 00:08:28.700 --> 00:08:29.843 of your FakeResponse. 161 00:08:30.930 --> 00:08:34.830 So, you can do self.assertEqual result 162 00:08:39.870 --> 00:08:41.833 should be hello. 163 00:08:42.720 --> 00:08:46.460 And we can do fake content is hello 164 00:08:46.460 --> 00:08:47.553 and put it in here. 165 00:08:49.160 --> 00:08:53.120 All right now this will pass as well if we run it, 166 00:08:53.120 --> 00:08:57.067 and we have successfully faked what the method 167 00:08:57.067 --> 00:08:59.400 here is going to return. 168 00:08:59.400 --> 00:09:01.350 This is a very common pattern, 169 00:09:01.350 --> 00:09:04.690 where you fake the return value of something. 170 00:09:04.690 --> 00:09:09.180 We've learned how to fake the return value of a function 171 00:09:09.180 --> 00:09:13.040 and also how to make sure that it was called. 172 00:09:13.040 --> 00:09:15.364 There is a lot more on patching and mocking 173 00:09:15.364 --> 00:09:17.740 in the official documentation that I have linked 174 00:09:17.740 --> 00:09:19.399 in the resources section of this lecture. 175 00:09:19.399 --> 00:09:23.940 So, please do give it a read if you want to do more on this. 176 00:09:23.940 --> 00:09:26.714 There is a lot to know and it can get a little bit confusing 177 00:09:26.714 --> 00:09:29.989 when you start to play with different side-effects 178 00:09:29.989 --> 00:09:32.430 and other things that these mocks can do, 179 00:09:32.430 --> 00:09:34.150 and when you start using mocks instead 180 00:09:34.150 --> 00:09:36.027 of magic mocks and so on. 181 00:09:36.027 --> 00:09:39.245 So, if you want to do more testing I would recommend looking 182 00:09:39.245 --> 00:09:42.240 at that and potentially also going deeper 183 00:09:42.240 --> 00:09:45.010 into learning about unit testing in Python. 184 00:09:45.010 --> 00:09:46.980 There is quite a lot to do. 185 00:09:46.980 --> 00:09:48.002 Thanks for joining me in this video. 186 00:09:48.002 --> 00:09:49.763 I'll see you on the next one.