1 00:00:08,030 --> 00:00:13,650 Welcome back. We've already seen how to implement a test for a function. 2 00:00:13,650 --> 00:00:17,520 You just invoke test.testEqual where their first input is 3 00:00:17,520 --> 00:00:21,480 an invocation of the function and the second input is the correct value, 4 00:00:21,480 --> 00:00:23,445 the correct output for the function. 5 00:00:23,445 --> 00:00:28,545 In this video, we're going to consider what tests are good to implement. 6 00:00:28,545 --> 00:00:33,825 It's useful to distinguish between two kinds of things that a function might accomplish. 7 00:00:33,825 --> 00:00:37,110 One is that it might return a value, 8 00:00:42,050 --> 00:00:48,595 and the other thing is that it might have a side effect. 9 00:00:48,595 --> 00:00:50,950 By a side effect, 10 00:00:50,950 --> 00:00:58,630 I mean that it might change the contents of a list or change the contents of 11 00:00:58,630 --> 00:01:06,100 the dictionary or might also write to a file or produce some output in the output window, 12 00:01:06,100 --> 00:01:08,875 but we're not going to use test.testEqual for 13 00:01:08,875 --> 00:01:12,190 checking on writing to a file or the output window, 14 00:01:12,190 --> 00:01:15,280 but we will use test.testEqual to see if 15 00:01:15,280 --> 00:01:20,000 a list has been modified or a dictionary has been modified. 16 00:01:21,410 --> 00:01:25,605 So, I'll call the two different kinds of tests, 17 00:01:25,605 --> 00:01:28,690 a return value test or a side effect test 18 00:01:28,690 --> 00:01:33,330 depending on what it is that the function was supposed to be doing. 19 00:01:33,940 --> 00:01:37,520 Let's first consider return value test. 20 00:01:37,520 --> 00:01:39,425 So, this is a function like square, 21 00:01:39,425 --> 00:01:42,920 where its whole job is just to compute a new value. 22 00:01:42,920 --> 00:01:45,290 It gets an input, it produces an output, 23 00:01:45,290 --> 00:01:49,510 it's not changing the contents of any list or dictionary. 24 00:01:49,510 --> 00:01:55,140 So, which inputs should we give it as tests? 25 00:01:55,390 --> 00:02:01,100 One way to think about that is to think about the equivalence classes of inputs, 26 00:02:01,100 --> 00:02:04,340 because we're not going to be able to test every single possible input. 27 00:02:04,340 --> 00:02:11,230 So, maybe we should for something that's computing squares or some arithmetic thing, 28 00:02:11,230 --> 00:02:15,965 maybe one equivalence class of inputs are positive numbers. 29 00:02:15,965 --> 00:02:22,155 You already see we've got one test where we're passing in three as an input. 30 00:02:22,155 --> 00:02:28,205 But perhaps, we ought to have another input which would be negative number. 31 00:02:28,205 --> 00:02:32,830 Maybe if we somehow implemented this wrong, 32 00:02:32,830 --> 00:02:34,980 it would work for the positive numbers, 33 00:02:34,980 --> 00:02:36,500 but not work for the negative numbers. 34 00:02:36,500 --> 00:02:42,720 So, it would be a good idea to have a test of some negative value. 35 00:02:44,780 --> 00:02:50,900 That if we square minus four we should get positive 16, not negative 16. 36 00:02:51,450 --> 00:02:54,475 It's also a good idea to think of, 37 00:02:54,475 --> 00:02:57,445 what other classes of inputs could we get? 38 00:02:57,445 --> 00:03:00,650 Maybe we could get a floating point number. 39 00:03:02,370 --> 00:03:06,115 Maybe it only works on integers for some reason. 40 00:03:06,115 --> 00:03:10,359 So, suppose I had two point, 41 00:03:10,359 --> 00:03:14,710 well, I need to do something where I can actually compute it myself. 42 00:03:14,710 --> 00:03:20,820 Let's see, 1.5, what's the square of 1.5? 43 00:03:20,820 --> 00:03:26,085 It should be 2.25, I believe. 44 00:03:26,085 --> 00:03:28,545 Let's check that to be sure. 45 00:03:28,545 --> 00:03:31,070 Yes, I passed all three of those tests. 46 00:03:31,070 --> 00:03:32,740 You'll notice this is an important point. 47 00:03:32,740 --> 00:03:37,000 When you're writing a test you got to figure out which inputs should you run a test on, 48 00:03:37,000 --> 00:03:39,890 and you have to know what is the correct output. 49 00:03:39,890 --> 00:03:43,610 In that case, I was a little unsure about the square of 1.5, 50 00:03:43,610 --> 00:03:46,060 but it is 2.25. 51 00:03:46,060 --> 00:03:48,630 Then you also should think about sort of 52 00:03:48,630 --> 00:03:50,960 the boundaries between these equivalence classes. 53 00:03:50,960 --> 00:03:52,100 So, I did a positive number, 54 00:03:52,100 --> 00:03:53,675 I did a negative number. 55 00:03:53,675 --> 00:04:00,340 Gee, what happens if we do zero? We'll get that right. 56 00:04:00,340 --> 00:04:04,910 So, it's a good idea to have a test for these boundary conditions, 57 00:04:04,910 --> 00:04:07,100 these edge or extreme cases. 58 00:04:07,100 --> 00:04:10,645 It's also helpful to think about what might go wrong. 59 00:04:10,645 --> 00:04:14,510 Like, what could I possibly do wrong and this is a very simple function, 60 00:04:14,510 --> 00:04:16,130 it's hard to think of things that could go wrong, 61 00:04:16,130 --> 00:04:21,360 but maybe I did it with a plus instead of times. 62 00:04:21,360 --> 00:04:29,200 If I were to do test.testEqual square of two, 63 00:04:29,750 --> 00:04:32,670 I would still get this right. 64 00:04:32,670 --> 00:04:36,430 So, I've failed most of my test, 65 00:04:36,430 --> 00:04:40,660 but square of two came out to be four even though I did it wrong. 66 00:04:40,660 --> 00:04:45,070 So, two isn't really a great choice, or if I do two, 67 00:04:45,070 --> 00:04:46,835 I should also do something like three, 68 00:04:46,835 --> 00:04:52,800 that would distinguish between a correct implementation and an incorrect implementation. 69 00:04:53,710 --> 00:04:56,525 It's also worth thinking about 70 00:04:56,525 --> 00:05:01,670 return value test for functions that have optional parameters. 71 00:05:01,670 --> 00:05:04,220 If a function takes an optional parameter, 72 00:05:04,220 --> 00:05:06,800 one of the edge cases to test for is 73 00:05:06,800 --> 00:05:09,980 when no parameter value is supplied during execution. 74 00:05:09,980 --> 00:05:13,295 So, let's consider the built-in sorted function. 75 00:05:13,295 --> 00:05:17,605 You remember that it has an optional parameter reversed. 76 00:05:17,605 --> 00:05:20,550 So, I can call sorted of one, 77 00:05:20,550 --> 00:05:27,800 seven and four and not specify any value for the reverse parameter, it's optional. 78 00:05:27,800 --> 00:05:31,405 If I don't specify the reverse parameter at all, 79 00:05:31,405 --> 00:05:33,855 I should get the results not reversed. 80 00:05:33,855 --> 00:05:35,820 I should get one, four and seven. 81 00:05:35,820 --> 00:05:38,205 If I call sorted of one, seven, 82 00:05:38,205 --> 00:05:40,200 four with reverse equals true, 83 00:05:40,200 --> 00:05:42,620 then I should get the values in the opposite order, 84 00:05:42,620 --> 00:05:43,975 seven, four and one. 85 00:05:43,975 --> 00:05:47,200 So, I should pass both of these tests. 86 00:05:47,270 --> 00:05:49,840 Just to be complete, 87 00:05:49,840 --> 00:05:53,090 I might want to have one more test here, which is, 88 00:05:53,090 --> 00:05:55,805 what happens if I call sorted on one, 89 00:05:55,805 --> 00:06:01,875 seven and four, but I say reverse equals false. 90 00:06:01,875 --> 00:06:05,000 So, I've actually provided this parameter. 91 00:06:05,000 --> 00:06:08,570 I should get the same value that I would get if I left out that 92 00:06:08,570 --> 00:06:14,045 parameter entirely and just got the default value because the default value is false. 93 00:06:14,045 --> 00:06:16,595 So, this one should pass as well. 94 00:06:16,595 --> 00:06:21,420 Of course, if I changed any of these, 95 00:06:23,170 --> 00:06:26,245 seven, one and four, 96 00:06:26,245 --> 00:06:29,680 now I'm going to fail the second test. 97 00:06:29,680 --> 00:06:33,760 It said, we expected to get seven, one, four, 98 00:06:33,760 --> 00:06:36,635 this is what we specified was supposed to be the value, 99 00:06:36,635 --> 00:06:39,215 but we actually got seven, four, one. 100 00:06:39,215 --> 00:06:43,475 Now, in this case, we failed the test because I wrote a bad test. 101 00:06:43,475 --> 00:06:47,040 The correct answer when we pass one, seven, 102 00:06:47,040 --> 00:06:49,220 four to sorted with reverse equals true, 103 00:06:49,220 --> 00:06:53,220 the correct answer is seven, four, one. 104 00:06:55,420 --> 00:06:59,600 Now, we've passed it. In summary, 105 00:06:59,600 --> 00:07:02,510 you'll use a return value test when the purpose of 106 00:07:02,510 --> 00:07:05,765 a function is to compute an output from its inputs. 107 00:07:05,765 --> 00:07:09,260 You express the test by calling test.testEqual. 108 00:07:09,260 --> 00:07:11,915 The first parameter's an invocation of the function, 109 00:07:11,915 --> 00:07:13,645 the second is the correct output, 110 00:07:13,645 --> 00:07:15,665 which you had to compute manually. 111 00:07:15,665 --> 00:07:19,250 You should make one test case for each of the equivalence classes of 112 00:07:19,250 --> 00:07:22,925 inputs and don't forget the edge or extreme cases. 113 00:07:22,925 --> 00:07:26,904 When you're dealing with a function that has optional parameters, 114 00:07:26,904 --> 00:07:29,630 some of those edge or extreme cases should 115 00:07:29,630 --> 00:07:33,830 include: omitting or including the optional parameters. 116 00:07:33,830 --> 00:07:38,330 Now, the order of creating test cases is that you're going to create several of them. 117 00:07:38,330 --> 00:07:41,840 When you've correctly implemented the function that you're testing, 118 00:07:41,840 --> 00:07:44,620 you will pass all of the tests, 119 00:07:44,620 --> 00:07:48,185 but you want to have what's called good coverage of those tests. 120 00:07:48,185 --> 00:07:50,870 They need to cover all the ways in which you 121 00:07:50,870 --> 00:07:53,755 might make a mistake in implementing the function. 122 00:07:53,755 --> 00:07:57,005 So, if there was some error in the implementation of the function, 123 00:07:57,005 --> 00:07:59,090 then one of your tests ought to fail. 124 00:07:59,090 --> 00:08:01,400 But if the function is correctly implemented, 125 00:08:01,400 --> 00:08:03,380 it should pass all of the test. 126 00:08:03,380 --> 00:08:06,830 The order of this is to pick a good set of tests, 127 00:08:06,830 --> 00:08:10,790 so that you'll fail if the function is not implemented correctly, 128 00:08:10,790 --> 00:08:13,040 but you'll pass them all when the function is 129 00:08:13,040 --> 00:08:17,130 implemented correctly. I'll see you next time.