1 00:00:00,000 --> 00:00:04,900 So one very good use of interfaces in go, is to make writing 2 00:00:04,900 --> 00:00:08,500 tests easy. If you can use an interface rather than a concrete 3 00:00:08,500 --> 00:00:12,500 type, then it turns out there makes mocking things in test 4 00:00:12,500 --> 00:00:16,700 extremely easy for you to do. For example, I've added to my shelter, a 5 00:00:16,700 --> 00:00:20,900 package, here, a function called read and shout, and what it 6 00:00:20,900 --> 00:00:24,400 does is it takes a file, obviously a concrete type 7 00:00:24,400 --> 00:00:28,500 reads every line of that file and then shouts them. So it will 8 00:00:28,500 --> 00:00:29,800 print them out or 9 00:00:30,000 --> 00:00:34,600 all in uppercase and I've changed the my program so that it 10 00:00:34,800 --> 00:00:38,500 accepts a file argument opens that file and then 11 00:00:38,500 --> 00:00:42,700 shouts it to stand out. So if we just go ahead and build that 12 00:00:43,600 --> 00:00:47,800 and then run it and I'll just shout food or go. I was it goes, line-by-line 13 00:00:47,800 --> 00:00:51,800 everything turns into upper case so no real surprise about what it does. Now 14 00:00:52,200 --> 00:00:56,800 if I run the tests for shout then I'm going to 15 00:00:56,800 --> 00:00:59,800 discover that I need to write some tests for read and 16 00:01:00,000 --> 00:01:04,700 Out and immediately I'm faced with the idea of okay well I need to create a temporary 17 00:01:04,700 --> 00:01:08,800 file and I can do that because the OS package provides a way to create temporary files. I need to make sure I 18 00:01:08,800 --> 00:01:12,900 delete it and you put something in the file. Sounds like a bit of a pain. When really what I 19 00:01:12,900 --> 00:01:16,800 want to do is test the basic functionality. And so the way to do 20 00:01:16,800 --> 00:01:20,600 that is to modify this so that it 21 00:01:20,600 --> 00:01:24,900 doesn't use a concrete type, he uses an interface and obviously the simplest interface for 22 00:01:24,900 --> 00:01:28,600 this is going to be an IO reader, and 23 00:01:28,600 --> 00:01:29,800 so we'll just do that. 24 00:01:30,300 --> 00:01:34,100 And now this is taking interface type and let's just build it. 25 00:01:36,400 --> 00:01:40,700 We no longer need less here because we're not doing it but we need IO 26 00:01:40,700 --> 00:01:44,200 because we're doing that and let's just check that it works. 27 00:01:45,400 --> 00:01:49,700 Okay, that works exactly the same. I didn't notice, I didn't change anything else in the program. If I go back to my program, 28 00:01:50,200 --> 00:01:54,900 I'm still passing in this file but because file is an IO reader. Then 29 00:01:55,000 --> 00:01:59,400 this works correctly. And this now means that the tests we can be made a little bit more easy. 30 00:01:59,700 --> 00:02:03,900 Now, it's gonna be a bit tricky to test this when this is printing to standard out. So I'm going to modify this a 31 00:02:03,900 --> 00:02:07,500 little bit more so it can return a string. 32 00:02:08,700 --> 00:02:12,400 And an error and will just gather up the 33 00:02:12,400 --> 00:02:16,800 response like this. So rather than printing it, I'm going to gather 34 00:02:16,800 --> 00:02:20,900 it like that. So now I've got the whole thing put together 35 00:02:21,200 --> 00:02:25,700 and I'm going to add back in those line feeds. 36 00:02:26,000 --> 00:02:30,900 I'm not going to need format anymore. And here I'm going to return the 37 00:02:30,900 --> 00:02:34,500 gathered string and the error like that 38 00:02:34,900 --> 00:02:37,700 at the other end. I'll just modify my program. 39 00:02:39,000 --> 00:02:40,300 Set a time print. 40 00:02:41,300 --> 00:02:42,300 Do this. So, 41 00:02:43,600 --> 00:02:47,000 Let's be a little bit naughty and ignore the error and just assume everything went. Well, 42 00:03:00,300 --> 00:03:06,100 as 43 00:03:06,100 --> 00:03:10,000 ever, we have to remember to import everything correctly because go is rather strict about 44 00:03:14,100 --> 00:03:18,500 Okay, so it works the same. So now I've got myself in a case where I think I can 45 00:03:18,900 --> 00:03:22,900 safely write a unit test for this and so in here before I would 46 00:03:22,900 --> 00:03:26,900 have had to get a file, save it right stuff to a deleted or sort of 47 00:03:26,900 --> 00:03:30,300 thing, but now I can just use a test string. So let's make myself a test string 48 00:03:31,200 --> 00:03:32,300 and this is going to be 49 00:03:34,000 --> 00:03:38,500 Something like this and I just need to know your reader. Well, let's look in the 50 00:03:39,600 --> 00:03:43,700 the strings package. There's this thing, 51 00:03:43,900 --> 00:03:47,900 a new reader function, which takes a string and returns an IO reader, so 52 00:03:47,900 --> 00:03:51,300 that's going to be perfect. So I'm going to bring in strings. 53 00:03:53,700 --> 00:03:57,700 I do that. So we're going to say and we're going to do read 54 00:03:57,700 --> 00:04:01,900 and Shout, I'm going to do it from strings 55 00:04:01,900 --> 00:04:05,900 new Reader test string, so that that will 56 00:04:05,900 --> 00:04:09,800 do what we wanted. That will actually do that, and it's going to reply with the string 57 00:04:09,800 --> 00:04:10,400 and error. 58 00:04:11,500 --> 00:04:15,200 Okay, so let's just make sure first of all we'll do make sure no errors that happened 59 00:04:16,100 --> 00:04:17,900 that happened. Then I'll see that's bad. 60 00:04:24,100 --> 00:04:28,900 That shouldn't happen. And then there's also the same thing about there being no lowercase, so let's just make 61 00:04:28,900 --> 00:04:31,300 sure that we do that. 62 00:04:37,000 --> 00:04:41,600 Okay, so read and Shout here, make two 63 00:04:41,600 --> 00:04:44,700 errors, make sure there's no lowercase in 64 00:04:45,500 --> 00:04:46,000 s. 65 00:04:48,200 --> 00:04:52,800 And therefore got a nice little test using, just this new reader here 66 00:04:52,800 --> 00:04:56,900 and let's just go test it. You got 67 00:04:56,900 --> 00:05:00,700 it, runs correctly. What's nice about that is you use the interface. Now, 68 00:05:00,700 --> 00:05:04,900 in this instance, I use one of the standard interfaces IR reader which is used all over the 69 00:05:04,900 --> 00:05:08,800 place, but you can also find this technique useful in your own programs. You may find 70 00:05:08,800 --> 00:05:12,600 that there's an instance where it's better to have an interface because in the test Suite, 71 00:05:12,600 --> 00:05:16,600 you can then Implement some dummy version of an object Robin 72 00:05:16,600 --> 00:05:18,000 instantiating some enormous. 73 00:05:18,200 --> 00:05:22,500 Thing. The other thing you can do is that if you limit it to just 74 00:05:22,500 --> 00:05:26,900 part of an interface, just the bits, you typically need. So for example, I O reader 75 00:05:26,900 --> 00:05:30,800 you only need that then you can have tests which don't have to create some 76 00:05:30,800 --> 00:05:34,200 gigantic object, some gigantic thing with all sorts of interfaces 77 00:05:34,200 --> 00:05:37,400 and that allows you to really focus in on what you want to mock.