1 00:00:06,570 --> 00:00:08,130 - Alright, we're about to start learning 2 00:00:08,130 --> 00:00:10,650 how to write unit tests in Go. 3 00:00:10,650 --> 00:00:13,450 I love that unit tests are integrated 4 00:00:13,450 --> 00:00:16,510 into the Go programming language and into the tooling. 5 00:00:16,510 --> 00:00:19,330 And it's really a minimal solution, 6 00:00:19,330 --> 00:00:20,740 which is all you need, right? 7 00:00:20,740 --> 00:00:22,870 Minimize, reduce, and simplify. 8 00:00:22,870 --> 00:00:24,840 Now, there are third-party packages out there. 9 00:00:24,840 --> 00:00:26,840 GoConvey is probably my favorite, 10 00:00:26,840 --> 00:00:29,930 but I really want to avoid using third-party stuff, 11 00:00:29,930 --> 00:00:31,800 just because it adds extra dependencies 12 00:00:31,800 --> 00:00:33,290 and things to your code. 13 00:00:33,290 --> 00:00:35,220 So normally I'm not really a fan 14 00:00:35,220 --> 00:00:37,160 of bringing your third-party package in 15 00:00:37,160 --> 00:00:40,780 to provide some maybe stronger testing support, 16 00:00:40,780 --> 00:00:41,613 but you don't really need it. 17 00:00:41,613 --> 00:00:43,590 I'm gonna show you how it all works right now. 18 00:00:43,590 --> 00:00:47,007 But, Kevin Henney said this and I really love it. 19 00:00:47,007 --> 00:00:52,007 "A unit test is a test of behavior whose success or failure 20 00:00:53,327 --> 00:00:56,993 "is wholly determined by the correctness of the test 21 00:00:56,993 --> 00:01:01,030 "and the correctness of the unit under test." 22 00:01:01,030 --> 00:01:04,090 So, one thing we've really gotta validate and make sure 23 00:01:04,090 --> 00:01:06,380 is that our tests are adding value, 24 00:01:06,380 --> 00:01:09,950 and also that we're not over unit testing 25 00:01:09,950 --> 00:01:11,860 or under unit testing, this stuff's complicated, 26 00:01:11,860 --> 00:01:15,320 but we're gonna go over really the mechanics today. 27 00:01:15,320 --> 00:01:17,220 I'm gonna show you how I write unit tests, 28 00:01:17,220 --> 00:01:19,780 which isn't necessarily how you need to write unit tests, 29 00:01:19,780 --> 00:01:23,020 but I just want a team to be consistent 30 00:01:23,020 --> 00:01:24,610 because there's nothing more frustrating, 31 00:01:24,610 --> 00:01:27,600 when everybody's kind of doing things differently, 32 00:01:27,600 --> 00:01:29,680 and because you just have a minimal solution here, 33 00:01:29,680 --> 00:01:32,100 it's quite possible for that to happen. 34 00:01:32,100 --> 00:01:35,490 Alright, so we're gonna go through a basic unit test here. 35 00:01:35,490 --> 00:01:40,490 I'm gonna be using VSCode to show all this stuff off, 36 00:01:40,830 --> 00:01:42,540 and we're gonna start here. 37 00:01:42,540 --> 00:01:46,610 Now, there is a front-end called Go, 38 00:01:46,610 --> 00:01:48,790 and we've been using go build throughout the class. 39 00:01:48,790 --> 00:01:51,830 Today we're gonna start using go test quite a bit. 40 00:01:51,830 --> 00:01:54,160 We're also gonna be using go tool p prof, 41 00:01:54,160 --> 00:01:55,970 go tool trace, we're gonna start using more 42 00:01:55,970 --> 00:01:58,690 of the go tooling outside of just the compiler. 43 00:01:58,690 --> 00:02:02,390 And if you want to write tests, then your files 44 00:02:02,390 --> 00:02:04,990 have to be in an underscore test file. 45 00:02:04,990 --> 00:02:09,470 Remember Go is about convention over configuration, 46 00:02:09,470 --> 00:02:12,880 and we use this underscore test convention here 47 00:02:12,880 --> 00:02:15,770 to denote files that are gonna be really isolated 48 00:02:15,770 --> 00:02:18,560 just to the testing tool, which means that these files 49 00:02:18,560 --> 00:02:19,920 aren't going to be built and compiled 50 00:02:19,920 --> 00:02:22,330 into your production level binaries. 51 00:02:22,330 --> 00:02:24,750 Alright, but go test will run the compiler. 52 00:02:24,750 --> 00:02:26,800 We'll see some of that today. 53 00:02:26,800 --> 00:02:28,660 So, I've got my underscore test. 54 00:02:28,660 --> 00:02:32,340 Now, once you create an underscore test file, 55 00:02:32,340 --> 00:02:35,440 ideally that's going to be in the same package 56 00:02:35,440 --> 00:02:39,150 as your source code for your production level product 57 00:02:39,150 --> 00:02:40,830 whether it's that API or the binary, 58 00:02:40,830 --> 00:02:43,440 whatever you're building, and you're gonna have to either 59 00:02:43,440 --> 00:02:47,020 put the test inside the same package name, 60 00:02:47,020 --> 00:02:49,230 or a lot of times what we do, and I tend 61 00:02:49,230 --> 00:02:51,270 to do this more than not, is use 62 00:02:51,270 --> 00:02:55,420 the same underscore test convention for the package name. 63 00:02:55,420 --> 00:02:57,540 So why would you do one over the other? 64 00:02:57,540 --> 00:02:59,350 If you want to be able to write tests 65 00:02:59,350 --> 00:03:03,140 that hit the unexported API, you're gonna do this. 66 00:03:03,140 --> 00:03:05,870 You're gonna have just the same package name 67 00:03:05,870 --> 00:03:07,870 that the rest of the source code is in. 68 00:03:07,870 --> 00:03:10,760 If you want to write unit tests that are more tailored 69 00:03:10,760 --> 00:03:13,240 to how your users are gonna be using your API, 70 00:03:13,240 --> 00:03:15,230 which is what I really believe in, 71 00:03:15,230 --> 00:03:17,040 then you're gonna want to do this. 72 00:03:17,040 --> 00:03:19,270 Go allows this files to kind of exist 73 00:03:19,270 --> 00:03:20,940 in their own package, even though 74 00:03:20,940 --> 00:03:23,070 they're in the same folder, and then, 75 00:03:23,070 --> 00:03:24,790 you have to import your package 76 00:03:24,790 --> 00:03:27,510 like anyone else does and work with the API. 77 00:03:27,510 --> 00:03:30,180 Now, what happens to me a lot of times is 78 00:03:30,180 --> 00:03:33,160 I'm writing a new package let's say, right, 79 00:03:33,160 --> 00:03:36,790 and I'm starting with the unexported API quite a bit, 80 00:03:36,790 --> 00:03:39,920 so I might start writing unit tests with this 81 00:03:39,920 --> 00:03:43,240 because I want to start testing the unexported API, 82 00:03:43,240 --> 00:03:46,610 but eventually when I get to the exported API 83 00:03:46,610 --> 00:03:49,540 that's using the unexported API, 84 00:03:49,540 --> 00:03:52,780 I could start ripping out the unexported tests 85 00:03:52,780 --> 00:03:55,190 and just keep the exported tests, 86 00:03:55,190 --> 00:03:57,160 and then eventually end up here. 87 00:03:57,160 --> 00:03:59,300 I don't get hung up writing tests 88 00:03:59,300 --> 00:04:01,490 that I might throw away later on 89 00:04:01,490 --> 00:04:03,930 because I want to make sure as I'm coding 90 00:04:03,930 --> 00:04:06,090 that my code is working all the way through. 91 00:04:06,090 --> 00:04:08,210 I don't consider that a waste of time. 92 00:04:08,210 --> 00:04:10,890 I actually consider it a way of being more productive. 93 00:04:10,890 --> 00:04:13,280 So, during the course of my development, 94 00:04:13,280 --> 00:04:16,520 I probably have a lot more unexported tests 95 00:04:16,520 --> 00:04:17,810 that eventually get thrown out 96 00:04:17,810 --> 00:04:20,440 because the exported tests then give me 97 00:04:20,440 --> 00:04:22,830 the same code coverage that I need. 98 00:04:22,830 --> 00:04:23,960 You gotta find your workflow. 99 00:04:23,960 --> 00:04:26,080 That's my workflow right there, 100 00:04:26,080 --> 00:04:27,070 and I always want to make sure 101 00:04:27,070 --> 00:04:31,313 that those unexported APIs are very very testable. 102 00:04:32,730 --> 00:04:37,730 We want to make sure the exported APIs are very very usable. 103 00:04:37,990 --> 00:04:40,140 So, it's a really interesting balance. 104 00:04:40,140 --> 00:04:41,510 These are my philosophies. 105 00:04:41,510 --> 00:04:45,440 So let's just start with this very basic unit test in Go. 106 00:04:45,440 --> 00:04:46,980 I've got the underscore test file. 107 00:04:46,980 --> 00:04:50,120 I got package example, which is the name of the folder, 108 00:04:50,120 --> 00:04:53,620 and I'm gonna show you again what I do for unit testing. 109 00:04:53,620 --> 00:04:54,920 You don't have to do all of this. 110 00:04:54,920 --> 00:04:57,750 I'm a little crazy, I like the verbosity of tests 111 00:04:57,750 --> 00:04:58,620 because when they run in the CI, 112 00:04:58,620 --> 00:05:00,770 I'd like to have a lot of information. 113 00:05:00,770 --> 00:05:04,010 I'm really about not hiding information, right? 114 00:05:04,010 --> 00:05:06,710 So I've defined these two constants, 115 00:05:06,710 --> 00:05:09,850 which are these unicode characters for x and check. 116 00:05:09,850 --> 00:05:13,100 You'll see how I use those, and the big thing here 117 00:05:13,100 --> 00:05:15,230 is having a function named test. 118 00:05:15,230 --> 00:05:17,520 So you can see here that this function starts 119 00:05:17,520 --> 00:05:19,900 with the word test and it's exported. 120 00:05:19,900 --> 00:05:22,940 It is critical that this function is exported 121 00:05:22,940 --> 00:05:25,260 or the testing tool will not find it. 122 00:05:25,260 --> 00:05:28,400 It is also critical that whatever you name the test, 123 00:05:28,400 --> 00:05:30,970 which is what comes after the word test, 124 00:05:30,970 --> 00:05:33,770 okay, starts with a capital letter. 125 00:05:33,770 --> 00:05:36,710 If you do this, the testing tool will not find 126 00:05:36,710 --> 00:05:39,450 this test function, you will go crazy. 127 00:05:39,450 --> 00:05:44,450 Now some people like using an underscore here. 128 00:05:45,660 --> 00:05:47,410 I'm not a big fan of that because 129 00:05:47,410 --> 00:05:50,520 we don't really write functions like that in Go. 130 00:05:50,520 --> 00:05:52,930 There is some conventions around examples 131 00:05:52,930 --> 00:05:57,930 that I will show you, where that might become important, 132 00:05:58,010 --> 00:05:59,300 but overall, I don't do that. 133 00:05:59,300 --> 00:06:00,240 It doesn't mean it's wrong. 134 00:06:00,240 --> 00:06:02,020 If you want to do that, that's fine. 135 00:06:02,020 --> 00:06:04,750 The tester will still find these test functions, 136 00:06:04,750 --> 00:06:06,640 but you're not gonna see me doing it. 137 00:06:06,640 --> 00:06:08,850 Okay, the other big thing is not only does it have 138 00:06:08,850 --> 00:06:10,630 to start with test, with a capital t, 139 00:06:10,630 --> 00:06:13,230 and the next letter has to be capital or underscore, 140 00:06:14,450 --> 00:06:17,120 is got to accept a testing t pointer. 141 00:06:17,120 --> 00:06:19,810 That's your integration into the testing tool, 142 00:06:19,810 --> 00:06:20,860 the t pointer. 143 00:06:20,860 --> 00:06:25,830 Now, the t pointer has the API that we're gonna need to use. 144 00:06:25,830 --> 00:06:29,030 And if I just quickly just talk about the API, 145 00:06:29,030 --> 00:06:30,980 you can see that we've got functions called error 146 00:06:30,980 --> 00:06:35,040 and fail and fatal and log and some other things here, 147 00:06:35,040 --> 00:06:38,630 and we're gonna focus on what this API is doing, 148 00:06:38,630 --> 00:06:42,010 but basically, the log function is a way 149 00:06:42,010 --> 00:06:45,280 of adding verbosity into your test. 150 00:06:45,280 --> 00:06:47,220 It doesn't mean whether tests succeed or fail. 151 00:06:47,220 --> 00:06:49,690 It's just extra tracing information. 152 00:06:49,690 --> 00:06:52,490 You're gonna see me using error, and error is gonna mean 153 00:06:52,490 --> 00:06:54,110 that we're gonna log some information, 154 00:06:54,110 --> 00:06:56,870 but the test is now marked as failed, 155 00:06:56,870 --> 00:06:59,550 but we keep executing any code left 156 00:06:59,550 --> 00:07:02,430 inside that test function, and then you're gonna see 157 00:07:02,430 --> 00:07:05,730 me using fatal and what fatal's gonna say is 158 00:07:05,730 --> 00:07:08,860 hey, this test is failed, and guess what, we're done. 159 00:07:08,860 --> 00:07:10,430 There's no reason to run anything else 160 00:07:10,430 --> 00:07:12,360 because we're in such a bad state 161 00:07:12,360 --> 00:07:14,230 that anything else is now irrelevant. 162 00:07:14,230 --> 00:07:17,080 So you're gonna see me use these three functions, 163 00:07:17,080 --> 00:07:19,360 error, log, and fatal, and then we'll use 164 00:07:19,360 --> 00:07:21,570 some of the other API as we get there. 165 00:07:21,570 --> 00:07:24,790 Now the whole idea of a unit test is to validate 166 00:07:24,790 --> 00:07:27,530 that something is working, right? 167 00:07:27,530 --> 00:07:29,910 Normally, we're gonna validate 168 00:07:29,910 --> 00:07:31,560 that some API that you've written, 169 00:07:31,560 --> 00:07:33,150 whether it's exported or unexported, 170 00:07:33,150 --> 00:07:36,010 is behaving, that if I give it this input, 171 00:07:36,010 --> 00:07:38,110 it produces this sort of output. 172 00:07:38,110 --> 00:07:39,470 We're trying to unit test 173 00:07:39,470 --> 00:07:41,800 the expected behavior of things, right? 174 00:07:41,800 --> 00:07:45,880 The semantics of what we expect this API to do. 175 00:07:45,880 --> 00:07:49,740 That is what we're trying to unit test all the time. 176 00:07:49,740 --> 00:07:51,730 So, look at what I'm gonna do here. 177 00:07:51,730 --> 00:07:55,480 I want to unit test the HTTP get call. 178 00:07:55,480 --> 00:07:57,490 I want to validate that the semantics 179 00:07:57,490 --> 00:08:01,180 of the get call are working, and so, what I do 180 00:08:01,180 --> 00:08:03,340 is I set up some basic input here. 181 00:08:03,340 --> 00:08:06,060 We're gonna use this URL, which is the URL 182 00:08:06,060 --> 00:08:10,160 to the RSS feed for my blog, and we're gonna expect 183 00:08:10,160 --> 00:08:12,910 to always get back a 200, right? 184 00:08:12,910 --> 00:08:15,860 Http code 200 every time I call it. 185 00:08:15,860 --> 00:08:19,820 Now I like the idea of given, when, should 186 00:08:19,820 --> 00:08:22,370 when I'm writing unit tests, and given is 187 00:08:22,370 --> 00:08:24,500 why we're writing this test to begin with, 188 00:08:24,500 --> 00:08:27,980 when is what data we're using for the test, 189 00:08:27,980 --> 00:08:30,230 and should is what should happen. 190 00:08:30,230 --> 00:08:33,040 And I like to break this given, when, should 191 00:08:33,040 --> 00:08:35,910 into three different blocks of code. 192 00:08:35,910 --> 00:08:39,460 So you see me use an artificial code block here. 193 00:08:39,460 --> 00:08:40,990 You see me using the curly brackets 194 00:08:40,990 --> 00:08:42,410 that defines another level of scope, 195 00:08:42,410 --> 00:08:45,480 but for me it's a readability marker 196 00:08:45,480 --> 00:08:47,540 that this is the given section, 197 00:08:47,540 --> 00:08:49,900 and you can have multiple given sections 198 00:08:49,900 --> 00:08:52,450 in a test function if that's how you want to organize it. 199 00:08:52,450 --> 00:08:55,120 But given the need to test downloading content, 200 00:08:55,120 --> 00:08:57,670 when, so we're doing the next block, 201 00:08:57,670 --> 00:09:02,070 when we use this URL expecting this status code, 202 00:09:02,070 --> 00:09:05,020 our inputs and sometimes our expected outputs, 203 00:09:05,020 --> 00:09:07,910 you can also see I've labeled the test as test zero. 204 00:09:07,910 --> 00:09:10,170 I'm using some tabbing, you'll see the output in a second. 205 00:09:10,170 --> 00:09:12,410 And then we start doing the test code, 206 00:09:12,410 --> 00:09:14,172 and you want to make sure this code 207 00:09:14,172 --> 00:09:18,240 is really as close to how you would write production code, 208 00:09:18,240 --> 00:09:21,670 but also more importantly, if a function fails, 209 00:09:21,670 --> 00:09:24,193 like there's an error, you gotta check your errors here. 210 00:09:24,193 --> 00:09:26,650 I don't want to see blank identifiers 211 00:09:26,650 --> 00:09:27,960 being used in your test code. 212 00:09:27,960 --> 00:09:30,500 You're going to get in trouble when you do that. 213 00:09:30,500 --> 00:09:32,200 So you've gotta check those errors, 214 00:09:32,200 --> 00:09:34,000 and make it part of the should. 215 00:09:34,000 --> 00:09:36,120 Now I like consistency in output, 216 00:09:36,120 --> 00:09:38,150 so whether it succeeds or fails, 217 00:09:38,150 --> 00:09:41,500 I want to really try to see the same exact message. 218 00:09:41,500 --> 00:09:43,620 Yes, there's a little duplication here. 219 00:09:43,620 --> 00:09:44,870 I told you, I'm crazy, okay. 220 00:09:44,870 --> 00:09:47,060 There is a little duplication here. 221 00:09:47,060 --> 00:09:48,560 Not a lot of people will do this. 222 00:09:48,560 --> 00:09:49,500 I like doing it. 223 00:09:49,500 --> 00:09:52,220 I like consistency in that final output. 224 00:09:52,220 --> 00:09:56,170 It helps with readability when things are going wrong. 225 00:09:56,170 --> 00:09:57,340 This is why I like it. 226 00:09:57,340 --> 00:09:59,070 So, we should be able to make the call 227 00:09:59,070 --> 00:09:59,903 without an error, right? 228 00:09:59,903 --> 00:10:01,170 We should be able to make the call, 229 00:10:01,170 --> 00:10:03,640 whether it failed or succeeded we'll find out. 230 00:10:03,640 --> 00:10:05,390 You'll see that that's being placed right there 231 00:10:05,390 --> 00:10:06,530 in the beginning of the output. 232 00:10:06,530 --> 00:10:08,160 I'll show you that, and if there's an error 233 00:10:08,160 --> 00:10:10,763 we're also going to show what that error was. 234 00:10:11,690 --> 00:10:14,720 Now we're using fatal here because if that fails, 235 00:10:14,720 --> 00:10:16,710 there's no reason to do anything else, 236 00:10:16,710 --> 00:10:19,860 but if it doesn't fail, then we'll defer the closed body, 237 00:10:19,860 --> 00:10:21,770 just like we would do in any normal piece 238 00:10:21,770 --> 00:10:24,550 of code calling get, and then we can do our checks. 239 00:10:24,550 --> 00:10:27,040 In this case, I'm checking that the status code 240 00:10:27,040 --> 00:10:29,730 we got back is the 200 that we expect. 241 00:10:29,730 --> 00:10:32,620 And now you're seeing my pattern for when there's an error. 242 00:10:32,620 --> 00:10:35,350 This is my pattern for fatal, where again, 243 00:10:35,350 --> 00:10:36,610 we're always gonna use that if statement 244 00:10:36,610 --> 00:10:39,100 for that negative case, so fatal we're done, 245 00:10:39,100 --> 00:10:41,440 or we could just log, but since with errors 246 00:10:41,440 --> 00:10:43,260 we're gonna keep going, we have to use 247 00:10:43,260 --> 00:10:45,040 the if else in this case. 248 00:10:45,040 --> 00:10:48,110 So, now I'm testing the positive case here. 249 00:10:48,110 --> 00:10:51,060 If it does succeed, then we should get the success, 250 00:10:51,060 --> 00:10:54,220 else on the failure side, we should see failure. 251 00:10:54,220 --> 00:10:56,710 Okay, so I've got a test here. 252 00:10:56,710 --> 00:10:58,630 So what I'm gonna do is I've already moved 253 00:10:58,630 --> 00:11:00,743 into this local directory here. 254 00:11:01,950 --> 00:11:04,650 I've already moved into this local directory here. 255 00:11:04,650 --> 00:11:08,120 You see the example one underscore test, 256 00:11:08,120 --> 00:11:09,153 so let's just look run through the tests 257 00:11:09,153 --> 00:11:10,960 through a couple of little different ways, 258 00:11:10,960 --> 00:11:14,510 so you can see how we're using this basic test. 259 00:11:14,510 --> 00:11:18,870 So I can just say go test, nothing less nothing more, 260 00:11:18,870 --> 00:11:21,010 and since everything is passing, 261 00:11:21,010 --> 00:11:23,270 all it does say is pass, and it shows you 262 00:11:23,270 --> 00:11:27,990 that it took almost 900 milliseconds to run the test. 263 00:11:27,990 --> 00:11:30,020 But what if I want to see the output of this test 264 00:11:30,020 --> 00:11:31,550 even though it's succeeding? 265 00:11:31,550 --> 00:11:33,390 I could use minus v, 266 00:11:33,390 --> 00:11:36,070 and minus v is giving me that verbosity. 267 00:11:36,070 --> 00:11:38,380 And now you can see why I've kind of structured 268 00:11:38,380 --> 00:11:41,120 the output of my test the way I did. 269 00:11:41,120 --> 00:11:44,040 Look at that, it says given the need, test zero 270 00:11:44,040 --> 00:11:47,520 when we use this data, you see the check marks. 271 00:11:47,520 --> 00:11:49,470 I mean, for me this is really nice, right? 272 00:11:49,470 --> 00:11:52,240 And if you were to bring in some third-party packages 273 00:11:52,240 --> 00:11:54,670 for this, they'd give you output that's kind of similar, 274 00:11:54,670 --> 00:11:56,930 and I'm showing you here how we could do it ourselves 275 00:11:56,930 --> 00:11:58,510 with really minimal work. 276 00:11:58,510 --> 00:12:01,790 It just takes a little bit of consistency by the whole team. 277 00:12:01,790 --> 00:12:04,250 So we've got that right there as well. 278 00:12:04,250 --> 00:12:06,240 Now, another thing I can do, 279 00:12:06,240 --> 00:12:08,710 let's just cause this test to just fail. 280 00:12:08,710 --> 00:12:10,610 This is an artificial failure here, right? 281 00:12:10,610 --> 00:12:13,450 Line 32, I'm gonna say not equals, 282 00:12:13,450 --> 00:12:16,510 and what I'm gonna do, let's not even do that. 283 00:12:16,510 --> 00:12:19,370 Let's change, let's say we were expecting 284 00:12:19,370 --> 00:12:21,401 to get a 400 back, okay. 285 00:12:21,401 --> 00:12:23,270 We're getting expecting to get a 400 back. 286 00:12:23,270 --> 00:12:24,300 Now what's gonna happen? 287 00:12:24,300 --> 00:12:25,650 Well, let me clear it. 288 00:12:25,650 --> 00:12:30,200 If I just run go test now, notice that when the test fails, 289 00:12:30,200 --> 00:12:33,290 it switches into verbosity mode automatically. 290 00:12:33,290 --> 00:12:35,370 Didn't have to do the minus v. 291 00:12:35,370 --> 00:12:37,810 That's really nice because then when things are passing, 292 00:12:37,810 --> 00:12:39,460 our output will be really clean. 293 00:12:39,460 --> 00:12:42,090 There's no noise there, and then when something fails, 294 00:12:42,090 --> 00:12:44,780 we get all of that work we did for the verbosity, 295 00:12:44,780 --> 00:12:47,150 and this is exactly what I want you to see. 296 00:12:47,150 --> 00:12:49,440 You know, you see how here visually it says x, 297 00:12:49,440 --> 00:12:52,737 hey this one failed, we were expecting a 400, 298 00:12:53,660 --> 00:12:55,470 we got back a 200. 299 00:12:55,470 --> 00:12:58,060 So, I'm trying to really make sure that the test output 300 00:12:58,060 --> 00:13:00,750 gives us a very clear indication of what's going on. 301 00:13:00,750 --> 00:13:02,150 It even tells us the line code, 302 00:13:02,150 --> 00:13:04,630 line 35, on where that failed. 303 00:13:04,630 --> 00:13:07,160 So, this is really really nice stuff. 304 00:13:07,160 --> 00:13:10,020 This is our basic testing here. 305 00:13:10,020 --> 00:13:12,930 Now Go also has on here, you're gonna see me use 306 00:13:12,930 --> 00:13:15,760 a minus run flag, and what's nice 307 00:13:15,760 --> 00:13:20,760 about the minus run flag is it uses a regular expression 308 00:13:20,800 --> 00:13:22,640 to be able to filter the test functions 309 00:13:22,640 --> 00:13:24,200 that you just want to run. 310 00:13:24,200 --> 00:13:27,970 So, I can just say run anything that starts with down, 311 00:13:27,970 --> 00:13:31,430 and you can see that it found test download, 312 00:13:31,430 --> 00:13:34,290 which is pretty cool, so how you name functions too 313 00:13:34,290 --> 00:13:37,160 will be able to filter out what functions you want 314 00:13:37,160 --> 00:13:40,950 in an entire test suite by using that run function. 315 00:13:40,950 --> 00:13:43,270 So this is our basic unit test. 316 00:13:43,270 --> 00:13:45,290 I've shown you some of the command line options 317 00:13:45,290 --> 00:13:47,140 that we have already. 318 00:13:47,140 --> 00:13:49,550 It's gonna be up to you about how consistent 319 00:13:49,550 --> 00:13:51,370 and how much verbosity you want, 320 00:13:51,370 --> 00:13:53,883 but I love just this basic API.