1 00:00:06,730 --> 00:00:10,800 - Something that the language team added in Go 1.7 2 00:00:10,800 --> 00:00:15,230 was the concept of subtests and Marcelle who works 3 00:00:15,230 --> 00:00:18,680 for Google in the Switzerland office did all of this 4 00:00:18,680 --> 00:00:21,920 work and he did a amazing job with this. 5 00:00:21,920 --> 00:00:24,010 I wanna show you subtests in Go. 6 00:00:24,010 --> 00:00:27,140 They really, really help when we start looking 7 00:00:27,140 --> 00:00:29,573 at table tests because one of the things that we have 8 00:00:29,573 --> 00:00:31,440 with table tests is the ability 9 00:00:31,440 --> 00:00:33,840 to do this data-driven testing. 10 00:00:33,840 --> 00:00:36,470 But if we wanna just filter out one piece of data 11 00:00:36,470 --> 00:00:39,860 over the other, historically, we had to comment out 12 00:00:39,860 --> 00:00:41,890 the data which meant we had to go in 13 00:00:41,890 --> 00:00:43,800 and do some code changes. 14 00:00:43,800 --> 00:00:46,700 What our subtests are gonna let us do is filter 15 00:00:46,700 --> 00:00:49,530 a piece of data at the command line-level 16 00:00:49,530 --> 00:00:52,030 and I'm gonna also show you how we can run that 17 00:00:52,030 --> 00:00:54,940 table test in parallel, as well. 18 00:00:54,940 --> 00:00:58,000 Let's start with our test download function here. 19 00:00:58,000 --> 00:01:00,000 Our standard test download function using 20 00:01:00,000 --> 00:01:04,210 our standard table tests that we learned before. 21 00:01:04,210 --> 00:01:07,380 But, I added a new field to the table. 22 00:01:07,380 --> 00:01:08,840 It's called name. 23 00:01:08,840 --> 00:01:13,050 This is gonna give us the ability to name each piece of data 24 00:01:13,050 --> 00:01:15,520 and then filter things on the command line. 25 00:01:15,520 --> 00:01:18,610 I've called this the status OK test. 26 00:01:18,610 --> 00:01:22,220 This is the status not found subtest. 27 00:01:22,220 --> 00:01:24,920 Two subtests, same as before, but we've just added 28 00:01:24,920 --> 00:01:26,330 a name to it. 29 00:01:26,330 --> 00:01:28,180 Now, we're gonna say given the need to test 30 00:01:28,180 --> 00:01:31,470 download content, we're gonna range over our table, 31 00:01:31,470 --> 00:01:33,920 but here's another change that I made here. 32 00:01:33,920 --> 00:01:35,990 Here's another change. 33 00:01:35,990 --> 00:01:39,520 Notice that I've defined a literal function 34 00:01:39,520 --> 00:01:41,423 assigning it to the variable tf. 35 00:01:42,360 --> 00:01:46,330 Subtests run with the idea that every piece of data 36 00:01:46,330 --> 00:01:49,070 is bound to its own literal function, 37 00:01:49,070 --> 00:01:52,150 that's how we can execute these the way filter, 38 00:01:52,150 --> 00:01:54,370 and execute, and parallel. 39 00:01:54,370 --> 00:01:56,700 I've got my own literal testing functions. 40 00:01:56,700 --> 00:01:59,730 See, it takes the testing t pointer and I run the rest 41 00:01:59,730 --> 00:02:03,340 of the tests or define those tests in the literal function. 42 00:02:03,340 --> 00:02:07,940 When we use this data input, that expected data output, 43 00:02:07,940 --> 00:02:11,250 we do the get, we do the close, we check the status, 44 00:02:11,250 --> 00:02:14,270 we now have this literal test function tf. 45 00:02:14,270 --> 00:02:17,320 We range over that, but here's the key, 46 00:02:17,320 --> 00:02:19,600 is we now call t.Run. 47 00:02:19,600 --> 00:02:22,740 We give t.Run the name for this subtest 48 00:02:22,740 --> 00:02:25,130 and the function to execute. 49 00:02:25,130 --> 00:02:27,160 Then we iterate again and we do the next piece of data. 50 00:02:27,160 --> 00:02:29,830 Iterate again, and we do the next piece of data. 51 00:02:29,830 --> 00:02:31,560 How cool is this? 52 00:02:31,560 --> 00:02:36,300 I can now give each piece of data in my table test a name. 53 00:02:36,300 --> 00:02:40,210 Also, define it within its own path of execution really. 54 00:02:40,210 --> 00:02:43,560 It's own function, and then tell run to execute 55 00:02:43,560 --> 00:02:47,180 each individual literal function one at a time. 56 00:02:47,180 --> 00:02:50,590 Let's run this download test now. 57 00:02:50,590 --> 00:02:53,380 Already in our folder here. 58 00:02:53,380 --> 00:02:58,380 Go test, run, just test download minus v. 59 00:02:58,690 --> 00:03:00,750 Give me some verbosity. 60 00:03:00,750 --> 00:03:04,730 You can see that it found the subtest status OK. 61 00:03:04,730 --> 00:03:07,890 Status not found, and you can also see that 62 00:03:07,890 --> 00:03:11,400 it executed status OK, status not found. 63 00:03:11,400 --> 00:03:14,300 It executed it in series, one after the other. 64 00:03:14,300 --> 00:03:16,970 It took a full second to run this test, 65 00:03:16,970 --> 00:03:18,860 but guess what, how cool is that? 66 00:03:18,860 --> 00:03:22,000 Now, let's say I just wanted to run status OK. 67 00:03:22,000 --> 00:03:23,990 I can just come back over to run, 68 00:03:23,990 --> 00:03:26,680 say no, just run status OK. 69 00:03:26,680 --> 00:03:28,450 This is the cool part. 70 00:03:28,450 --> 00:03:33,210 Just run TestDownload/statusok. 71 00:03:33,210 --> 00:03:34,640 Now, I didn't have to go into my code 72 00:03:34,640 --> 00:03:37,573 and comment out any particular line in my table. 73 00:03:38,440 --> 00:03:41,090 The testing tool now knows just run that piece 74 00:03:41,090 --> 00:03:42,830 of data from the table test. 75 00:03:42,830 --> 00:03:44,690 Come on, this is really brilliant stuff. 76 00:03:44,690 --> 00:03:46,900 Marcelle's a brilliant engineer over at Google. 77 00:03:46,900 --> 00:03:48,980 We're so lucky to have him on the engineering team. 78 00:03:48,980 --> 00:03:51,500 He works on some really powerful stuff for us and this 79 00:03:51,500 --> 00:03:55,530 is something he spent a lot of time designing and building 80 00:03:55,530 --> 00:03:58,010 for us, and it's really great, brilliant stuff. 81 00:03:58,010 --> 00:04:01,010 Now, I wanna show you how now we can run all of this data 82 00:04:01,010 --> 00:04:04,600 in parallel when it's reasonable and practical to do so. 83 00:04:04,600 --> 00:04:07,010 What I've done is I've added another test function 84 00:04:07,010 --> 00:04:09,210 here called test parallelize. 85 00:04:09,210 --> 00:04:11,430 Really, it's structured almost identical. 86 00:04:11,430 --> 00:04:14,280 Here's our table, here is our name, 87 00:04:14,280 --> 00:04:16,750 here's our data bound to these names. 88 00:04:16,750 --> 00:04:20,220 Given the need to do this, we range over our table 89 00:04:20,220 --> 00:04:23,180 and we still have our function. 90 00:04:23,180 --> 00:04:26,020 We pass it to run, but look. 91 00:04:26,020 --> 00:04:28,340 This time the very first thing I do inside 92 00:04:28,340 --> 00:04:31,860 this literal function is called t.Parallel. 93 00:04:31,860 --> 00:04:34,620 What this tells the testing tool is run this 94 00:04:34,620 --> 00:04:37,710 as a separate or independent path of execution. 95 00:04:37,710 --> 00:04:39,520 Literally, run this on its own goroutine. 96 00:04:39,520 --> 00:04:41,510 Don't run it on the goroutine you're using 97 00:04:41,510 --> 00:04:46,510 right now, run it on a independent goroutine. 98 00:04:46,960 --> 00:04:49,460 Now, watch what happens when we run, 99 00:04:49,460 --> 00:04:50,960 test our parallelize. 100 00:04:50,960 --> 00:04:52,660 Remember, the first time we ran this test 101 00:04:52,660 --> 00:04:55,540 it took a full second to run. 102 00:04:55,540 --> 00:04:59,723 Let's run test parallelize and show me v. 103 00:05:00,680 --> 00:05:01,513 Boom. 104 00:05:01,513 --> 00:05:02,610 Look how fast it ran. 105 00:05:02,610 --> 00:05:06,920 It wasn't a second anymore, it's 113 milliseconds. 106 00:05:06,920 --> 00:05:07,753 Why? 107 00:05:07,753 --> 00:05:11,100 Because it ran these tests or this data in parallel 108 00:05:11,100 --> 00:05:13,710 against all the different cores that I have. 109 00:05:13,710 --> 00:05:16,070 Come on, this is really cool stuff. 110 00:05:16,070 --> 00:05:17,160 Very cool stuff. 111 00:05:17,160 --> 00:05:20,600 Subtests are fantastic when we've got these 112 00:05:20,600 --> 00:05:24,050 data-driven tests, because it's gonna allow us 113 00:05:24,050 --> 00:05:26,950 to not just be able to isolate on the command line 114 00:05:26,950 --> 00:05:28,760 one given piece of data over the other, 115 00:05:28,760 --> 00:05:30,940 but run all of this stuff in parallel, 116 00:05:30,940 --> 00:05:32,340 which means our unit tests 117 00:05:32,340 --> 00:05:35,003 can run faster in our CI service.