1 00:00:00,480 --> 00:00:03,480 foreign 2 00:00:10,880 --> 00:00:15,719 is an independent independent software 3 00:00:13,620 --> 00:00:18,300 consultant building python-based 4 00:00:15,719 --> 00:00:20,039 back-end devops and Data Systems she 5 00:00:18,300 --> 00:00:22,500 also teaches python via online 6 00:00:20,039 --> 00:00:24,539 month-long boot camps she's an open 7 00:00:22,500 --> 00:00:27,359 source Enthusiast and has contributed to 8 00:00:24,539 --> 00:00:30,980 pandas and Apache airflow please put 9 00:00:27,359 --> 00:00:30,980 your hands together for povani 10 00:00:32,120 --> 00:00:35,940 thank you 11 00:00:34,079 --> 00:00:40,340 thank you thanks for such a nice 12 00:00:35,940 --> 00:00:43,020 introduction first of all hello everyone 13 00:00:40,340 --> 00:00:45,719 hello everyone 14 00:00:43,020 --> 00:00:49,200 okay nice good now we are all awake I 15 00:00:45,719 --> 00:00:51,000 know we are hungry but 16 00:00:49,200 --> 00:00:53,160 just to put things into perspective I'm 17 00:00:51,000 --> 00:00:55,440 bhavani Ravi I've been fallen in love by 18 00:00:53,160 --> 00:00:57,660 with python seven years back and it's 19 00:00:55,440 --> 00:00:59,640 still going on I'm an independent 20 00:00:57,660 --> 00:01:01,920 software consultant I get thrown into 21 00:00:59,640 --> 00:01:04,680 technical problems and I Rise Up from 22 00:01:01,920 --> 00:01:07,320 there that's what I do for living 23 00:01:04,680 --> 00:01:09,180 and today we are here to build our own 24 00:01:07,320 --> 00:01:12,299 unit testing Library 25 00:01:09,180 --> 00:01:14,280 and when I put out this talk and tell to 26 00:01:12,299 --> 00:01:18,540 all my friends that the talkers accepted 27 00:01:14,280 --> 00:01:19,560 the very first question was why 28 00:01:18,540 --> 00:01:22,140 Center 29 00:01:19,560 --> 00:01:23,460 why even your own testing Library 30 00:01:22,140 --> 00:01:25,740 and 31 00:01:23,460 --> 00:01:30,500 I don't have a perfect answer for that I 32 00:01:25,740 --> 00:01:30,500 have an answer for that one is it's fun 33 00:01:30,840 --> 00:01:34,799 remember when you all first started 34 00:01:33,240 --> 00:01:36,780 programming remember that moment when 35 00:01:34,799 --> 00:01:38,520 you've fallen in love with that first 36 00:01:36,780 --> 00:01:41,820 program that you wrote it gave you that 37 00:01:38,520 --> 00:01:44,820 spark and kept you hooked all along mine 38 00:01:41,820 --> 00:01:46,799 was printing the first 10 numbers and I 39 00:01:44,820 --> 00:01:49,619 changed the program to ten thousand and 40 00:01:46,799 --> 00:01:52,500 then to a lakh until the system crashed 41 00:01:49,619 --> 00:01:55,619 but there came a point where programs 42 00:01:52,500 --> 00:01:58,320 like that got really boring and now I 43 00:01:55,619 --> 00:01:59,340 can do this for fun and I hope you can 44 00:01:58,320 --> 00:02:01,380 too 45 00:01:59,340 --> 00:02:03,180 and there's this Rich environments quote 46 00:02:01,380 --> 00:02:05,820 what you don't create you don't 47 00:02:03,180 --> 00:02:06,960 understand and I pretty much love this 48 00:02:05,820 --> 00:02:09,420 quote 49 00:02:06,960 --> 00:02:11,819 and as a result of that I created own 50 00:02:09,420 --> 00:02:15,180 flask my own version of flask 51 00:02:11,819 --> 00:02:16,220 application and that was almost a year 52 00:02:15,180 --> 00:02:19,260 back 53 00:02:16,220 --> 00:02:22,739 it's been too long since I've had fun so 54 00:02:19,260 --> 00:02:25,980 now I am after Pi test 55 00:02:22,739 --> 00:02:27,440 the only problem was I've been using pi 56 00:02:25,980 --> 00:02:30,480 test pretty much 57 00:02:27,440 --> 00:02:31,920 extensively the last uh eight months and 58 00:02:30,480 --> 00:02:34,140 the hundred percent test coverage from 59 00:02:31,920 --> 00:02:36,239 the previous talk all of that was so 60 00:02:34,140 --> 00:02:38,280 relatable and I love all of these 61 00:02:36,239 --> 00:02:40,620 features that by test provides the test 62 00:02:38,280 --> 00:02:42,959 Runner parameterized test cases expected 63 00:02:40,620 --> 00:02:45,300 exceptions fixtures mocking you name 64 00:02:42,959 --> 00:02:46,640 them I use them 65 00:02:45,300 --> 00:02:49,080 and 66 00:02:46,640 --> 00:02:50,519 show all fans how many of you have used 67 00:02:49,080 --> 00:02:52,920 by test 68 00:02:50,519 --> 00:02:55,019 okay everybody almost everybody if you 69 00:02:52,920 --> 00:02:57,360 have not used it your logic will look 70 00:02:55,019 --> 00:02:59,640 something like this and your Associated 71 00:02:57,360 --> 00:03:02,099 test case which starts with test 72 00:02:59,640 --> 00:03:04,920 underscore followed by you call your 73 00:03:02,099 --> 00:03:07,080 logic and test whether that uh that the 74 00:03:04,920 --> 00:03:09,000 logic behaves the exact same way and 75 00:03:07,080 --> 00:03:10,800 that's a very simple test case this is 76 00:03:09,000 --> 00:03:14,459 your parameterized test case where you 77 00:03:10,800 --> 00:03:16,319 pass a bunch of data and hope that all 78 00:03:14,459 --> 00:03:17,580 the data that you're passing behave the 79 00:03:16,319 --> 00:03:19,860 same way as well 80 00:03:17,580 --> 00:03:21,360 and you can also expect your 81 00:03:19,860 --> 00:03:24,780 functionality to raise a particular 82 00:03:21,360 --> 00:03:26,879 exception and a pie test will capture 83 00:03:24,780 --> 00:03:29,519 that 84 00:03:26,879 --> 00:03:33,060 so I thought okay let's start building 85 00:03:29,519 --> 00:03:35,640 it and the first place to start is 86 00:03:33,060 --> 00:03:38,700 reverse engineer it and I went and 87 00:03:35,640 --> 00:03:41,280 looked into Pi test source code and this 88 00:03:38,700 --> 00:03:42,360 was the reaction 89 00:03:41,280 --> 00:03:43,920 I 90 00:03:42,360 --> 00:03:47,580 well 91 00:03:43,920 --> 00:03:51,540 it has about 130k lines of code 92 00:03:47,580 --> 00:03:53,819 earliest comment was on 2007 and so far 93 00:03:51,540 --> 00:03:55,920 there are 5000 PRS being merged for the 94 00:03:53,819 --> 00:03:58,319 project which is a lot more than flask 95 00:03:55,920 --> 00:04:00,180 flask was very rather simple what I'm 96 00:03:58,319 --> 00:04:02,540 trying to say with all this is It's hard 97 00:04:00,180 --> 00:04:06,120 to reverse and generate 98 00:04:02,540 --> 00:04:08,400 the next option was chargpt or GitHub 99 00:04:06,120 --> 00:04:11,640 co-pilot because we are all relying on 100 00:04:08,400 --> 00:04:13,080 that so much but things like this llms 101 00:04:11,640 --> 00:04:16,199 really work if there are previous 102 00:04:13,080 --> 00:04:17,820 examples available unfortunately even if 103 00:04:16,199 --> 00:04:19,079 you Google right now there are not a lot 104 00:04:17,820 --> 00:04:21,060 of examples on how do you build a 105 00:04:19,079 --> 00:04:24,479 listing library from scratch 106 00:04:21,060 --> 00:04:25,440 so again thrown out of all the options 107 00:04:24,479 --> 00:04:26,460 here 108 00:04:25,440 --> 00:04:28,759 so 109 00:04:26,460 --> 00:04:31,259 building my own testing Library 110 00:04:28,759 --> 00:04:33,120 reflecting whatever Pi test provides as 111 00:04:31,259 --> 00:04:36,960 an interface I'm gonna have all these 112 00:04:33,120 --> 00:04:39,240 features and let's see how that goes 113 00:04:36,960 --> 00:04:41,160 first starting with the test Runner I'm 114 00:04:39,240 --> 00:04:43,979 going to be live coding this and if I 115 00:04:41,160 --> 00:04:47,160 make any mistakes please be kind to me 116 00:04:43,979 --> 00:04:50,160 and the test Runner this is all our 117 00:04:47,160 --> 00:04:52,500 version this is not by this version so 118 00:04:50,160 --> 00:04:56,040 it has an interface that looks like this 119 00:04:52,500 --> 00:04:58,560 you do PI test followed by the directory 120 00:04:56,040 --> 00:05:00,120 that you want to test and if we think 121 00:04:58,560 --> 00:05:01,440 about it how would you write a test 122 00:05:00,120 --> 00:05:04,380 Runner 123 00:05:01,440 --> 00:05:06,660 first problem is finding out all the 124 00:05:04,380 --> 00:05:08,520 test functions that are there in all the 125 00:05:06,660 --> 00:05:12,180 test files under that for the particular 126 00:05:08,520 --> 00:05:15,120 directory and then you have to run them 127 00:05:12,180 --> 00:05:17,280 maintain a streak of success and failure 128 00:05:15,120 --> 00:05:20,220 and if there is an error you have to 129 00:05:17,280 --> 00:05:21,540 report them can we live code it 130 00:05:20,220 --> 00:05:23,880 okay 131 00:05:21,540 --> 00:05:26,220 I did say we are going to do things from 132 00:05:23,880 --> 00:05:28,380 scratch but I kind of lied 133 00:05:26,220 --> 00:05:31,440 so we're gonna 134 00:05:28,380 --> 00:05:33,720 start with this so here's my test 135 00:05:31,440 --> 00:05:36,660 function okay 136 00:05:33,720 --> 00:05:39,840 here's my own test module which is where 137 00:05:36,660 --> 00:05:41,220 we're gonna fill out things uh the test 138 00:05:39,840 --> 00:05:44,160 Runner is the only thing that's going to 139 00:05:41,220 --> 00:05:46,560 run everything else is a race an 140 00:05:44,160 --> 00:05:48,120 accepted reception parameterize picture 141 00:05:46,560 --> 00:05:51,180 which we will come back and fill in 142 00:05:48,120 --> 00:05:52,919 later here is my test Runner and some of 143 00:05:51,180 --> 00:05:56,340 the complex complexities I have written 144 00:05:52,919 --> 00:05:59,820 away using certain functions so 145 00:05:56,340 --> 00:06:02,699 I have got all the test files I've got 146 00:05:59,820 --> 00:06:04,800 all the test objects here and the only 147 00:06:02,699 --> 00:06:07,919 thing that we have to do right now is 148 00:06:04,800 --> 00:06:11,060 run the test cases so what do we mean 149 00:06:07,919 --> 00:06:11,060 when we run the test case 150 00:06:15,780 --> 00:06:20,580 we have a test uh sorry we have a test 151 00:06:18,419 --> 00:06:22,800 file with a bunch of functions we have 152 00:06:20,580 --> 00:06:24,600 loaded all that function into our module 153 00:06:22,800 --> 00:06:26,580 now we have the test function name and 154 00:06:24,600 --> 00:06:29,580 the test function object and running 155 00:06:26,580 --> 00:06:33,479 would running them would actually mean 156 00:06:29,580 --> 00:06:36,259 calling that test function object and if 157 00:06:33,479 --> 00:06:36,259 I run this 158 00:06:36,780 --> 00:06:41,520 so I'm going to use the own Pi test 159 00:06:39,000 --> 00:06:43,440 module and pass all the test cases all 160 00:06:41,520 --> 00:06:44,940 this functionality of reading the 161 00:06:43,440 --> 00:06:48,539 directory reading all the functions has 162 00:06:44,940 --> 00:06:50,940 been already written so if I run this it 163 00:06:48,539 --> 00:06:53,520 says success no address has been found 164 00:06:50,940 --> 00:06:55,680 whether it's really working or not I 165 00:06:53,520 --> 00:06:58,680 might not know so what I'm gonna do is 166 00:06:55,680 --> 00:07:00,600 in my case I'm going to make it 10 and 167 00:06:58,680 --> 00:07:03,020 see what happens 168 00:07:00,600 --> 00:07:03,020 okay 169 00:07:03,060 --> 00:07:07,020 there we have it our first assertion 170 00:07:05,100 --> 00:07:08,880 error so it's not just a matter of 171 00:07:07,020 --> 00:07:10,680 calling the function to run the test 172 00:07:08,880 --> 00:07:12,120 case you have to also maintain a streak 173 00:07:10,680 --> 00:07:13,560 of all your errors 174 00:07:12,120 --> 00:07:16,500 so 175 00:07:13,560 --> 00:07:18,740 let's wrap this in a very nice try and 176 00:07:16,500 --> 00:07:18,740 accept 177 00:07:25,500 --> 00:07:31,020 all right so we're gonna wrap it in a 178 00:07:27,660 --> 00:07:33,900 nice except and there we go so we're 179 00:07:31,020 --> 00:07:36,720 gonna keep a track of our exception 180 00:07:33,900 --> 00:07:39,180 and under here if there are any errors 181 00:07:36,720 --> 00:07:40,860 we have to print them so let's print it 182 00:07:39,180 --> 00:07:46,340 for 183 00:07:40,860 --> 00:07:46,340 wow life coding is hard so here we go 184 00:07:46,740 --> 00:07:50,819 I'm kind of cheating right here but it's 185 00:07:48,900 --> 00:07:52,860 okay so we are capturing all the errors 186 00:07:50,819 --> 00:07:55,460 we are getting a trace back and we're 187 00:07:52,860 --> 00:07:55,460 printing them 188 00:07:56,340 --> 00:07:59,160 hmm 189 00:07:57,720 --> 00:08:01,080 so okay 190 00:07:59,160 --> 00:08:03,599 we have something running here and then 191 00:08:01,080 --> 00:08:05,099 there is an error under test ad these 192 00:08:03,599 --> 00:08:07,080 are the this is a trace bag and where 193 00:08:05,099 --> 00:08:09,660 the session error is happening let's 194 00:08:07,080 --> 00:08:11,759 also give some more meaningful things so 195 00:08:09,660 --> 00:08:15,620 that we know something is running 196 00:08:11,759 --> 00:08:15,620 running desk keys 197 00:08:16,500 --> 00:08:20,639 test function name 198 00:08:18,060 --> 00:08:22,860 all right so we know that it's running 199 00:08:20,639 --> 00:08:26,099 certain test cases there are certain 200 00:08:22,860 --> 00:08:29,759 errors let's revert the spark that's our 201 00:08:26,099 --> 00:08:32,039 test Runner so now we have a test Runner 202 00:08:29,759 --> 00:08:35,719 which takes all the text objects runs 203 00:08:32,039 --> 00:08:37,740 them marks them success marks them error 204 00:08:35,719 --> 00:08:40,380 we're good to go 205 00:08:37,740 --> 00:08:42,959 the next thing is the easiest one of all 206 00:08:40,380 --> 00:08:44,940 accepted exceptions so looking at this 207 00:08:42,959 --> 00:08:48,240 by test.racist we are going to implement 208 00:08:44,940 --> 00:08:51,200 the races what can you make out of it 209 00:08:48,240 --> 00:08:51,200 the interface 210 00:08:52,680 --> 00:08:58,680 races is a context manager 211 00:08:55,920 --> 00:09:01,680 and context managers if you have seen it 212 00:08:58,680 --> 00:09:04,140 it comes with an entry and an exit block 213 00:09:01,680 --> 00:09:06,120 it is initialized with an exception type 214 00:09:04,140 --> 00:09:09,540 that you're expecting 215 00:09:06,120 --> 00:09:11,100 and when exiting the block you have to 216 00:09:09,540 --> 00:09:13,380 ensure that the particular exception 217 00:09:11,100 --> 00:09:15,300 that you have mentioned should be raised 218 00:09:13,380 --> 00:09:16,740 and if not we are going to raise an 219 00:09:15,300 --> 00:09:17,940 assertion error 220 00:09:16,740 --> 00:09:20,880 and 221 00:09:17,940 --> 00:09:21,899 oops not here yet 222 00:09:20,880 --> 00:09:25,680 okay 223 00:09:21,899 --> 00:09:30,480 so let's go to our PI test.races own pi 224 00:09:25,680 --> 00:09:33,360 test.races and this is my template block 225 00:09:30,480 --> 00:09:36,480 so right now to test this particular 226 00:09:33,360 --> 00:09:38,339 aspect of it I have a very nicely 227 00:09:36,480 --> 00:09:40,440 written test case right here so this is 228 00:09:38,339 --> 00:09:43,680 going to address type error if I'm 229 00:09:40,440 --> 00:09:45,060 passing anything that's not a integer to 230 00:09:43,680 --> 00:09:47,399 my uh 231 00:09:45,060 --> 00:09:50,100 ad subtract multiple divide 232 00:09:47,399 --> 00:09:51,060 so let's run this now it raises a type 233 00:09:50,100 --> 00:09:53,040 error 234 00:09:51,060 --> 00:09:54,839 and it's not being captured it's not 235 00:09:53,040 --> 00:09:57,540 being handled because we haven't 236 00:09:54,839 --> 00:09:59,940 implemented this Rises yet if you've 237 00:09:57,540 --> 00:10:02,040 perfectly implemented it then it would 238 00:09:59,940 --> 00:10:04,019 just pass through and Mark everything as 239 00:10:02,040 --> 00:10:06,660 access because the function is working 240 00:10:04,019 --> 00:10:09,779 as expected so at enter we don't have to 241 00:10:06,660 --> 00:10:13,200 do anything at Exit we have to check 242 00:10:09,779 --> 00:10:15,959 if the first the exception type is none 243 00:10:13,200 --> 00:10:19,560 or not if it's none no exception has 244 00:10:15,959 --> 00:10:21,300 been raised so that is there and if the 245 00:10:19,560 --> 00:10:22,800 exception type is not there then we are 246 00:10:21,300 --> 00:10:24,779 raising an assertion error both the 247 00:10:22,800 --> 00:10:27,240 cases Association error different logic 248 00:10:24,779 --> 00:10:29,940 but how is GitHub copilot doing all that 249 00:10:27,240 --> 00:10:33,019 because I have practiced this almost 100 250 00:10:29,940 --> 00:10:35,459 times so far so 251 00:10:33,019 --> 00:10:37,260 assertion error raised when the 252 00:10:35,459 --> 00:10:41,220 exception type is none or if it's not 253 00:10:37,260 --> 00:10:43,459 matched so now let's run this 254 00:10:41,220 --> 00:10:45,779 okay that's weird 255 00:10:43,459 --> 00:10:49,680 since we have already handled the 256 00:10:45,779 --> 00:10:52,079 exception we also have to Market as true 257 00:10:49,680 --> 00:10:54,899 that you don't have to do anything just 258 00:10:52,079 --> 00:10:57,000 everything is nice and good 259 00:10:54,899 --> 00:11:00,120 so now it has ran the test cases it has 260 00:10:57,000 --> 00:11:02,040 also ran the test Rises and things are 261 00:11:00,120 --> 00:11:04,260 fine and well but 262 00:11:02,040 --> 00:11:06,600 is it really working well 263 00:11:04,260 --> 00:11:08,700 so instead of this zero division error I 264 00:11:06,600 --> 00:11:10,620 am going to mark it as typewriter as 265 00:11:08,700 --> 00:11:12,180 well now our function should fail 266 00:11:10,620 --> 00:11:14,399 because it's expecting something and 267 00:11:12,180 --> 00:11:16,680 resulting in something 268 00:11:14,399 --> 00:11:21,000 there we go we have an assertion error 269 00:11:16,680 --> 00:11:23,820 my yes raised typewriter has been raised 270 00:11:21,000 --> 00:11:26,040 instead of a zero division error so yeah 271 00:11:23,820 --> 00:11:29,540 kind of works there 272 00:11:26,040 --> 00:11:29,540 let's revert this back 273 00:11:30,420 --> 00:11:35,420 and life is all good nice and successful 274 00:11:33,180 --> 00:11:35,420 again 275 00:11:36,899 --> 00:11:40,200 good 276 00:11:38,160 --> 00:11:42,660 the next thing is parameterized test 277 00:11:40,200 --> 00:11:44,640 case again this isn't this this might 278 00:11:42,660 --> 00:11:46,320 look very difficult but it's also very 279 00:11:44,640 --> 00:11:48,079 simple 280 00:11:46,320 --> 00:11:50,040 or the drill looking at 281 00:11:48,079 --> 00:11:51,480 bytest.mark.paramel trials what can you 282 00:11:50,040 --> 00:11:54,980 make out of it 283 00:11:51,480 --> 00:11:54,980 what python construct it is 284 00:11:55,200 --> 00:12:00,000 a decorator and if you look at it it's 285 00:11:57,899 --> 00:12:03,360 not just a normal decorator it's a 286 00:12:00,000 --> 00:12:05,760 decorator with arguments oh scary 287 00:12:03,360 --> 00:12:08,399 when it's so first you are registering 288 00:12:05,760 --> 00:12:10,140 the parameters the second your uh you're 289 00:12:08,399 --> 00:12:12,000 registering the function and then you're 290 00:12:10,140 --> 00:12:14,279 gonna return a wrapper all of that has 291 00:12:12,000 --> 00:12:17,100 to happen 292 00:12:14,279 --> 00:12:19,140 and when once you have the function then 293 00:12:17,100 --> 00:12:21,540 the function is being called you have to 294 00:12:19,140 --> 00:12:22,920 run it n times so that all your subtest 295 00:12:21,540 --> 00:12:25,380 also runs 296 00:12:22,920 --> 00:12:27,540 and lock the results even if there is 297 00:12:25,380 --> 00:12:29,880 failure in either one of them you have 298 00:12:27,540 --> 00:12:33,180 to ensure that that is captured and 299 00:12:29,880 --> 00:12:38,360 finally you will get there 300 00:12:33,180 --> 00:12:38,360 so Pi tested parameterize here is my 301 00:12:38,540 --> 00:12:44,940 is going to fill it the keys are look 302 00:12:42,660 --> 00:12:47,220 okay first the test case the own tester 303 00:12:44,940 --> 00:12:49,500 parameterize looks something like this 304 00:12:47,220 --> 00:12:51,980 here I've used Python's eval don't ever 305 00:12:49,500 --> 00:12:53,820 use it in production 306 00:12:51,980 --> 00:12:56,940 and 307 00:12:53,820 --> 00:12:59,519 yeah so to the parameters I am passing 308 00:12:56,940 --> 00:13:01,800 like three four Arguments for me to test 309 00:12:59,519 --> 00:13:03,839 it and your keys are going to be this 310 00:13:01,800 --> 00:13:06,959 your values are going to be this first 311 00:13:03,839 --> 00:13:08,940 when registering the arguments I have to 312 00:13:06,959 --> 00:13:12,839 put it in a nice format so that I can 313 00:13:08,940 --> 00:13:14,220 just pass it as argument so let's make a 314 00:13:12,839 --> 00:13:18,600 test args 315 00:13:14,220 --> 00:13:20,940 list and here we are going to 316 00:13:18,600 --> 00:13:22,800 okay 317 00:13:20,940 --> 00:13:25,139 different than the previous one but sure 318 00:13:22,800 --> 00:13:26,459 next what we're going to do is we are 319 00:13:25,139 --> 00:13:27,660 going to when the function is being 320 00:13:26,459 --> 00:13:30,839 called when your test case is being 321 00:13:27,660 --> 00:13:36,139 called You're creating subtests so let's 322 00:13:30,839 --> 00:13:36,139 create I comma test ARG 323 00:13:36,860 --> 00:13:41,779 in numerate of test arguments 324 00:13:42,740 --> 00:13:47,839 then we'll print that we are running the 325 00:13:45,300 --> 00:13:47,839 subdes 326 00:13:50,399 --> 00:13:55,940 and also call the particular function 327 00:13:52,740 --> 00:13:55,940 with the test argument 328 00:13:55,980 --> 00:14:00,779 so when previously when we were calling 329 00:13:58,920 --> 00:14:02,700 the test function it was just calling 330 00:14:00,779 --> 00:14:04,740 that one particular test object right 331 00:14:02,700 --> 00:14:07,320 now what we are calling is the wrapped 332 00:14:04,740 --> 00:14:08,639 decorator so inside the lab tech Creator 333 00:14:07,320 --> 00:14:10,440 instead of directly calling the function 334 00:14:08,639 --> 00:14:12,060 we are calling the function n number of 335 00:14:10,440 --> 00:14:13,500 times based on the parameters that is 336 00:14:12,060 --> 00:14:14,639 getting registered 337 00:14:13,500 --> 00:14:17,040 so 338 00:14:14,639 --> 00:14:17,820 let's run this 339 00:14:17,040 --> 00:14:21,360 um 340 00:14:17,820 --> 00:14:23,880 yeah so you have running sub uh subtest 341 00:14:21,360 --> 00:14:25,800 0 1 2 depending on the parameters if I 342 00:14:23,880 --> 00:14:28,920 go and add more it's going to add more 343 00:14:25,800 --> 00:14:30,959 if I change something here that also 344 00:14:28,920 --> 00:14:33,720 gets handled because we have taken care 345 00:14:30,959 --> 00:14:35,040 of assertion errors globally not you 346 00:14:33,720 --> 00:14:37,160 have to do you don't have to do anything 347 00:14:35,040 --> 00:14:41,240 particularly inside the parameterization 348 00:14:37,160 --> 00:14:41,240 so that is also good 349 00:14:41,399 --> 00:14:44,399 great 350 00:14:45,600 --> 00:14:50,880 all good now 351 00:14:48,480 --> 00:14:53,940 we have a decorator that takes arguments 352 00:14:50,880 --> 00:14:54,899 and a function looped over it all good 353 00:14:53,940 --> 00:14:58,500 to go 354 00:14:54,899 --> 00:15:00,720 the last but the scary part is fixtures 355 00:14:58,500 --> 00:15:03,600 this is a scary thing for me very easy 356 00:15:00,720 --> 00:15:04,620 to use very nice feature of Pi test but 357 00:15:03,600 --> 00:15:06,240 this one 358 00:15:04,620 --> 00:15:08,519 suck my brain out because I have to 359 00:15:06,240 --> 00:15:10,980 implement it all by myself 360 00:15:08,519 --> 00:15:13,440 and fixtures are great because you can 361 00:15:10,980 --> 00:15:16,500 do a ton of things from there 362 00:15:13,440 --> 00:15:19,260 you can define a whole large data set 363 00:15:16,500 --> 00:15:21,839 and have it available and multiple tests 364 00:15:19,260 --> 00:15:24,000 can use it or you can do your setup and 365 00:15:21,839 --> 00:15:25,620 tear down and there are Pi test comes 366 00:15:24,000 --> 00:15:28,980 with enormous amount of features this or 367 00:15:25,620 --> 00:15:31,800 to use scoping you can put it in your 368 00:15:28,980 --> 00:15:34,260 conf test and the variety no wonder they 369 00:15:31,800 --> 00:15:37,079 have 130k lines right they want to make 370 00:15:34,260 --> 00:15:39,180 your life easier so 371 00:15:37,079 --> 00:15:41,940 it's a decorator again 372 00:15:39,180 --> 00:15:43,079 and you can register a function as a 373 00:15:41,940 --> 00:15:46,139 fixture 374 00:15:43,079 --> 00:15:49,680 and when you are running the test case 375 00:15:46,139 --> 00:15:52,139 you have to ensure that you are passing 376 00:15:49,680 --> 00:15:55,680 the argument which is a fixture which in 377 00:15:52,139 --> 00:15:58,560 turn is a function which is decorated 378 00:15:55,680 --> 00:16:01,920 appeared yeah that's how I felt too 379 00:15:58,560 --> 00:16:04,800 handling test argument that is a fixture 380 00:16:01,920 --> 00:16:06,839 and then you have fixtures that are just 381 00:16:04,800 --> 00:16:09,660 data fixtures which is going to return 382 00:16:06,839 --> 00:16:11,160 dictionary or a list or a tuple or you 383 00:16:09,660 --> 00:16:14,160 have yielding fixtures which is going to 384 00:16:11,160 --> 00:16:16,139 yield and then do something later so all 385 00:16:14,160 --> 00:16:19,639 of these things are going on 386 00:16:16,139 --> 00:16:19,639 let's try to implement this 387 00:16:23,220 --> 00:16:28,500 so here is our beautiful fixture 388 00:16:26,519 --> 00:16:30,240 and that's it 389 00:16:28,500 --> 00:16:31,980 that's all you have to do for fixtures 390 00:16:30,240 --> 00:16:35,220 because 391 00:16:31,980 --> 00:16:38,100 you register a function as a fixture and 392 00:16:35,220 --> 00:16:39,899 your job is done but a lot of things 393 00:16:38,100 --> 00:16:43,079 that you have to do is in your test 394 00:16:39,899 --> 00:16:45,000 Runner you have to ensure that you are 395 00:16:43,079 --> 00:16:47,040 passing the arguments so far when we are 396 00:16:45,000 --> 00:16:49,980 calling the test function we are not 397 00:16:47,040 --> 00:16:52,500 passing any arguments so first thing 398 00:16:49,980 --> 00:16:55,800 that we have to do is to find out what 399 00:16:52,500 --> 00:17:00,060 arguments like parameters are there 400 00:16:55,800 --> 00:17:03,120 in your test function so this particular 401 00:17:00,060 --> 00:17:05,220 construct code variable names will give 402 00:17:03,120 --> 00:17:09,959 you all the arguments of a particular 403 00:17:05,220 --> 00:17:11,760 function and for args in test args we 404 00:17:09,959 --> 00:17:14,459 have to see whether that particular 405 00:17:11,760 --> 00:17:16,199 picture is in a fiction mapping 406 00:17:14,459 --> 00:17:18,959 but we haven't defined our fiction 407 00:17:16,199 --> 00:17:20,640 mapping yet so let's go to that here I 408 00:17:18,959 --> 00:17:23,459 have some logic to get all the test 409 00:17:20,640 --> 00:17:25,260 functions this does nothing but get all 410 00:17:23,459 --> 00:17:27,299 the members of the module 411 00:17:25,260 --> 00:17:29,520 finds out all the functions that starts 412 00:17:27,299 --> 00:17:32,880 with test underscore this time we are 413 00:17:29,520 --> 00:17:34,440 also going to check if members of one 414 00:17:32,880 --> 00:17:37,400 which is the object 415 00:17:34,440 --> 00:17:37,400 Dot 416 00:17:39,660 --> 00:17:43,799 name is a fixture wrapper because we 417 00:17:41,880 --> 00:17:45,480 have wrapped it in a fixture then we are 418 00:17:43,799 --> 00:17:48,419 going to store it in the fixture app 419 00:17:45,480 --> 00:17:51,419 picture mapping so great 420 00:17:48,419 --> 00:17:54,660 so it's in the fixture mapping then you 421 00:17:51,419 --> 00:17:56,880 call it that is your test argument 422 00:17:54,660 --> 00:17:58,919 let's also create a list 423 00:17:56,880 --> 00:18:01,080 of course this code is never going to be 424 00:17:58,919 --> 00:18:03,179 used or being production so all the 425 00:18:01,080 --> 00:18:05,419 solid yagni principles doesn't apply 426 00:18:03,179 --> 00:18:05,419 here 427 00:18:05,520 --> 00:18:08,179 list 428 00:18:08,460 --> 00:18:13,559 all right we are not going to use it 429 00:18:11,940 --> 00:18:15,900 test 430 00:18:13,559 --> 00:18:18,240 s 431 00:18:15,900 --> 00:18:21,720 dot append we are going to call the 432 00:18:18,240 --> 00:18:23,940 fixture and get the result put it in a 433 00:18:21,720 --> 00:18:27,000 test art list 434 00:18:23,940 --> 00:18:30,120 and gonna pass it to 435 00:18:27,000 --> 00:18:31,380 desktop list now when I run this it's 436 00:18:30,120 --> 00:18:34,200 gonna pass 437 00:18:31,380 --> 00:18:35,400 let's uncomment these test cases here I 438 00:18:34,200 --> 00:18:38,820 have a fixture that is getting 439 00:18:35,400 --> 00:18:41,640 registered and we have a 440 00:18:38,820 --> 00:18:42,720 a test con which is going to execute a 441 00:18:41,640 --> 00:18:43,980 particular connection which is also 442 00:18:42,720 --> 00:18:48,179 going to raise an operational error 443 00:18:43,980 --> 00:18:49,380 because I don't even have the database 444 00:18:48,179 --> 00:18:51,660 don't 445 00:18:49,380 --> 00:18:53,580 it's raising an assertion error which is 446 00:18:51,660 --> 00:18:56,580 weird because 447 00:18:53,580 --> 00:18:58,320 it's expecting an operational error but 448 00:18:56,580 --> 00:19:01,440 it's actually getting an attribute error 449 00:18:58,320 --> 00:19:04,020 what do you think is happening here 450 00:19:01,440 --> 00:19:06,660 Beyond errors like that has popped up 451 00:19:04,020 --> 00:19:09,720 and the problem is because of what's 452 00:19:06,660 --> 00:19:11,400 happening in con fixture if we go go 453 00:19:09,720 --> 00:19:12,840 here and print out what is actually 454 00:19:11,400 --> 00:19:15,299 getting passed when we are running the 455 00:19:12,840 --> 00:19:17,340 test case is you can see that it's a 456 00:19:15,299 --> 00:19:19,679 generator this is where I said it's an 457 00:19:17,340 --> 00:19:22,500 yielding function not 458 00:19:19,679 --> 00:19:24,419 a direct data fixture so we have to do 459 00:19:22,500 --> 00:19:25,860 something even more crazy 460 00:19:24,419 --> 00:19:28,559 uh 461 00:19:25,860 --> 00:19:30,660 again back to our test Runner here we 462 00:19:28,559 --> 00:19:32,780 have an argument which is the fixture we 463 00:19:30,660 --> 00:19:36,500 know that great 464 00:19:32,780 --> 00:19:36,500 now we have to get 465 00:19:39,480 --> 00:19:45,360 let's get the fixture object 466 00:19:42,960 --> 00:19:48,440 and we have to check if the fixture 467 00:19:45,360 --> 00:19:48,440 object has 468 00:19:49,440 --> 00:19:55,740 the next argument in it so that we know 469 00:19:52,799 --> 00:19:59,039 it's a yielding gen it's a generator if 470 00:19:55,740 --> 00:20:01,380 it's a generator we are going to call it 471 00:19:59,039 --> 00:20:03,480 and then store that value 472 00:20:01,380 --> 00:20:05,940 else 473 00:20:03,480 --> 00:20:09,780 we're going to call that object directly 474 00:20:05,940 --> 00:20:11,760 so that's the logic 475 00:20:09,780 --> 00:20:13,559 there are two types of fixtures one is 476 00:20:11,760 --> 00:20:16,559 an yielding fixture which is a generator 477 00:20:13,559 --> 00:20:19,020 the other one is a direct fixture object 478 00:20:16,559 --> 00:20:20,640 which just passes the data and we have 479 00:20:19,020 --> 00:20:22,260 handled both the cases now let's run 480 00:20:20,640 --> 00:20:24,240 this 481 00:20:22,260 --> 00:20:26,760 oh still an assertion error this has 482 00:20:24,240 --> 00:20:29,100 also happened quite a bit of time and 483 00:20:26,760 --> 00:20:32,160 still legit 484 00:20:29,100 --> 00:20:34,799 it's still a generator object 485 00:20:32,160 --> 00:20:37,520 now I'm confused 486 00:20:34,799 --> 00:20:37,520 any help 487 00:20:38,940 --> 00:20:45,620 I didn't call it yes great 488 00:20:42,299 --> 00:20:45,620 oh I don't call 489 00:20:50,160 --> 00:20:52,700 hmm 490 00:20:57,360 --> 00:21:00,500 it's a fixture object 491 00:21:04,080 --> 00:21:08,580 we're calling it and then 492 00:21:06,780 --> 00:21:11,480 okay this is why I was scared of doing 493 00:21:08,580 --> 00:21:11,480 this but 494 00:21:14,340 --> 00:21:20,660 okay I'm gonna add more print statements 495 00:21:16,320 --> 00:21:20,660 very classic programmer move 496 00:21:21,660 --> 00:21:26,299 a picture object what is coming here 497 00:21:23,400 --> 00:21:26,299 it's a wrapper 498 00:21:30,780 --> 00:21:33,380 right 499 00:21:38,159 --> 00:21:43,799 okay I'm gonna pull out another classic 500 00:21:41,100 --> 00:21:46,860 programmer move is have your backup code 501 00:21:43,799 --> 00:21:49,980 go through that see what it does and 502 00:21:46,860 --> 00:21:51,600 just go with it so here is my perfectly 503 00:21:49,980 --> 00:21:55,400 running fixture 504 00:21:51,600 --> 00:21:55,400 stuff I'm gonna copy paste that 505 00:21:56,520 --> 00:22:02,580 all right so 506 00:21:59,940 --> 00:22:04,440 we have the fixture value here we are 507 00:22:02,580 --> 00:22:07,559 going to call return on it or you're 508 00:22:04,440 --> 00:22:10,760 gonna directly call next on it or just 509 00:22:07,559 --> 00:22:10,760 gonna directly append it 510 00:22:11,640 --> 00:22:14,480 so that's there 511 00:22:15,179 --> 00:22:20,720 perfectly out of sync okay much better 512 00:22:24,120 --> 00:22:28,820 still a lot of things test arcs to pass 513 00:22:32,220 --> 00:22:35,059 all right 514 00:22:38,820 --> 00:22:46,320 thank you so yes that is our fixture 515 00:22:43,020 --> 00:22:48,360 which is a healing fixture next we call 516 00:22:46,320 --> 00:22:49,740 next on it if not if it's a data fixture 517 00:22:48,360 --> 00:22:52,799 that will also work 518 00:22:49,740 --> 00:22:54,120 so after a very so thank you for that I 519 00:22:52,799 --> 00:22:55,080 didn't I forgot to put the thumbs up 520 00:22:54,120 --> 00:22:57,059 over here 521 00:22:55,080 --> 00:22:59,100 so if you want to go through the same 522 00:22:57,059 --> 00:23:01,080 thing you can you can go to my GitHub 523 00:22:59,100 --> 00:23:03,000 repository and try it out on your own 524 00:23:01,080 --> 00:23:05,340 there is a blog post associated with it 525 00:23:03,000 --> 00:23:07,760 with it which needs an update since a 526 00:23:05,340 --> 00:23:11,700 lot has changed in the last three months 527 00:23:07,760 --> 00:23:13,440 and what can you do to have fun is you 528 00:23:11,700 --> 00:23:16,320 can try implementing mocks on top of 529 00:23:13,440 --> 00:23:19,020 this or try testing this testing library 530 00:23:16,320 --> 00:23:21,539 or testing your own testing library or 531 00:23:19,020 --> 00:23:24,020 build your own eggs and have fun as a 532 00:23:21,539 --> 00:23:24,020 part of it 533 00:23:24,299 --> 00:23:29,039 yeah most importantly don't forgot the 534 00:23:27,299 --> 00:23:31,500 first program that you ever wrote which 535 00:23:29,039 --> 00:23:33,480 was very fun and kept you hooked so far 536 00:23:31,500 --> 00:23:35,159 and if you want to check out my other 537 00:23:33,480 --> 00:23:38,700 works here if you want to talk about 538 00:23:35,159 --> 00:23:41,580 python devops data data Ops I'm here 539 00:23:38,700 --> 00:23:43,700 thank you 540 00:23:41,580 --> 00:23:43,700 thank you 541 00:23:46,340 --> 00:23:50,360 we have some time for questions 542 00:23:51,720 --> 00:23:54,740 they're all too hungry 543 00:23:55,620 --> 00:23:58,940 oh just up there 544 00:24:08,460 --> 00:24:14,299 so I have a question regarding 545 00:24:11,340 --> 00:24:18,380 um once you have the test completed 546 00:24:14,299 --> 00:24:21,720 usually you end in a big trouble 547 00:24:18,380 --> 00:24:24,240 analyzing the test because usually you 548 00:24:21,720 --> 00:24:28,020 just need to look at the assertive 549 00:24:24,240 --> 00:24:30,299 statements but when things grow 550 00:24:28,020 --> 00:24:33,900 a bunch of things you have hundreds of 551 00:24:30,299 --> 00:24:37,020 tests and analyzing that is quite 552 00:24:33,900 --> 00:24:39,900 difficult so did you have any strategy 553 00:24:37,020 --> 00:24:43,159 once you have everything completed just 554 00:24:39,900 --> 00:24:45,799 for example instead of doing the assert 555 00:24:43,159 --> 00:24:48,720 racing specific 556 00:24:45,799 --> 00:24:51,500 assertions or custom exceptions do you 557 00:24:48,720 --> 00:24:51,500 have something in mind 558 00:24:53,220 --> 00:24:56,700 quite capture that question exactly what 559 00:24:55,679 --> 00:24:59,539 you 560 00:24:56,700 --> 00:25:02,640 when you are once the test is completed 561 00:24:59,539 --> 00:25:06,120 and the analysis of the test is a bit 562 00:25:02,640 --> 00:25:07,159 difficult so do you have any strategy 563 00:25:06,120 --> 00:25:09,840 for that 564 00:25:07,159 --> 00:25:11,520 all right so assertions I don't know 565 00:25:09,840 --> 00:25:13,679 whether this is what you're asking but 566 00:25:11,520 --> 00:25:16,919 if you do it with by test this is a pi 567 00:25:13,679 --> 00:25:18,980 test version of test case that's here 568 00:25:16,919 --> 00:25:18,980 um 569 00:25:19,080 --> 00:25:24,059 yes so when you do it with pi test I'm 570 00:25:21,960 --> 00:25:26,220 going to change things over here yeah 571 00:25:24,059 --> 00:25:28,679 any number would work and I'm going to 572 00:25:26,220 --> 00:25:31,559 run it with by test 573 00:25:28,679 --> 00:25:33,299 I have printed it pretty badly right 574 00:25:31,559 --> 00:25:34,980 because we are building it live but when 575 00:25:33,299 --> 00:25:37,080 you do it with whiteest it's gonna show 576 00:25:34,980 --> 00:25:39,900 you exactly where that error happens and 577 00:25:37,080 --> 00:25:41,940 it also has a very nice Trace back that 578 00:25:39,900 --> 00:25:44,580 you can print with more verbose things 579 00:25:41,940 --> 00:25:46,860 so it doesn't matter at what level the 580 00:25:44,580 --> 00:25:48,720 error occurs you will have a complete 581 00:25:46,860 --> 00:25:51,480 race back of things and there are 582 00:25:48,720 --> 00:25:53,220 options in pi test to do that I think I 583 00:25:51,480 --> 00:25:54,659 when we do this case it's just an 584 00:25:53,220 --> 00:25:56,279 assertion error happening at that 585 00:25:54,659 --> 00:25:58,799 particular line but if you have it in 586 00:25:56,279 --> 00:26:01,740 your logic there also it works so let's 587 00:25:58,799 --> 00:26:06,380 say you are expecting five here but 588 00:26:01,740 --> 00:26:06,380 instead of add I'm gonna change this to 589 00:26:06,600 --> 00:26:10,860 oh 590 00:26:08,159 --> 00:26:12,659 let's do something fun 591 00:26:10,860 --> 00:26:14,580 10 always 592 00:26:12,659 --> 00:26:17,360 then it's also going to give you that 593 00:26:14,580 --> 00:26:17,360 whole Trace back 594 00:26:17,400 --> 00:26:22,500 yeah so here it says you know assert on 595 00:26:19,740 --> 00:26:24,120 the left you get 10 but on the 5 uh if 596 00:26:22,500 --> 00:26:26,340 you're making any particular logical 597 00:26:24,120 --> 00:26:30,679 error that also comes as a part of the 598 00:26:26,340 --> 00:26:30,679 price back okay thank you very much 599 00:26:32,460 --> 00:26:35,240 um no other questions 600 00:26:38,520 --> 00:26:40,580 thank you 601 00:26:46,400 --> 00:26:49,799 what do you think is the most useful 602 00:26:48,240 --> 00:26:51,779 Insight you've got about the internals 603 00:26:49,799 --> 00:26:53,580 of Pi test that you learn from this 604 00:26:51,779 --> 00:26:54,840 re-implementation is there some part of 605 00:26:53,580 --> 00:26:57,620 the internals that you know you wish 606 00:26:54,840 --> 00:26:57,620 people better understood 607 00:26:58,500 --> 00:27:05,299 oops 608 00:27:01,080 --> 00:27:05,299 I'm gonna go back to the slide where 609 00:27:07,740 --> 00:27:14,820 I was pretty overwhelmed scared uh it 610 00:27:10,980 --> 00:27:17,520 was very hard to even just look at it or 611 00:27:14,820 --> 00:27:19,559 understand it because it has built for 612 00:27:17,520 --> 00:27:22,080 so many different use cases even 613 00:27:19,559 --> 00:27:23,700 something as simple as fixture it 614 00:27:22,080 --> 00:27:25,860 behaves completely differently to what 615 00:27:23,700 --> 00:27:28,260 we what I have built so I have stopped 616 00:27:25,860 --> 00:27:30,059 drawing inspiration from pie test way 617 00:27:28,260 --> 00:27:34,580 early in the process and just built up 618 00:27:30,059 --> 00:27:34,580 my own version so that's 619 00:27:38,700 --> 00:27:41,240 hmm 620 00:27:52,559 --> 00:27:57,120 thank you for your talk could you talk 621 00:27:54,840 --> 00:27:59,940 us through the entry point of your code 622 00:27:57,120 --> 00:28:02,700 how it iterates over the test files 623 00:27:59,940 --> 00:28:05,460 finds the test classes finds the test 624 00:28:02,700 --> 00:28:09,740 methods and then works out what to run 625 00:28:05,460 --> 00:28:09,740 sure so it's pretty 626 00:28:09,779 --> 00:28:12,840 but sure 627 00:28:11,279 --> 00:28:15,120 all right 628 00:28:12,840 --> 00:28:17,940 that's my test Runner and it gets test 629 00:28:15,120 --> 00:28:23,059 files and then a bunch of test functions 630 00:28:17,940 --> 00:28:23,059 so test files is nothing but reading 631 00:28:24,059 --> 00:28:28,980 reading the directory if the directory 632 00:28:27,000 --> 00:28:31,880 does not have test in it you skip the 633 00:28:28,980 --> 00:28:34,679 directory and if it does have in it 634 00:28:31,880 --> 00:28:37,380 check get all the files that starts with 635 00:28:34,679 --> 00:28:38,640 tests and ends with pi and then return 636 00:28:37,380 --> 00:28:41,400 them 637 00:28:38,640 --> 00:28:43,140 so that's all the test files inside any 638 00:28:41,400 --> 00:28:45,840 particular directory of course I have 639 00:28:43,140 --> 00:28:48,539 done it for only one level 640 00:28:45,840 --> 00:28:51,059 and for the test function I'm importing 641 00:28:48,539 --> 00:28:53,400 the whole module like the whole file and 642 00:28:51,059 --> 00:28:56,039 going through its members using whether 643 00:28:53,400 --> 00:28:57,419 it's it's a function and if it if a 644 00:28:56,039 --> 00:28:59,279 function starts with test underscore 645 00:28:57,419 --> 00:29:01,640 that is a test function and I'm passing 646 00:28:59,279 --> 00:29:01,640 them back 647 00:29:04,980 --> 00:29:08,360 that's that help 648 00:29:08,460 --> 00:29:13,620 thank you 649 00:29:10,799 --> 00:29:15,360 okay thank you um thanks pavani for such 650 00:29:13,620 --> 00:29:17,419 an engaging talk 651 00:29:15,360 --> 00:29:17,419 um 652 00:29:18,600 --> 00:29:23,179 it's a token of our appreciation thank 653 00:29:20,340 --> 00:29:23,179 you thank you 654 00:29:27,020 --> 00:29:32,940 uh one small thing a very thank you to 655 00:29:30,179 --> 00:29:34,679 pycon Au they have sponsored me to come 656 00:29:32,940 --> 00:29:36,720 all the way from India to present the 657 00:29:34,679 --> 00:29:39,440 stock here thank you so much from the 658 00:29:36,720 --> 00:29:39,440 bottom of my heart