- Something that the language team added in Go 1.7
was the concept of subtests and Marcelle who works
for Google in the Switzerland office did all of this
work and he did a amazing job with this.
I wanna show you subtests in Go.
They really, really help when we start looking
at table tests because one of the things that we have
with table tests is the ability
to do this data-driven testing.
But if we wanna just filter out one piece of data
over the other, historically, we had to comment out
the data which meant we had to go in
and do some code changes.
What our subtests are gonna let us do is filter
a piece of data at the command line-level
and I'm gonna also show you how we can run that
table test in parallel, as well.
Let's start with our test download function here.
Our standard test download function using
our standard table tests that we learned before.
But, I added a new field to the table.
It's called name.
This is gonna give us the ability to name each piece of data
and then filter things on the command line.
I've called this the status OK test.
This is the status not found subtest.
Two subtests, same as before, but we've just added
a name to it.
Now, we're gonna say given the need to test
download content, we're gonna range over our table,
but here's another change that I made here.
Here's another change.
Notice that I've defined a literal function
assigning it to the variable tf.
Subtests run with the idea that every piece of data
is bound to its own literal function,
that's how we can execute these the way filter,
and execute, and parallel.
I've got my own literal testing functions.
See, it takes the testing t pointer and I run the rest
of the tests or define those tests in the literal function.
When we use this data input, that expected data output,
we do the get, we do the close, we check the status,
we now have this literal test function tf.
We range over that, but here's the key,
is we now call t.Run.
We give t.Run the name for this subtest
and the function to execute.
Then we iterate again and we do the next piece of data.
Iterate again, and we do the next piece of data.
How cool is this?
I can now give each piece of data in my table test a name.
Also, define it within its own path of execution really.
It's own function, and then tell run to execute
each individual literal function one at a time.
Let's run this download test now.
Already in our folder here.
Go test, run, just test download minus v.
Give me some verbosity.
You can see that it found the subtest status OK.
Status not found, and you can also see that
it executed status OK, status not found.
It executed it in series, one after the other.
It took a full second to run this test,
but guess what, how cool is that?
Now, let's say I just wanted to run status OK.
I can just come back over to run,
say no, just run status OK.
This is the cool part.
Just run TestDownload/statusok.
Now, I didn't have to go into my code
and comment out any particular line in my table.
The testing tool now knows just run that piece
of data from the table test.
Come on, this is really brilliant stuff.
Marcelle's a brilliant engineer over at Google.
We're so lucky to have him on the engineering team.
He works on some really powerful stuff for us and this
is something he spent a lot of time designing and building
for us, and it's really great, brilliant stuff.
Now, I wanna show you how now we can run all of this data
in parallel when it's reasonable and practical to do so.
What I've done is I've added another test function
here called test parallelize.
Really, it's structured almost identical.
Here's our table, here is our name,
here's our data bound to these names.
Given the need to do this, we range over our table
and we still have our function.
We pass it to run, but look.
This time the very first thing I do inside
this literal function is called t.Parallel.
What this tells the testing tool is run this
as a separate or independent path of execution.
Literally, run this on its own goroutine.
Don't run it on the goroutine you're using
right now, run it on a independent goroutine.
Now, watch what happens when we run,
test our parallelize.
Remember, the first time we ran this test
it took a full second to run.
Let's run test parallelize and show me v.
Boom.
Look how fast it ran.
It wasn't a second anymore, it's 113 milliseconds.
Why?
Because it ran these tests or this data in parallel
against all the different cores that I have.
Come on, this is really cool stuff.
Very cool stuff.
Subtests are fantastic when we've got these
data-driven tests, because it's gonna allow us
to not just be able to isolate on the command line
one given piece of data over the other,
but run all of this stuff in parallel,
which means our unit tests
can run faster in our CI service.