1 00:00:06,550 --> 00:00:09,050 - So there's another kind of test in Go 2 00:00:09,050 --> 00:00:10,690 that a lot of people don't know about 3 00:00:10,690 --> 00:00:13,100 and they're called Example Tests. 4 00:00:13,100 --> 00:00:15,700 In fact, Examples serve two purposes, 5 00:00:15,700 --> 00:00:18,160 they help with providing examples 6 00:00:18,160 --> 00:00:21,490 in the Go documentation that your code is producing 7 00:00:21,490 --> 00:00:25,310 and for a test, so what I'm gonna show you here is 8 00:00:25,310 --> 00:00:28,210 I've added another file, another underscore 9 00:00:28,210 --> 00:00:32,350 test file to this project called handlers_example_test, 10 00:00:32,350 --> 00:00:36,910 and in here I've written a function called Example. 11 00:00:36,910 --> 00:00:40,590 Now, what's really interesting here and on this example 12 00:00:40,590 --> 00:00:44,680 is that there is no parameter being passed into it. 13 00:00:44,680 --> 00:00:47,040 We just start with the word example, 14 00:00:47,040 --> 00:00:50,070 and then again what we're gonna have here 15 00:00:50,070 --> 00:00:53,330 is something that we want to test, 16 00:00:53,330 --> 00:00:55,200 and because this is an example, 17 00:00:55,200 --> 00:00:59,490 what's gonna happen is is we've got to bind our example 18 00:00:59,490 --> 00:01:03,230 to an actual exported function in this package. 19 00:01:03,230 --> 00:01:06,770 So notice that I have a function here called SendJSON, 20 00:01:06,770 --> 00:01:10,150 this is now ExampleSendJSON. 21 00:01:10,150 --> 00:01:13,480 You know if I give this some other name, 22 00:01:13,480 --> 00:01:15,950 notice I've got some squiggly lines here, 23 00:01:15,950 --> 00:01:19,490 the Go linters identified that this example 24 00:01:19,490 --> 00:01:23,330 doesn't refer to some known exported thing 25 00:01:23,330 --> 00:01:25,970 inside the package, you see that golint 26 00:01:25,970 --> 00:01:28,620 is really trying to make sure that we do this, 27 00:01:28,620 --> 00:01:30,900 and this is because if it doesn't bind 28 00:01:30,900 --> 00:01:33,430 to something that's exported, it's not gonna show up 29 00:01:33,430 --> 00:01:35,070 in the GoDocs, so I'm gonna show you 30 00:01:35,070 --> 00:01:36,800 the GoDocs in a second. 31 00:01:36,800 --> 00:01:39,610 Now, if you're talking about a method, 32 00:01:39,610 --> 00:01:42,150 something like a method off of a type, 33 00:01:42,150 --> 00:01:44,690 then there's a naming convention 34 00:01:44,690 --> 00:01:47,110 where you're gonna be using a type name 35 00:01:47,110 --> 00:01:48,790 and an underscore for the method, 36 00:01:48,790 --> 00:01:52,760 so if this was a method off of some type, 37 00:01:52,760 --> 00:01:57,240 we'd be using the type name, and then we'd be 38 00:01:57,240 --> 00:02:00,090 using underscore to denote the method, 39 00:02:00,090 --> 00:02:03,180 golint will help you find in your way there. 40 00:02:03,180 --> 00:02:06,890 Okay, so notice it says ExampleSendJSON. 41 00:02:06,890 --> 00:02:08,880 What I'd like to do before we run this code 42 00:02:08,880 --> 00:02:10,630 and look at it is, look at something 43 00:02:10,630 --> 00:02:13,070 that's a little bit more, maybe real world, 44 00:02:13,070 --> 00:02:16,160 and I've moved over to the KIT pack, the KIT project 45 00:02:16,160 --> 00:02:17,500 that I have under ardanlabs 46 00:02:17,500 --> 00:02:20,650 and specifically looking at the log package. 47 00:02:20,650 --> 00:02:24,610 Now notice that in log I did do log_examples_test, 48 00:02:24,610 --> 00:02:26,750 this is my naming convention for examples 49 00:02:26,750 --> 00:02:28,120 when I want to split them. 50 00:02:28,120 --> 00:02:30,430 All you really need to do is have in it a 51 00:02:30,430 --> 00:02:32,050 test_test file. 52 00:02:32,050 --> 00:02:34,220 And you can see that this example 53 00:02:34,220 --> 00:02:38,480 is showing the user how to use the log API. 54 00:02:38,480 --> 00:02:41,030 Now, what I want to do is a couple of things here. 55 00:02:41,030 --> 00:02:43,830 Let's go ahead and run GoDoc. 56 00:02:43,830 --> 00:02:46,760 Now, to run GoDoc, I just type godoc 57 00:02:46,760 --> 00:02:51,253 and I tell it what part I wanted to listen on for http. 58 00:02:52,300 --> 00:02:55,970 By the way, this is great because what GoDoc does 59 00:02:55,970 --> 00:02:58,170 is able to read your Gopath and all of the 60 00:02:58,170 --> 00:03:00,890 source code on your machine and give you documentation. 61 00:03:00,890 --> 00:03:03,257 So look at what I've done here, I've said godoc-http:3000 62 00:03:06,400 --> 00:03:11,400 and if I come into my browser now and do localhost 3000, 63 00:03:13,000 --> 00:03:15,250 this might look familiar to you. 64 00:03:15,250 --> 00:03:17,380 In fact, if I go to 65 00:03:18,530 --> 00:03:21,030 if I go to golang.org 66 00:03:21,030 --> 00:03:23,240 right here, which is where we get documentation 67 00:03:23,240 --> 00:03:27,160 when we're online, looks pretty similar doesn't it? 68 00:03:27,160 --> 00:03:31,750 Yeah, because golang.org is really built around GoDoc, 69 00:03:31,750 --> 00:03:34,060 just with some modifications. 70 00:03:34,060 --> 00:03:38,900 Okay, and what's nice is I can click on Packages. 71 00:03:38,900 --> 00:03:42,030 So a lot of times I'm too cheap to buy internet 72 00:03:42,030 --> 00:03:45,570 on the airplanes, and I'm on airplanes all the time right, 73 00:03:45,570 --> 00:03:48,118 so when I need documentation, guess what I do? 74 00:03:48,118 --> 00:03:50,810 GoDoc on the command line and I don't need 75 00:03:50,810 --> 00:03:54,650 to worry about golang.org not being available to me. 76 00:03:54,650 --> 00:03:57,060 Now, what's also cool here is I've got a list 77 00:03:57,060 --> 00:03:58,530 of all of the packages, not just 78 00:03:58,530 --> 00:04:02,479 in the standard library, but also inside my Gopath, 79 00:04:02,479 --> 00:04:04,130 look at that, in my Gopath. 80 00:04:04,130 --> 00:04:06,060 Now the thing that stinks 81 00:04:06,060 --> 00:04:07,790 is they didn't give us a search feature. 82 00:04:07,790 --> 00:04:11,960 So, if I want to find that log package under Kit, 83 00:04:11,960 --> 00:04:14,290 I'm gonna have to start searching, 84 00:04:14,290 --> 00:04:17,530 so there's ardanlabs right there, 85 00:04:17,530 --> 00:04:19,780 and I've got a lot of stuff under ardanlabs, right 86 00:04:19,780 --> 00:04:22,100 that's all the Go training stuff here. 87 00:04:22,100 --> 00:04:26,210 This is the only thing that stinks about our GoDoc here 88 00:04:26,210 --> 00:04:28,190 is trying to find what you want 89 00:04:28,190 --> 00:04:30,760 'cause I've gotta use the browser search feature, 90 00:04:30,760 --> 00:04:34,610 but here's Kit and here is log. 91 00:04:34,610 --> 00:04:36,820 Now, you might find this interesting 92 00:04:36,820 --> 00:04:40,840 that there's some really nice looking documentation here. 93 00:04:40,840 --> 00:04:42,690 Look at that, Package log, 94 00:04:42,690 --> 00:04:44,690 where did all this documentation come from, 95 00:04:44,690 --> 00:04:46,720 where did all this overview come from? 96 00:04:46,720 --> 00:04:50,850 Look, the code you are writing is also documentation 97 00:04:50,850 --> 00:04:54,730 and anything that's exported, is coming out in the index, 98 00:04:54,730 --> 00:04:58,080 and any comments you put above anything that's exported, 99 00:04:58,080 --> 00:05:00,870 is going to be comments in the documentation. 100 00:05:00,870 --> 00:05:03,700 Look at this, and look what you see here. 101 00:05:03,700 --> 00:05:05,140 Example 102 00:05:05,140 --> 00:05:06,000 and what do you see? 103 00:05:06,000 --> 00:05:09,790 All the code I wrote inside the example function. 104 00:05:09,790 --> 00:05:12,970 So, here's some rules that I'm going to put in 105 00:05:12,970 --> 00:05:15,550 and what golint does is, well, 106 00:05:15,550 --> 00:05:17,870 every comment you write is code, 107 00:05:17,870 --> 00:05:21,370 not only is every comment code, it's documentation, 108 00:05:21,370 --> 00:05:25,390 and so comments must be proper sentences, 109 00:05:25,390 --> 00:05:28,130 grammar, punctuation, everything, 110 00:05:28,130 --> 00:05:30,690 and in a code review I am looking for that, 111 00:05:30,690 --> 00:05:32,000 because every comment you write, 112 00:05:32,000 --> 00:05:34,990 especially those above anything that's exported, 113 00:05:34,990 --> 00:05:37,030 show up here. 114 00:05:37,030 --> 00:05:40,260 Remember, your code is also documentation. 115 00:05:40,260 --> 00:05:45,000 Write clear, concise sentences, grammar, punctuation, 116 00:05:45,000 --> 00:05:46,690 the whole nine yards. 117 00:05:46,690 --> 00:05:49,490 and you can see how the example code 118 00:05:49,490 --> 00:05:51,450 that I wrote inside this function 119 00:05:51,450 --> 00:05:54,950 showed up in the Go documentation. 120 00:05:54,950 --> 00:05:57,950 And if we look at part of the API you see, 121 00:05:57,950 --> 00:06:01,630 this is why I write clear, concise, complete 122 00:06:01,630 --> 00:06:03,310 grammar type sentences. 123 00:06:03,310 --> 00:06:07,060 Now, I have a lot of overview in this documentation. 124 00:06:07,060 --> 00:06:08,390 When you're gonna have a lot of overview 125 00:06:08,390 --> 00:06:12,880 the best thing to do is head to doc.go file 126 00:06:12,880 --> 00:06:15,700 and what you're gonna is put all that overview 127 00:06:15,700 --> 00:06:18,630 documentation there above the package log. 128 00:06:18,630 --> 00:06:22,770 Any comments you put above package log becomes overview. 129 00:06:22,770 --> 00:06:25,700 And when you're gonna have a lot of it, like 40 lines of it, 130 00:06:25,700 --> 00:06:27,750 don't put it into a normal source code files, 131 00:06:27,750 --> 00:06:32,530 just do a doc.go, it all has to be about package log. 132 00:06:32,530 --> 00:06:35,690 And how you space things and indent things 133 00:06:35,690 --> 00:06:37,340 will show up as code blocks 134 00:06:37,340 --> 00:06:40,740 or sometimes even section headers. 135 00:06:40,740 --> 00:06:44,140 Okay, brilliant, so look at that, that is some really cool. 136 00:06:44,140 --> 00:06:47,850 So these example also become part of your documentation 137 00:06:47,850 --> 00:06:51,580 and golint will also try to help you make sure 138 00:06:51,580 --> 00:06:54,990 that your comments are there and they're gonna be useful 139 00:06:54,990 --> 00:06:58,640 from a documentation standpoint. 140 00:06:58,640 --> 00:07:00,490 But I started this with the idea 141 00:07:00,490 --> 00:07:04,290 that an example is also a test and I want to show you that. 142 00:07:04,290 --> 00:07:08,370 Notice how this example has at the bottom this output 143 00:07:08,370 --> 00:07:10,470 directive using a comment. 144 00:07:10,470 --> 00:07:13,490 What this means is that anything, any comment 145 00:07:13,490 --> 00:07:14,970 you now put at below, and you're gonna have 146 00:07:14,970 --> 00:07:17,010 multiple lines of comment here, 147 00:07:17,010 --> 00:07:20,340 is now what we expect to see from standard out. 148 00:07:20,340 --> 00:07:22,980 So anything in this example writes to standard out, 149 00:07:22,980 --> 00:07:25,200 we can now validate, think about this. 150 00:07:25,200 --> 00:07:28,030 You have example code in your documentation, 151 00:07:28,030 --> 00:07:29,170 if somebody comes to you and says, 152 00:07:29,170 --> 00:07:30,510 I don't know how to use it, you say 153 00:07:30,510 --> 00:07:34,580 dude, I've added examples to the GoDoc, just read it, 154 00:07:34,580 --> 00:07:37,530 but you've also validated that your examples work 155 00:07:37,530 --> 00:07:39,850 with every build of your source code. 156 00:07:39,850 --> 00:07:42,130 So if anybody copies and pastes that, 157 00:07:42,130 --> 00:07:43,830 you don't have to worry about them coming back and saying, 158 00:07:43,830 --> 00:07:45,050 hey, it's not working. 159 00:07:45,050 --> 00:07:47,100 No, no, no, no, I know it's working 160 00:07:47,100 --> 00:07:49,980 because that example produced this standard out, 161 00:07:49,980 --> 00:07:52,420 this output out of standard out and I tested it. 162 00:07:52,420 --> 00:07:55,600 So look at this, we're saying that ExampleSendJSON 163 00:07:55,600 --> 00:07:58,860 should always produce this JSON document. 164 00:07:58,860 --> 00:08:01,680 Now, let's go ahead and test that, right. 165 00:08:01,680 --> 00:08:03,563 Let's go and test that. 166 00:08:04,600 --> 00:08:07,350 So let's come in here, let's call our godoc for a second, 167 00:08:07,350 --> 00:08:10,260 we're still in handlers, I've got my example test, 168 00:08:10,260 --> 00:08:12,220 and what I want to do is say go test, 169 00:08:12,220 --> 00:08:15,100 but this time I'm gonna tell it to just run 170 00:08:15,100 --> 00:08:18,250 this ExampleSendJSON, 171 00:08:18,250 --> 00:08:21,610 and when I do that, it's just gonna say pass, okay, 172 00:08:21,610 --> 00:08:23,540 because the output's the same. 173 00:08:23,540 --> 00:08:24,820 So let me do the following. 174 00:08:24,820 --> 00:08:28,050 Let's pretend that this was the expected output. 175 00:08:28,050 --> 00:08:30,570 Just bill ardanlabs., we know it isn't, 176 00:08:30,570 --> 00:08:32,710 let's say that's what it was expected, 177 00:08:32,710 --> 00:08:35,720 now watch what happens when I run just Example. 178 00:08:35,720 --> 00:08:38,650 It says, hey Bill, you know you got this, 179 00:08:38,650 --> 00:08:41,670 this is what you got, but you wanted this. 180 00:08:41,670 --> 00:08:44,190 Hey, this test, this test fails. 181 00:08:44,190 --> 00:08:46,040 Oh, how brilliant is that? 182 00:08:46,040 --> 00:08:49,680 So I've got examples that show up in Go documentation 183 00:08:49,680 --> 00:08:52,060 with the idea that I can also validate 184 00:08:52,060 --> 00:08:54,130 that these examples work by testing 185 00:08:54,130 --> 00:08:57,110 what this example code outputs. 186 00:08:57,110 --> 00:09:00,320 So we can just fix this output now, there it is. 187 00:09:00,320 --> 00:09:02,020 Run it again, brilliant. 188 00:09:02,020 --> 00:09:04,730 My examples are now passing. 189 00:09:04,730 --> 00:09:06,990 So examples are really powerful. 190 00:09:06,990 --> 00:09:09,350 Now, you can't have an example as a test, 191 00:09:09,350 --> 00:09:12,730 examples don't have to be tests, by the way. 192 00:09:12,730 --> 00:09:15,240 When we were looking at my log, 193 00:09:15,240 --> 00:09:17,650 there was no output directive here, 194 00:09:17,650 --> 00:09:20,183 I was purely using it for documentation, 195 00:09:21,360 --> 00:09:23,440 but if you decide you want it to be a test, 196 00:09:23,440 --> 00:09:26,240 just remember that the output has to be consistent. 197 00:09:26,240 --> 00:09:29,060 So, if you've got output that changes based on 198 00:09:29,060 --> 00:09:31,450 what time it is, and where you are and things like that, 199 00:09:31,450 --> 00:09:33,830 you can't do this, we're not gonna change code 200 00:09:33,830 --> 00:09:35,720 to make sure that this test can do that, 201 00:09:35,720 --> 00:09:36,900 that's bad, right. 202 00:09:36,900 --> 00:09:38,840 Code is for the users, we've got to really focus 203 00:09:38,840 --> 00:09:41,210 on usability first, I don't want to add things 204 00:09:41,210 --> 00:09:43,660 to an API just to make it testable, 205 00:09:43,660 --> 00:09:46,150 but we can create APIs that are testable 206 00:09:46,150 --> 00:09:48,600 by focusing on the inputs and the outputs. 207 00:09:48,600 --> 00:09:50,440 But, here we are, here's an example 208 00:09:50,440 --> 00:09:52,890 that will show both in the Go documentation 209 00:09:52,890 --> 00:09:55,063 and we can run it as a test.