Review failing feature test0:00
Alright, let's get back to work. At this point, we know that when a User earns experience, we do fire a custom event, userEarnedExperience. So now, we can potentially hook into this and check, well, how many points does the User have? Should we award a badge? Anything like that. Alright, but still, if we come back to our main feature test, it is failing. So we create a world, we award a User enough points to earn a badge, but then when we check this relationship here, of course, it doesn't yet exist, so our test is currently failing.
Start Achievements unit test0:24
So we create a world, we award a User enough points to earn a Badge, but then when we check this relationship here, of course, it doesn't yet exist, so our test is currently failing. So I think we'll move on to this next step here. It sounds like I do need an achievements table. But what I currently have is kind of an outside-in feature test. Whenever I need to test a model specifically, I put that either within a unit folder or an integration folder, whatever you want. So let's whip up a new test here. I'm going to call it AchievementsTest again. Maybe we'll change the feature test name to be something a little more descriptive.
I'm going to call it achievementsTest again. Maybe we'll change the feature test name to be something a little more descriptive. But this will be a unit test. And again, whether you call it a unit test or an integration test, you know, people disagree. I don't think at the end of the day it matters that much. So how about it has a name? So every Achievement needs to have a name associated with it. So as part of this, we're going to test our migration. So I'm going to use php artisan migrate:refresh. And then we'll say whip up a Achievement.
So I'm going to use php artisan migrate:refresh. And then we'll say whip up a Achievement. So it sounds like we're going to need a new Eloquent model where the name is someBadge. All right, so we'll save that. And then we can say this->assertEquals(someBadge, $achievement->name) is what we'll call it. Okay, so let's give this a run. And it does fail. So we're unable to locate a factory for this Achievement model. And of course not, it doesn't yet exist.
Create model factory1:44
So we're unable to locate a factory for this Achievement model. And of course not, it doesn't yet exist. Now as of Laravel 5.5 or 6, I can't remember, but there is a make:factory builder here. So let's call it AchievementsFactory, or Achievement, you know, whether you do plural or not. Everyone, everyone differs. All right, so now we have our AchievementFactory. It's just a fancy name for quickly whipping up the blueprint. All right, so this will be an Achievement class. Again, it doesn't yet exist.
All right, so this will be an Achievement class. Again, it doesn't yet exist. And Achievement to start consists of a name. And that will just be a faker word. That's fine. So we'll give that another run. But it still fails. And that's because I assume the Achievement class doesn't exist. So let's whip up a model here for the Achievement. All right, and now we can use it.
Add achievements migration2:29
So let's whip up a model here for the Achievement. All right, and now we can use it. Like so. All right, give it another run. Okay, so now we have changed the error. Base table or view not found. Fair enough. We don't have a migration. So let's make a migration called create_achievements_table. And the table we're creating is called achievements.
So let's make a migration called create_achievements_table. And the table we're creating is called achievements. All right. So here, to begin, we're going to have a string for name. And I'll give it another run. There we go. Now it's passing. So if we switch back to our achievements_test, yeah, I mean, we can just continue on. Okay, what else should a Badge have? Well, a Badge consists of a name.
Add description and icon3:14
Okay, what else should a Badge have? Well, a Badge consists of a name. What else? Well, you'll remember we have that achievements test where we kind of outlined this together. It has a description and it also has an associated icon or the path to the icon. Okay, so let's say it has a description. And we'll say foobar description. And then update this. All right, let's run that one. Okay, it fails.
All right, let's run that one. Okay, it fails. That column does not exist. All right, we switch back to our migration. We'll add another one here. This can be, we'll do text to start, but we may not need that much description. Run it again. And now we do get green. Okay, but also while we are here, let's go to our AchievementFactory and add one for the description.
Okay, but also while we are here, let's go to our AchievementFactory and add one for the description. That can be a sentence. Okay. What else? We said one more, it has an iconPath. All right, so here we'll set the icon to some icon.svg. And then finally, some icon.svg and give me the iconPath. Yeah, in this case, it's not a path, it is an icon file name. All right, so if we give that a run, it'll fail for the exact same reason.
Yeah, in this case, it's not a path, it is an icon file name. All right, so if we give that a run, it'll fail for the exact same reason. Let's go back. We'll add an icon. And this can just be hard coded. And then we'll go to our migration. And this will be a string for the icons path. Okay, so let's give it a run again. And we get green. Okay, so if we switch back, I'll let you take a look at this.
And we get green. Okay, so if we switch back, I'll let you take a look at this. Yeah, developers differ on whether they take this approach or not. If you want to take a true TDD, where you don't, you don't write a line of code, not even a migration declaration, then you would maybe take this approach. Or if you want to simplify it, you might say something like it has all necessary attributes. And then you would just clump all of these together, whatever you want. I've seen both. So now think about it. At this point, we have an Achievement Eloquent model.
Preview user-achievement relationship5:24
So now think about it. At this point, we have an Achievement Eloquent model. We know the underlying database table consists of a name, a description, and an icon. And we also know that we can quickly whip up one of these models and populate it using the new model factory we created. So in the next episode, we'll talk about associating a User with a Batch. We can't just add a user_id column to the achievements table, right? That wouldn't make any sense. Because an Achievement doesn't belong to a User. An Achievement can belong or can have many different Users.
Because an Achievement doesn't belong to a User. An Achievement can belong or can have many different Users. And many different Users can be assigned the same batch. So we'll talk about those relationships in the next episode.
