1 00:00:06,600 --> 00:00:08,220 - [Instructor] All the tests we've seen so far 2 00:00:08,220 --> 00:00:10,860 are what we call resulting state tests. 3 00:00:10,860 --> 00:00:13,830 So in your test function, you call a method, 4 00:00:13,830 --> 00:00:15,810 the method that you're trying to test, 5 00:00:15,810 --> 00:00:17,760 and then you have an expect statement, 6 00:00:17,760 --> 00:00:21,180 an assertion to check the return value, for example. 7 00:00:21,180 --> 00:00:23,910 So typically, you just have one assert statement 8 00:00:23,910 --> 00:00:26,760 or one expect function per test function 9 00:00:26,760 --> 00:00:29,760 because if you have multiple assertions, 10 00:00:29,760 --> 00:00:33,600 if an assertion fails, it throws an exception. 11 00:00:33,600 --> 00:00:36,510 It doesn't go on to the next expect statement. 12 00:00:36,510 --> 00:00:39,420 So, you know, there isn't any point 13 00:00:39,420 --> 00:00:43,440 in having multiple expects per test. 14 00:00:43,440 --> 00:00:46,200 Generally speaking, you should have one expect statement, 15 00:00:46,200 --> 00:00:48,273 one assertion per test function. 16 00:00:49,230 --> 00:00:52,020 Now, there are some exceptions to that rule. 17 00:00:52,020 --> 00:00:55,830 Imagine you call a function and it returns an object 18 00:00:55,830 --> 00:00:57,810 and that object is complicated. 19 00:00:57,810 --> 00:01:00,870 And in order to make sure that the object is correct, 20 00:01:00,870 --> 00:01:03,300 you've gotta have multiple expect statements 21 00:01:03,300 --> 00:01:06,420 to check every aspect of that return object. 22 00:01:06,420 --> 00:01:08,130 Now that actually makes sense 23 00:01:08,130 --> 00:01:10,620 because you're just testing one logical scenario. 24 00:01:10,620 --> 00:01:12,780 You might need to have multiple assertions, 25 00:01:12,780 --> 00:01:16,200 but it's still one logical outcome that you're testing. 26 00:01:16,200 --> 00:01:17,880 So let me give you an example of that. 27 00:01:17,880 --> 00:01:18,810 Have a look at this code here. 28 00:01:18,810 --> 00:01:22,380 I've got an example that shows a resulting state test 29 00:01:22,380 --> 00:01:25,200 and there's a hypothetical code example. 30 00:01:25,200 --> 00:01:27,480 I've got some hypothetical function 31 00:01:27,480 --> 00:01:29,460 that returns a date, d. 32 00:01:29,460 --> 00:01:31,770 And that I want to check that the day, 33 00:01:31,770 --> 00:01:34,260 and the month, and the year are all valid. 34 00:01:34,260 --> 00:01:36,600 So, you know, I've decided to implement that 35 00:01:36,600 --> 00:01:39,390 as three separate expect statements. 36 00:01:39,390 --> 00:01:40,560 And that actually makes sense 37 00:01:40,560 --> 00:01:43,200 because it's still one logical outcome 38 00:01:43,200 --> 00:01:44,033 that I'm testing. 39 00:01:44,033 --> 00:01:47,910 By the way, that's my birthday, the 3rd of December, 1964. 40 00:01:47,910 --> 00:01:51,150 Now, if you're dealing with dates in lots of your tests, 41 00:01:51,150 --> 00:01:53,070 you might find that lots of your tests 42 00:01:53,070 --> 00:01:56,700 end up having a day, a month, and a year check. 43 00:01:56,700 --> 00:01:58,830 So you might find this kind of code 44 00:01:58,830 --> 00:02:02,970 repeating in lots of places in your test functions. 45 00:02:02,970 --> 00:02:06,750 So having repeating tests is just as bad 46 00:02:06,750 --> 00:02:08,640 as having repeated code. 47 00:02:08,640 --> 00:02:09,660 So what you might consider 48 00:02:09,660 --> 00:02:13,893 is to encapsulate that complexity into a helper function. 49 00:02:15,180 --> 00:02:18,450 So sometimes it's handy to define a custom assertion method, 50 00:02:18,450 --> 00:02:21,420 which encapsulates a complicated check, 51 00:02:21,420 --> 00:02:23,940 like a day, a month, and a year. 52 00:02:23,940 --> 00:02:26,910 You can put all of those checks into this helper method 53 00:02:26,910 --> 00:02:28,020 and then just call it. 54 00:02:28,020 --> 00:02:30,657 You can reuse it in multiple tests. 55 00:02:30,657 --> 00:02:32,310 I'm gonna do that now. 56 00:02:32,310 --> 00:02:35,370 I'm gonna take that code in InVision Studio, 57 00:02:35,370 --> 00:02:39,060 I'm going to refactor, I'm going to extract that common code 58 00:02:39,060 --> 00:02:40,980 into our global scope. 59 00:02:40,980 --> 00:02:42,630 Yeah, that'll probably be good. 60 00:02:42,630 --> 00:02:43,780 I'll call that function 61 00:02:46,140 --> 00:02:50,403 test day month year, 62 00:02:52,260 --> 00:02:53,093 like that. 63 00:02:53,093 --> 00:02:55,740 Okay, so it takes in a date object 64 00:02:55,740 --> 00:02:58,530 and then it kinda validates the day, 65 00:02:58,530 --> 00:02:59,730 the month, and the year. 66 00:03:00,571 --> 00:03:03,300 The refactoring hasn't been quite as useful 67 00:03:03,300 --> 00:03:04,920 as might hoped it would be 68 00:03:04,920 --> 00:03:06,570 because it's kind of hard-coded, 69 00:03:06,570 --> 00:03:09,870 the value for the day, the month, and the year. 70 00:03:09,870 --> 00:03:12,030 So I think I'm gonna parameterize it, 71 00:03:12,030 --> 00:03:15,000 I can do, instead of having a hard-coded parameter here, 72 00:03:15,000 --> 00:03:16,650 I'm going to parameterize it with 73 00:03:17,940 --> 00:03:20,013 expected date, 74 00:03:22,110 --> 00:03:24,423 expected month, 75 00:03:25,530 --> 00:03:27,060 expected year. 76 00:03:27,060 --> 00:03:28,950 So it parameterizes it. 77 00:03:28,950 --> 00:03:32,880 And then, obviously, here I'd be using the expected day. 78 00:03:32,880 --> 00:03:35,430 Check that the incoming date object 79 00:03:35,430 --> 00:03:37,380 has the expected day. 80 00:03:37,380 --> 00:03:39,000 Check that the incoming date object 81 00:03:39,000 --> 00:03:41,100 has the expected month. 82 00:03:41,100 --> 00:03:43,383 And also that it has the expected year. 83 00:03:44,846 --> 00:03:47,160 (keys clicking) 84 00:03:47,160 --> 00:03:48,300 Like so. 85 00:03:48,300 --> 00:03:49,428 Okay? 86 00:03:49,428 --> 00:03:50,490 And then up here, when I call it in this occasion, 87 00:03:50,490 --> 00:03:52,080 I can just say, well that's the date object 88 00:03:52,080 --> 00:03:52,980 that I'm testing. 89 00:03:52,980 --> 00:03:56,160 I want to check that it's got the expected day, 90 00:03:56,160 --> 00:03:58,402 the expected year, ah, month, 91 00:03:58,402 --> 00:04:00,090 and the expected year, like that. 92 00:04:00,090 --> 00:04:01,020 And what I've done now 93 00:04:01,020 --> 00:04:03,300 is I've got this function here 94 00:04:03,300 --> 00:04:05,460 encapsulates some complex test. 95 00:04:05,460 --> 00:04:07,710 Obviously, that could be as complicated as I want it to be, 96 00:04:07,710 --> 00:04:09,150 but it's really useful. 97 00:04:09,150 --> 00:04:11,970 So I could reuse that helper function 98 00:04:11,970 --> 00:04:13,920 in any of my tests that needed it. 99 00:04:13,920 --> 00:04:15,510 So that's actually, 100 00:04:15,510 --> 00:04:17,820 avoiding duplication in tests 101 00:04:17,820 --> 00:04:19,740 is important, otherwise the tests 102 00:04:19,740 --> 00:04:22,590 are gonna start getting hard to maintain. 103 00:04:22,590 --> 00:04:23,695 Okay? 104 00:04:23,695 --> 00:04:25,110 So that's a useful technique. 105 00:04:25,110 --> 00:04:26,850 Right, another kind of test that you can have 106 00:04:26,850 --> 00:04:29,850 is a guard test, a precondition. 107 00:04:29,850 --> 00:04:31,710 Basically, what you do is you have an assertion 108 00:04:31,710 --> 00:04:33,750 at the beginning, like an expect statement, 109 00:04:33,750 --> 00:04:36,210 at the beginning of your test method. 110 00:04:36,210 --> 00:04:39,150 Then, in your precondition, 111 00:04:39,150 --> 00:04:42,540 you can check, is the object in some known initial state? 112 00:04:42,540 --> 00:04:45,120 Before I do anything, let's just make sure 113 00:04:45,120 --> 00:04:46,350 that the incoming object 114 00:04:46,350 --> 00:04:48,933 is in some initial known state. 115 00:04:50,280 --> 00:04:53,040 Then, I invoke the method and the test as normal 116 00:04:53,040 --> 00:04:55,410 to, you know, to do something to the object. 117 00:04:55,410 --> 00:04:58,830 And then afterwards, I can have a resulting state test 118 00:04:58,830 --> 00:05:01,740 to see what's the state of my object afterwards. 119 00:05:01,740 --> 00:05:04,530 And that's effectively a postcondition, okay? 120 00:05:04,530 --> 00:05:06,570 So it tests the final state of the object. 121 00:05:06,570 --> 00:05:07,950 So what you've basically done 122 00:05:07,950 --> 00:05:11,550 is to ensure the object was in some initial state, 123 00:05:11,550 --> 00:05:12,720 I called a method, 124 00:05:12,720 --> 00:05:15,390 and now it's in a different, changed state. 125 00:05:15,390 --> 00:05:17,310 That you have actually, 126 00:05:17,310 --> 00:05:20,310 the object has actually gone through a transition. 127 00:05:20,310 --> 00:05:22,050 Let me show you an example of that. 128 00:05:22,050 --> 00:05:24,100 I've got an example here of a guard test. 129 00:05:25,170 --> 00:05:28,860 Imagine you've got some hypothetical person object 130 00:05:28,860 --> 00:05:31,830 and you want to add to this person's fleet of cars 131 00:05:31,830 --> 00:05:33,000 in their drive. 132 00:05:33,000 --> 00:05:35,880 You want to give this person a Bugatti Divo 133 00:05:35,880 --> 00:05:37,650 and then you want to say afterwards, 134 00:05:37,650 --> 00:05:39,300 let's get all the cars, 135 00:05:39,300 --> 00:05:41,970 imagine that's the collection of cars for this person, 136 00:05:41,970 --> 00:05:46,200 make sure that that collection contains a Bugatti Divo, 137 00:05:46,200 --> 00:05:47,380 okay? 138 00:05:47,380 --> 00:05:49,440 What, is this a valid test? 139 00:05:49,440 --> 00:05:50,970 Not necessarily. 140 00:05:50,970 --> 00:05:52,470 It could be the case that the person 141 00:05:52,470 --> 00:05:54,930 already had a Bugatti Divo, 142 00:05:54,930 --> 00:05:57,750 so adding the Bugatti Divo 143 00:05:57,750 --> 00:06:00,480 hasn't necessarily changed the state. 144 00:06:00,480 --> 00:06:02,820 Maybe that method failed, 145 00:06:02,820 --> 00:06:04,710 but maybe we got away with it 146 00:06:04,710 --> 00:06:08,730 because the person had a Bugatti Divo at the beginning. 147 00:06:08,730 --> 00:06:10,170 So the only way that it can check 148 00:06:10,170 --> 00:06:11,850 that that method's actually worked 149 00:06:11,850 --> 00:06:14,250 is to say, well, let's validate 150 00:06:14,250 --> 00:06:16,200 or let's ensure that this person 151 00:06:16,200 --> 00:06:18,990 didn't have a Bugatti Divo initially. 152 00:06:18,990 --> 00:06:19,823 Let's do that. 153 00:06:20,670 --> 00:06:22,140 Let's have an expectation. 154 00:06:22,140 --> 00:06:23,550 This is a guard condition. 155 00:06:23,550 --> 00:06:26,010 Let's say that we expect 156 00:06:26,010 --> 00:06:28,920 when we get, when you say to the person, 157 00:06:28,920 --> 00:06:30,093 dot get cars, 158 00:06:31,410 --> 00:06:33,450 when we get to the cars for the person initially, 159 00:06:33,450 --> 00:06:34,860 I want to make sure that initially, 160 00:06:34,860 --> 00:06:36,730 it does not contain 161 00:06:38,790 --> 00:06:39,963 a Bugatti Divo. 162 00:06:41,220 --> 00:06:42,720 Okay, so this would be me. 163 00:06:42,720 --> 00:06:45,150 I think it would be most people on the planet. 164 00:06:45,150 --> 00:06:47,610 Let's first of all ensure that the person, 165 00:06:47,610 --> 00:06:49,050 if I get the person's cars, 166 00:06:49,050 --> 00:06:52,860 that person doesn't have a Bugatti Divo initially. 167 00:06:52,860 --> 00:06:54,720 Okay, good, we know that. 168 00:06:54,720 --> 00:06:55,553 Otherwise, you know, 169 00:06:55,553 --> 00:06:56,940 if the person did have a Bugatti Divo, 170 00:06:56,940 --> 00:06:58,770 it would fail the test. 171 00:06:58,770 --> 00:07:01,740 So assuming that the person doesn't have one initially, 172 00:07:01,740 --> 00:07:04,350 when we add one and then we verify 173 00:07:04,350 --> 00:07:05,970 that the person now has one, 174 00:07:05,970 --> 00:07:07,620 it validates that we've transitioned 175 00:07:07,620 --> 00:07:11,580 from the no Bugatti to yes, I have a Bugatti. 176 00:07:11,580 --> 00:07:14,070 That means this method has actually worked. 177 00:07:14,070 --> 00:07:14,903 Okay? 178 00:07:14,903 --> 00:07:18,900 So we were in that state, now we're in that state. 179 00:07:18,900 --> 00:07:22,140 Something must've happened in this method to change state. 180 00:07:22,140 --> 00:07:24,960 It's a, we've undergone a transition. 181 00:07:24,960 --> 00:07:28,023 A Bugatti-free zone to a Bugatti ownership zone. 182 00:07:29,310 --> 00:07:31,020 Okay, that's still on my Christmas card list, 183 00:07:31,020 --> 00:07:33,210 by the way, Bugatti Divo. 184 00:07:33,210 --> 00:07:35,280 The third type of test we could look at 185 00:07:35,280 --> 00:07:37,110 is a delta test. 186 00:07:37,110 --> 00:07:40,650 This is often used for performance measurements. 187 00:07:40,650 --> 00:07:42,780 You don't necessarily know 188 00:07:42,780 --> 00:07:44,940 what the initial state of the object is 189 00:07:44,940 --> 00:07:46,140 or what the final state is, 190 00:07:46,140 --> 00:07:48,630 but you know what the delta is going to be, 191 00:07:48,630 --> 00:07:50,460 a relative change. 192 00:07:50,460 --> 00:07:53,460 So you don't know the absolute initial state 193 00:07:53,460 --> 00:07:54,930 or the absolute final state, 194 00:07:54,930 --> 00:07:57,030 but you know what the delta should be. 195 00:07:57,030 --> 00:07:59,880 So like I said, performance testing is a good example. 196 00:07:59,880 --> 00:08:01,500 When you do integration tests, 197 00:08:01,500 --> 00:08:04,080 when you're integrating the user interface, 198 00:08:04,080 --> 00:08:07,230 your code, the backend REST services, a database. 199 00:08:07,230 --> 00:08:08,700 Maybe you're doing performance checks 200 00:08:08,700 --> 00:08:10,830 to make sure that it's fast enough. 201 00:08:10,830 --> 00:08:13,260 So what you could do is, 202 00:08:13,260 --> 00:08:15,960 you don't know the absolute time 203 00:08:15,960 --> 00:08:17,610 or you don't really care what the absolute time 204 00:08:17,610 --> 00:08:19,650 is at any given juncture, 205 00:08:19,650 --> 00:08:22,140 but you want to know the difference in time 206 00:08:22,140 --> 00:08:24,930 that the operation took, how long did it take. 207 00:08:24,930 --> 00:08:27,120 So record the record the time at the beginning 208 00:08:27,120 --> 00:08:30,000 of the operation, do the operation, 209 00:08:30,000 --> 00:08:31,920 and then record the time afterwards. 210 00:08:31,920 --> 00:08:34,350 And then, you can calculate the delta 211 00:08:34,350 --> 00:08:38,340 to see if you have sufficiently adequate performance. 212 00:08:38,340 --> 00:08:41,220 So I've got some pseudocode to demonstrate that, as well. 213 00:08:41,220 --> 00:08:44,550 This is my demo of a delta test. 214 00:08:44,550 --> 00:08:47,220 I've got some hypothetical function. 215 00:08:47,220 --> 00:08:50,100 You could use the JavaScript date API. 216 00:08:50,100 --> 00:08:51,840 Get the current time in milliseconds. 217 00:08:51,840 --> 00:08:54,360 Who knows what the current time is? 218 00:08:54,360 --> 00:08:57,360 Whatever it is, do something, okay? 219 00:08:57,360 --> 00:08:59,940 So imagine that's some kind of REST service call. 220 00:08:59,940 --> 00:09:02,610 And then, get the time afterwards 221 00:09:02,610 --> 00:09:04,200 and let's measure the time difference. 222 00:09:04,200 --> 00:09:06,780 Imagine that's the time difference in milliseconds. 223 00:09:06,780 --> 00:09:09,810 Our performance test is that the time delta 224 00:09:09,810 --> 00:09:11,610 should be less than 5,000. 225 00:09:11,610 --> 00:09:14,310 So that's an example of a delta test. 226 00:09:14,310 --> 00:09:17,160 I don't really care what the final time is. 227 00:09:17,160 --> 00:09:19,020 I don't really care what the initial time was. 228 00:09:19,020 --> 00:09:21,150 All I wanna look at is the delta between them, 229 00:09:21,150 --> 00:09:23,280 what's the difference between the two. 230 00:09:23,280 --> 00:09:25,320 Okay, so these are the common types of tests 231 00:09:25,320 --> 00:09:28,890 that you have in JavaScript or other languages: 232 00:09:28,890 --> 00:09:30,570 resulting state tests, 233 00:09:30,570 --> 00:09:33,420 where you have assertions at the end of a method. 234 00:09:33,420 --> 00:09:37,005 Maybe we factored into a help function, like so. 235 00:09:37,005 --> 00:09:40,890 A guard condition to check the incoming state of an object 236 00:09:40,890 --> 00:09:42,150 as a precondition, 237 00:09:42,150 --> 00:09:43,110 so that you know it's gone 238 00:09:43,110 --> 00:09:45,750 through some kind of transition by the end. 239 00:09:45,750 --> 00:09:47,250 And then, a delta test, 240 00:09:47,250 --> 00:09:48,420 where you measure the difference 241 00:09:48,420 --> 00:09:51,480 between the end condition and the start condition 242 00:09:51,480 --> 00:09:55,083 to make sure that, for example, performance is suitable.