
Lesson Description
The "Testing CreateWorkout Errors" 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 adds two more workouts with invalid entries to test the error checking within the API. After the invalid cases are added, a for loop is used to run each test.
Transcript from the "Testing CreateWorkout Errors" Lesson
[00:00:00]
>> Melkey: So we have this happy path error, let's also create some not happy errors, right? Some paths that we want to error, these should be errors, right? We can see the name of this is going to be a workout with invalid entries. Okay, we can do the workout, is going to be workout like so.
[00:00:22]
And feel free to copy and paste the values from workout up here, like the tile description, duration, minutes, calories burned.
>> Melkey: If it makes it typing easier. So I'm gonna make the title as full body. I'll make description as complete workout, duration, we'll make it 90, and calories burned, we'll make it 500.
[00:00:48]
Doesn't truly matter. And here in the entries will be a slice of WorkoutEntry.
>> Melkey: Right, and here we'll have two entries to demonstrate it catching a potential problem. So here we'll make the exercise name, plank. Okay, we'll say this is just sets three, reps for a plank. We could do something like 60.
[00:01:20]
We could do notes and order index, so this should be fine.
>> Melkey: And this would be one.
>> Melkey: Cool, and then here we'll add another entry into the WorkoutEntries, and this is gonna have the constraint that we have. So let's go to exercise name, we'll say squats. Sets, we can set as 4.
[00:01:50]
Reps, we can do int pointer as 12. And then here we'll put duration in seconds. Now, if you remember, we can't have both reps and duration in seconds. We expect this to fail on us, right? So that's why this is gonna be a test case. We want to capture our error.
[00:02:06]
So duration in seconds would be an int pointer 60. We can do weight, it doesn't really matter, FloatPtr. Just put this as whatever value you want, 185.0. We can put notes as, Full depth, and OrderIndex 2. Okay, and one more thing, for this case, do we wantErr true?
[00:02:31]
>> Melkey: [COUGH]
>> Melkey: Cool, so now that we have the tests fully created,
>> Melkey: To make sure, right here, so outside of the slices of your test, we're actually gonna go through them individually. So we'll do 4, unless we can ignore the first variable in test case, in range of tests.
[00:03:01]
So the test we just created, we're gonna leverage our testing fixture. So we do test.run. We'll pass in the name of every individual test, we know what's currently running. And then we're gonna bring in an anonymous function. Okay, and this anonymous function is gonna be responsible for actually running the test that we are curious about, or that we want to know about, right?
[00:03:24]
So this func testing, so here, we can do createdWorkout error. Is going to be store.CreateWorkout, you can pass in tt.workout, like so. It's testing.t on the fixture.
>> Melkey: I forgot to add it last time. Okay, so here we can do if, our test case, if we want an error.
[00:03:46]
So if this is true, we expect store.CreateWorkout to in fact error out. So we can do assert, right, and we should actually bring in that assert package, cuz sometimes my LSP brings it in randomly. So it's github.com/ is going to be the stretcher package. So, stretcher slash testify, we can bring assert.
[00:04:15]
>> Melkey: Says I don't have it, so let's see.
>> Melkey: And we get to do slash assert.
>> Melkey: It's stretch. There you go. So here we can then use assert, okay, and since we expect this to be an error, we can do error.
>> Melkey: Okay, give me a second.
[00:04:45]
And with this error, we can just make sure that we pass in that texting fixture t, and then the error that we expect from the call of CreateWorkout, and then we can return. And so this explicit return will stop the test cases, right? We're gonna actually get out of the test cases here, or the test suite, okay?
[00:05:01]
So if If we don't want this to error, we expect this to be a happy case. So what we can do is require no error, okay? We can call it t, and then error. So this is gonna validate that error is none. Okay, so here, we require that no error.
[00:05:17]
And then here, we can just start asserting the fields we expect to have in our created workout. So here we can do assert equal, and pass in our t fixture, and here we can make the workout.title. We can make sure this matches created workout.Title, right? We can just copy and paste this a few times.
[00:05:39]
We could do title and description, so like, description, and then we could do something like, DurationMinutes.
>> Melkey: Like so, and DurationMinutes, right? So we're gonna make sure that whatever we're answering via created workout is, in fact, gonna be what we're inserting for the text case that we've assembled, okay?
[00:06:02]
And then one other thing I like to do is, because we have an actual database, we can actually also retrieve it. Since we created it, we know it's gonna exist in a database. Why, now we see what happens when we pull it out and does it still match the values that we want it to when we initially inserted it, right?
[00:06:16]
So here we can do something like retrieved error, is gonna be store.GetWorkoutByID, okay? And then we can cast the type, you can use in 64, we can cast the type using CreatedWorkout.ID, okay? So let's make sure, AcquireNoError NoError(t, and an error like so, to cover the error from GetWorkoutByID.
[00:06:42]
And in here we can do assert.Equal, pass in our t fixture, and we can do createdWorkout.ID. Matches the retrieved.CaloriesBurned the ID, like so. We can also assert.Equal, okay? And for all of these functions, it first expects the testing fixtures, that's why I'm passing in t continuously. You can also check that the length of tt.workout.Entries matches the length of retrieved.Entries, all right?
[00:07:16]
And this is pretty good, but we also wanna check the actual entries themselves. So here, for i entry in range retrieved entries, okay? Now we can iterate through every single entry that we have in our entry slice and see if they are in fact correct. So, one thing we can do is assert.Equal t, tt.Workout.Entry.
[00:07:43]
We can index it by i to get the specific one, ExerciseName matches the retrieved. I guess we also just do entry,
>> Melkey: Retrieved, not title, but retrieved.Entries. We can also index it at i, and can do, ExerciseName. And then can, if you want, just remove the entry here or use it.
[00:08:13]
>> Melkey: I think I personally like having this a little bit more explicit, just personally, with the iteration i using the index, but I'll leave that up to you. And then we can do this on a few more fields. So instead of ExerciseName, we can check something like sets, oops.
[00:08:34]
>> Melkey: Right, and we can also check another field like OrderIndex, for example. So here, GetSets.
>> Melkey: Here, OrderIndex. Interesting. So that's why I did v. So fatal f does not support error wrapping directive, module w, that's why I did v, Michael.
>> Micheal: I just noticed those OSP warnings.
[00:08:56]
>> Melkey: Yep, so the texting fixture, fatal f doesn't get the error wrapping module of format specifier. So we have to use the v, that's like a catch all, struct one.
>> Micheal: Okay.
>> Melkey: I knew there's a reason, but I don't think my LSP was, when you asked the question, I don't think it was pulling up.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops