
Lesson Description
The "Testing CreateWorkout Success" Lesson is part of the full, Complete Go for Professional Developers course featured in this preview video. Here's what you'd learn in this lesson:
Melkey writes a test for the CreateWorkout function. The first test is for a valid workout. The data contains the correct workout details along with one entry.
Transcript from the "Testing CreateWorkout Success" Lesson
[00:00:00]
>> Melkey: So now that we have the setup test function, Go has a pretty cool feature that, you saw that this file has test at the end of its file name. This lets the Go tester, which we'll explore, identify that it's a test file. But now we wanna tell that tester, that Go's built-in, tester, what functions are actually tests.
[00:00:22]
And we can do this very simply by just writing a function with the word test in it. So we can do TestCreateWorkout, like so. It's going to take our fixture, t, testing.T, okay? It's not gonna return anything. And here is where we're going to define not only our TestDB, but we're also gonna define our Table tests here.
[00:00:44]
So first things first, go ahead and do setupTestDB(, pass it our fixture t, will defer db.Close, I don't have any loose connections. Or lingering connections, I think it's more appropriate. And here we can actually get the pool.PostgresWorkoutStore, the actual WorkoutStore we're using. We don't need to make a fake, we don't need to make a mock.
[00:01:04]
None of that, we're gonna use the real deal. What we're gonna use in production is what we're gonna use here in testing. And so the goal of testing for me is to get as close to the real deal as possible. So we have the store, new.PostgresWorkoutStore. And here we're gonna create our set of tests.
[00:01:22]
So we have this variable tests, we can declare it as a slice of structs, okay? And then we're gonna make sure we format the struct correctly. So again, the first curly brace is the fields identifying what that struck is, and the second set of curly braces fills in those fields, okay?
[00:01:40]
Again, this is an anonymous struct. So for our tests, every test needs a name. This helps us know what tests are failing, so, Name string. For this particular test, we're gonna be testing how to create a workout. We're gonna test workout, and there's gonna be a pointer to a workout, like so.
[00:01:59]
And then we want to see, do we want to check if this is going to error or not? We wanna check happy path, and the not-so-happy path. So, WantError, this is gonna be a boolean, like so. So here we have defined our anonymous struct. It has three fields, all of different types.
[00:02:15]
And then here, because our struct is going to be a slice of these structs, every entry in the second set of brackets needs to be separated by its own individual set of curly braces to. To identify one individual workout, or one individual entry in the struck. So for example, we can do our first workout as name, our first test.
[00:02:37]
And we can say, ValidWorkout. All right, that's gonna be the happy-path test. We do not expect this to fail, all right? We want this to work completely fine. And if it doesn't work, it's gonna identify something is wrong in our system. Here we'll do a workout, and it's going to be an address to workout.
[00:02:55]
Okay, and here we're gonna pull in the details for what work we wanna use. So these details, let's make sure we get them correct, So Title B, Push Day. All right, we'll do our description. We'll say upper body day. Duration in minutes, we'll make it 60. So one hour.
[00:03:14]
Calories burn, we can say something like 200. And then for entries, right, we know this is going to be a slice of our workout entry, like so. And again, because this is a slice, every entry in the workout entry slice needs to be defined with its own set of curly braces.
[00:03:32]
All right, so here we can define every entry in that workout. So here we can say, bench press, sets, we could say 3, all right? And now, here's gonna be a bit of a fall. So, reps, let's say I did 10 reps. There's gonna be an issue, right?
[00:03:50]
If I fix this, can I use 10 untyped in constant as pointer int value? Okay, so you may be thinking, let's just do something like this. That also doesn't work, right? So the issue here is because, if you remember, it's not kReps, excuse me, it's just Reps. The issue here is, if you remember, when we first started to create our WorkoutEntry, we determined that the type for reps and duration in seconds are gonna be pointers to ints.
[00:04:19]
And for Go, you can't just in place say that this 10 is going to be a address of 10, right? You have to declare a separate variable and then use that variable accordingly. You can extract the address of that variable. Now, what I'm going to do, just to help make this a little bit nicer, I'm gonna make a new function called func.
[00:04:43]
I'm gonna intPtr, so int pointer, it's gonna be (i int), and it's going to return a pointer to an int. And this is going to be simply a helper function that allows me to extract the address of whatever variable I pass into this. Okay, I'm gonna repeat this for a float.
[00:05:00]
So, instead of int pointer, oops, I'm gonna call this float pointer. And the argument is not long to be an int, it's gonna be a float 64. And the return is not gonna be a pointer int, it's gonna be a float 64 bit, like so. But continuing on, we're gonna do int pointer, I'm gonna pass 10, okay?
[00:05:19]
Then we do our weight. Again, weight is a pointer to a float 64 bits. So we're gonna floatPtr, I'm gonna put 135.5. And then here we'll do Notes, and here we'll write, Warm up properly, okay? And then the order index will make 1, okay? So we're not fully done yet, because we are missing one more field.
[00:05:44]
And do we want this to error? And since this is our valid test case, no, I'm gonna set WantError to false, okay?
>> Speaker 2: Since you're using a slice of test cases, would all tests run even if one fails?
>> Melkey: Will all tests run even if one fails? So, that is actually fully up to you.
[00:06:00]
I'll show you, and like, once we range over the tests, we use the fixture to run each individual test in our slice here. And if you explicitly face an unforeseen error, it stops it. So it does not continue. It just stops the flow of the error. But also it's up to you how you wanna handle it.
[00:06:21]
You can actually explicitly say to return, if you want a certain error or not. And I'll show you how that looks like.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops