1 00:00:06,510 --> 00:00:08,550 - In industrial-strength code, 2 00:00:08,550 --> 00:00:12,750 it's important that your applications detect errors 3 00:00:12,750 --> 00:00:16,650 and throw exceptions and you can write tests 4 00:00:16,650 --> 00:00:19,080 to verify that happens. 5 00:00:19,080 --> 00:00:23,370 So, consider these three aspects of error handling. 6 00:00:23,370 --> 00:00:26,100 First of all, you might want to define an error class 7 00:00:26,100 --> 00:00:29,100 to encapsulate information about what's going on. 8 00:00:29,100 --> 00:00:31,770 So the example we are going to look at is a simple bank, 9 00:00:31,770 --> 00:00:33,030 simple example, 10 00:00:33,030 --> 00:00:36,090 where if the user tries to withdraw too much money 11 00:00:36,090 --> 00:00:37,250 and error occurs. 12 00:00:37,250 --> 00:00:39,570 So we're gonna define an error class 13 00:00:39,570 --> 00:00:40,920 to encapsulate information 14 00:00:40,920 --> 00:00:43,496 such as the amount they tried to withdraw, 15 00:00:43,496 --> 00:00:45,450 when they tried to do it, 16 00:00:45,450 --> 00:00:48,630 which ATM machine they were at when they tried to withdraw, 17 00:00:48,630 --> 00:00:50,130 that kind of information. 18 00:00:50,130 --> 00:00:51,870 So define an error class 19 00:00:51,870 --> 00:00:54,060 to store information about the problem. 20 00:00:54,060 --> 00:00:57,330 And then in your actual code throw an error 21 00:00:57,330 --> 00:01:01,050 when you detect an anomalous situation, insufficient funds. 22 00:01:01,050 --> 00:01:02,130 And then more importantly 23 00:01:02,130 --> 00:01:04,830 for this video series is how to test for that. 24 00:01:04,830 --> 00:01:06,360 How can you test your code 25 00:01:06,360 --> 00:01:08,190 to make sure that an error has been thrown 26 00:01:08,190 --> 00:01:09,570 when it should be? 27 00:01:09,570 --> 00:01:11,610 Okay. So we're gonna see all aspects of this 28 00:01:11,610 --> 00:01:14,820 in a simple example is in the testing for errors folder. 29 00:01:14,820 --> 00:01:16,970 So we'll first of all, take a look at that. 30 00:01:18,300 --> 00:01:23,300 In the code folder, JsTdd Lesson 03 testing for errors, 31 00:01:23,370 --> 00:01:24,540 that's the code folder. 32 00:01:24,540 --> 00:01:25,915 So if you open that folder up 33 00:01:25,915 --> 00:01:29,490 in the in the code editor, here we are. 34 00:01:29,490 --> 00:01:33,750 In my accounting js, I've defined two classes. 35 00:01:33,750 --> 00:01:35,340 I've defined an error class 36 00:01:35,340 --> 00:01:38,580 and I've defined the actual business class itself. 37 00:01:38,580 --> 00:01:41,370 Okay. So my error class extends error. 38 00:01:41,370 --> 00:01:43,200 That's a common practice 39 00:01:43,200 --> 00:01:45,510 when you are defining custom error classes. 40 00:01:45,510 --> 00:01:48,938 Error is a built in class in JavaScript. 41 00:01:48,938 --> 00:01:50,370 So that's my error class. 42 00:01:50,370 --> 00:01:51,900 We'll have a look at that first 43 00:01:51,900 --> 00:01:54,450 and then we'll see how to use the error class 44 00:01:54,450 --> 00:01:57,210 in my bank account code later. 45 00:01:57,210 --> 00:01:59,160 So first of all, the error class, 46 00:01:59,160 --> 00:02:00,510 this is what the error class looks like. 47 00:02:00,510 --> 00:02:01,620 I've call it bank error. 48 00:02:01,620 --> 00:02:04,950 It's common to call your class you know, something error. 49 00:02:04,950 --> 00:02:08,280 Extend the built in error class in JavaScript, 50 00:02:08,280 --> 00:02:09,930 define a constructor. 51 00:02:09,930 --> 00:02:12,360 Every error has a, a string message. 52 00:02:12,360 --> 00:02:15,330 So take a string message as a first parameter 53 00:02:15,330 --> 00:02:18,180 and then pass it to the super class constructor, 54 00:02:18,180 --> 00:02:19,106 the super class error. 55 00:02:19,106 --> 00:02:22,170 The constructor takes the error message 56 00:02:22,170 --> 00:02:24,120 and stores it internally 57 00:02:24,120 --> 00:02:26,407 and then any other parameters you want. 58 00:02:26,407 --> 00:02:27,686 So in our bank error, 59 00:02:27,686 --> 00:02:30,570 it would be useful to store amount of money 60 00:02:30,570 --> 00:02:33,420 that the user was trying to withdraw, for example. 61 00:02:33,420 --> 00:02:34,800 And probably convenient 62 00:02:34,800 --> 00:02:36,870 to have some kind of two string function 63 00:02:36,870 --> 00:02:40,975 which returns a textural representation of the error message 64 00:02:40,975 --> 00:02:43,354 plus other information as well. 65 00:02:43,354 --> 00:02:44,187 Okay. 66 00:02:44,187 --> 00:02:47,910 So that's the, that's my error class in accounting js. 67 00:02:47,910 --> 00:02:48,743 Next step, 68 00:02:48,743 --> 00:02:52,440 is to make use of that error class in my bank account. 69 00:02:52,440 --> 00:02:54,480 So here's my bank account code. 70 00:02:54,480 --> 00:02:56,821 I've got a static overdraft limit. 71 00:02:56,821 --> 00:03:01,818 Anybody can go overdrawn up to a thousand pounds, let's say. 72 00:03:01,818 --> 00:03:05,070 A constructor to initialize the details 73 00:03:05,070 --> 00:03:07,770 for this bank account, and the person's name, 74 00:03:07,770 --> 00:03:10,290 and the account balance is zero initially. 75 00:03:10,290 --> 00:03:12,810 The deposit function takes a balance 76 00:03:12,810 --> 00:03:15,180 takes an amount and adds it to the balance. 77 00:03:15,180 --> 00:03:16,013 That's simple. 78 00:03:16,013 --> 00:03:18,360 The withdrawal function, a bit more involved. 79 00:03:18,360 --> 00:03:20,520 Calculate what the balance would be 80 00:03:20,520 --> 00:03:22,800 if we subtracted the amount. 81 00:03:22,800 --> 00:03:25,980 And if the balance is too negative, 82 00:03:25,980 --> 00:03:30,980 so less than minus a thousand, then we throw an error. 83 00:03:31,170 --> 00:03:34,440 Okay. So that's the error class we just looked at. 84 00:03:34,440 --> 00:03:37,050 That's the error message, insufficient funds. 85 00:03:37,050 --> 00:03:39,903 That's the amount that the user was trying to withdraw. 86 00:03:41,070 --> 00:03:42,930 If the amount wasn't too large 87 00:03:42,930 --> 00:03:46,650 then we just proceed and subtract it from the balance. 88 00:03:46,650 --> 00:03:48,633 Okay. So that's my bank account class. 89 00:03:49,530 --> 00:03:52,050 And you can see the bank account class here, 90 00:03:52,050 --> 00:03:53,673 in my accounting js. 91 00:03:54,510 --> 00:03:58,470 Okay. So next then, then how can we be sure in our tests 92 00:03:58,470 --> 00:04:00,060 how can we validate the fact 93 00:04:00,060 --> 00:04:03,600 that the error was thrown when expected? 94 00:04:03,600 --> 00:04:08,010 So, here is my test suite in accounting test js. 95 00:04:08,010 --> 00:04:12,810 I'm gonna go through several different levels of rigor 96 00:04:12,810 --> 00:04:14,880 when it comes to checking for errors. 97 00:04:14,880 --> 00:04:18,120 Okay. So first of all, import the accounting module. 98 00:04:18,120 --> 00:04:20,610 When I import the accounting module 99 00:04:20,610 --> 00:04:24,180 that will have a class called bank account 100 00:04:24,180 --> 00:04:25,050 and a class called error. 101 00:04:25,050 --> 00:04:28,410 So the bank account class is in the accounting module, 102 00:04:28,410 --> 00:04:30,180 which I've just imported. 103 00:04:30,180 --> 00:04:31,950 So I've got a test suite. 104 00:04:31,950 --> 00:04:35,130 And before each test in my test suite, 105 00:04:35,130 --> 00:04:37,140 I create a new accounting object. 106 00:04:37,140 --> 00:04:40,410 It's important with unit testing 107 00:04:40,410 --> 00:04:42,540 that your unit tests are independent. 108 00:04:42,540 --> 00:04:46,680 So every test should have its own new bank account object. 109 00:04:46,680 --> 00:04:48,270 So I've created a bank account object there, 110 00:04:48,270 --> 00:04:49,890 that's the name of the folder. 111 00:04:49,890 --> 00:04:52,530 And just to get the ball rolling, 112 00:04:52,530 --> 00:04:56,203 I deposit 2000 pounds into that person's bank account. 113 00:04:56,203 --> 00:04:58,200 Thank you very much. 114 00:04:58,200 --> 00:05:02,010 And what we then got is that 1, 2, 3, 4, 5 different tests, 115 00:05:02,010 --> 00:05:04,560 which we're going to look at in the next few minutes. 116 00:05:04,560 --> 00:05:06,090 First of all, 117 00:05:06,090 --> 00:05:10,140 if the person, if Emily has 2000 in her account 118 00:05:10,140 --> 00:05:12,390 and she tries to withdraw a small amount 119 00:05:12,390 --> 00:05:16,233 then we'll test that that works okay without any errors. 120 00:05:17,070 --> 00:05:20,370 Then we'll see if we try to withdraw too much, 121 00:05:20,370 --> 00:05:21,870 that it should cause an error. 122 00:05:22,940 --> 00:05:23,790 And we'll then see 123 00:05:23,790 --> 00:05:27,630 four different levels of checking for errors. 124 00:05:27,630 --> 00:05:29,980 Okay. Depending on how rigorous you want to be. 125 00:05:31,020 --> 00:05:31,860 So first of all then, 126 00:05:31,860 --> 00:05:35,010 this is our first test where it's common usually 127 00:05:35,010 --> 00:05:36,900 when you're writing tests that you check 128 00:05:36,900 --> 00:05:39,660 for the kind of all good scenario first. 129 00:05:39,660 --> 00:05:41,070 Okay. So that's the first test. 130 00:05:41,070 --> 00:05:43,590 If I tried to withdraw a small account, 131 00:05:43,590 --> 00:05:45,450 that should work okay. 132 00:05:45,450 --> 00:05:49,050 So if the person's account balance is 2000, 133 00:05:49,050 --> 00:05:51,960 and we tried to withdraw a hundred, then that should succeed 134 00:05:51,960 --> 00:05:56,250 and the balance should be 1900. No problems at all. 135 00:05:56,250 --> 00:05:57,930 That's the first test. 136 00:05:57,930 --> 00:06:01,524 Then we start looking at error conditions. 137 00:06:01,524 --> 00:06:04,080 So if you wanna test an error occurs, 138 00:06:04,080 --> 00:06:06,480 if you just wanna test that the error occurred 139 00:06:06,480 --> 00:06:08,280 but you didn't want to, you know 140 00:06:08,280 --> 00:06:09,960 test the details of the error. 141 00:06:09,960 --> 00:06:13,200 Like did the error happen? And that's enough. 142 00:06:13,200 --> 00:06:15,660 This is the easiest way to check for errors. 143 00:06:15,660 --> 00:06:18,060 What you do is you call the expect function 144 00:06:18,060 --> 00:06:20,130 and you give it a Lambda. 145 00:06:20,130 --> 00:06:23,010 And in this Lambda, you basically invoke the method 146 00:06:23,010 --> 00:06:25,800 that you think will raise the error. 147 00:06:25,800 --> 00:06:27,840 And then you check that, you know 148 00:06:27,840 --> 00:06:31,320 this Lambda did cause an error to be thrown. 149 00:06:31,320 --> 00:06:33,570 So this is the simplest way of checking 150 00:06:33,570 --> 00:06:34,770 if an error occurred. 151 00:06:34,770 --> 00:06:36,570 when this Lambda was invoked, 152 00:06:36,570 --> 00:06:41,570 did the code inside that Lambda cause an error to occur? 153 00:06:41,970 --> 00:06:43,980 We haven't checked what type of error 154 00:06:43,980 --> 00:06:45,570 or what message or anything like that. 155 00:06:45,570 --> 00:06:47,490 We've just verified that 156 00:06:47,490 --> 00:06:50,694 the withdrawal function did throw an error of some type 157 00:06:50,694 --> 00:06:53,160 if we tried to withdraw too much money. 158 00:06:53,160 --> 00:06:55,893 So that's the simplest way of checking for an error. 159 00:06:56,730 --> 00:06:58,830 If you wanna be a bit more thorough, 160 00:06:58,830 --> 00:07:01,320 then you can test for a particular type of error. 161 00:07:01,320 --> 00:07:02,910 So you can say, okay, 162 00:07:02,910 --> 00:07:07,380 inside my expect function pass a Lambda with some code 163 00:07:07,380 --> 00:07:09,780 that we expect to throw an error. 164 00:07:09,780 --> 00:07:12,540 And then when you call to throw 165 00:07:12,540 --> 00:07:15,060 you can specify what type of error you expect. 166 00:07:15,060 --> 00:07:18,600 It could be the case that your function and a test 167 00:07:18,600 --> 00:07:21,060 threw different types of error, for different reasons. 168 00:07:21,060 --> 00:07:21,893 We can check 169 00:07:21,893 --> 00:07:25,020 that the particular error that it threw was the bank error. 170 00:07:25,020 --> 00:07:26,460 Remember bank error 171 00:07:26,460 --> 00:07:29,160 is the class defined in our accounting module. 172 00:07:29,160 --> 00:07:30,120 So you can check 173 00:07:30,120 --> 00:07:33,093 which particular kind of error did it throw. 174 00:07:34,290 --> 00:07:38,340 Right. You can go further and actually check the message. 175 00:07:38,340 --> 00:07:40,890 You can say, okay, here's my code. 176 00:07:40,890 --> 00:07:41,850 I'm expecting it. 177 00:07:41,850 --> 00:07:44,370 I'm testing that it threw an error. 178 00:07:44,370 --> 00:07:47,370 And this is the error message. 179 00:07:47,370 --> 00:07:50,400 And the previous example we checked for the error type. 180 00:07:50,400 --> 00:07:52,440 Now we're checking for the actual error message. 181 00:07:52,440 --> 00:07:54,540 Maybe you want to verify 182 00:07:54,540 --> 00:07:58,383 that a particular error message was thrown in the error. 183 00:08:00,060 --> 00:08:03,030 Okay. And if you want to test for a precise error object, 184 00:08:03,030 --> 00:08:06,390 you know, so you basically test all details about the error. 185 00:08:06,390 --> 00:08:09,240 Then you can be as precise as you want to be. 186 00:08:09,240 --> 00:08:10,440 So what you do is 187 00:08:10,440 --> 00:08:13,500 you basically call your method in a try block 188 00:08:13,500 --> 00:08:15,600 and then catch the error object, 189 00:08:15,600 --> 00:08:18,660 and then assert on the details of the error object 190 00:08:18,660 --> 00:08:21,600 in whatever ways you want to test. 191 00:08:21,600 --> 00:08:22,620 So here's an example, 192 00:08:22,620 --> 00:08:25,440 this is the most specific that you can be. 193 00:08:25,440 --> 00:08:29,010 So I'm I've got a try block where I call some code 194 00:08:29,010 --> 00:08:32,373 which I expect to throw an error, catch the error 195 00:08:32,373 --> 00:08:35,640 and then verify in as much detail as you want, 196 00:08:35,640 --> 00:08:36,780 if you need to. 197 00:08:36,780 --> 00:08:39,060 First of all, I'm expecting the error 198 00:08:39,060 --> 00:08:42,510 to be, the error object, to be an instance of that class. 199 00:08:42,510 --> 00:08:45,420 Was it this type of error that occurred? 200 00:08:45,420 --> 00:08:47,520 I can also check the error message, 201 00:08:47,520 --> 00:08:50,220 get the message property from the error object 202 00:08:50,220 --> 00:08:51,820 and check that it's this string. 203 00:08:53,310 --> 00:08:57,570 In my case, my error object also has an amount property. 204 00:08:57,570 --> 00:09:00,930 So I can check that the error amount is 3001. 205 00:09:00,930 --> 00:09:03,420 That's the amount that we were trying to withdraw. 206 00:09:03,420 --> 00:09:07,680 So if you want to, you can be as precise in error handling 207 00:09:07,680 --> 00:09:09,183 as, as you, as you like. 208 00:09:10,080 --> 00:09:14,303 Okay. So I'm going to run the code and verify 209 00:09:15,270 --> 00:09:18,870 that when I expect errors to occur, they do occur. 210 00:09:18,870 --> 00:09:23,190 So let's run the tests and, and let's see what happens. 211 00:09:23,190 --> 00:09:26,280 Okay. So here I am in my command window. 212 00:09:26,280 --> 00:09:30,900 So NPM round test, and then parameters, 213 00:09:30,900 --> 00:09:32,340 the name of the file, 214 00:09:32,340 --> 00:09:37,340 the name of the test file was accounting.test.js. 215 00:09:38,340 --> 00:09:39,960 Give it the file name. 216 00:09:39,960 --> 00:09:43,740 So it'll run all five test functions. 217 00:09:43,740 --> 00:09:46,899 One test function where the withdrawal was okay 218 00:09:46,899 --> 00:09:50,520 and four test functions where the error wasn't okay. 219 00:09:50,520 --> 00:09:52,470 And an error occurred 220 00:09:52,470 --> 00:09:56,850 and it successfully, you know, caught those errors. 221 00:09:56,850 --> 00:09:57,960 So there we go. 222 00:09:57,960 --> 00:10:02,040 So in the case where no error occurred or was expected, 223 00:10:02,040 --> 00:10:03,180 that was fine. 224 00:10:03,180 --> 00:10:06,300 In the four cases where an error was expected, 225 00:10:06,300 --> 00:10:08,160 my code did throw an error. 226 00:10:08,160 --> 00:10:11,790 So as far as my tests are concerned it they've succeeded. 227 00:10:11,790 --> 00:10:15,870 My code successfully threw an error when expected 228 00:10:15,870 --> 00:10:17,870 and that's what we were hoping to prove.