Renaming the Test0:00
Now, before we move on, our tests are currently passing, so let's take a few moments to clean things up. We'll start with ExampleTest. This is where we began, it's where we decided and figured out what are we doing here. But of course I don't want to leave it as ExampleTest. Now if we look at it, it sure looks like I'm testing a product, but it's not even a feature test, at least not how I describe it. We're not simulating a user, we're not going from the outside in, I'm really testing how these Eloquent models communicate with each other. So my instinct is not to put that in feature.
these Eloquent models communicate with each other. So my instinct is not to put that in feature. It's more of a integration test, or honestly I keep things pretty broad, I would call that a unit test. But that's really not the proper definition, but you know what, who cares. My opinion is test jargon is beyond complicated, and it's exacerbated by the fact that communities all have slightly different definitions for these terms. So functional vs. acceptance vs. end-to-end vs. feature vs. integration, it gets confusing so fast. So I would almost prefer that we not use these terms at all.
so fast. So I would almost prefer that we not use these terms at all. I'd rather see things like wide vs. narrow tests. So wide tests would test a wide surface area of the codebase, whereas narrow tests focus on a narrow area of the codebase, or section of the codebase. Example test, well notice we have products, we're testing the state of the product, so I'm going to rename this to ProductTest. Next if we return to our artisan command test, again this is passing, but I can see a number of areas we can clean things up a little bit. This is a little long for my taste.
Refactoring Test Setup1:41
of areas we can clean things up a little bit. This is a little long for my taste. So generally I begin a refactor by searching for low-hanging fruit, even things as simple as this. So why don't we, we're using php 7.4, why don't we switch to a short closure or arrow function. And we get something like that, I might even try to get that on its own line. So we end up with that number. Okay next, this section here is effectively our setup. It's the given portion of the test.
Okay next, this section here is effectively our setup. It's the given portion of the test. So given we have a Product and a Retailer, and the Product's not in stock, if we run an artisan command to query the Best Buy API, and that API returns that it is in stock, well we should update that on our local, within our local database. And that passes. So I'm thinking here, we talked about one duplication being okay, but two or more being an indication that you should refactor. Let's go ahead and do that now. And actually before we do that, this right here, it's fine, but it's redundant from when
Extracting a Database Seeder2:41
Let's go ahead and do that now. And actually before we do that, this right here, it's fine, but it's redundant from when we copy the test here. I don't really need it in this case, so I can remove that. And it still passes, of course. Okay, so let's grab all of this and see what it might look like if we extract it to a factory class or even a database seeder. So we could put them here, and I'll show you how. And we'll run php artisan make:seeder, and we'll give it a super specific name, like RetailerWithProduct.
And we'll run php artisan make:seeder, and we'll give it a super specific name, like RetailerWithProduct. Alright, so now that will show up here, and we're going to paste all of that code in, like so. Alright, so just a few tweaks here. I no longer need that, it's not necessary. Create a Product and a Retailer, and then supply for the Product at that Retailer. And in fact, maybe we can inline this, how's that look? Best Buy and stock for the switch, and here are the details. Okay, so now we have a database seeder, which means if I switch back to our test here and
Best Buy and stock for the switch, and here are the details. Okay, so now we have a database seeder, which means if I switch back to our test here and we give it a run, it's all going to fail because we have these missing variables. So let's do this. We're going to seed our database, and we want the RetailerWithProduct seeder. Okay, so now if we run that alone, it's going to trigger this command, and it'll create the product and the retailer and the stock. So if we were to say, give me all of your products, you'll see it does show up right here. It works. And yeah, pros and cons to this, right?
It works. And yeah, pros and cons to this, right? A pro is, we're able to move this common logic into a seeder. A con is, it's a little bit more blurry what the specifics are, but that's why we are as specific as we can with the name of the seeder. Actually, why don't we call this Seeder. Okay, and that should update over here as well. Okay, so now let's just update this section here, and we'll do it in a couple steps. First, we now know that we have a product, right? And by default, it's not in stock.
Fixing Autoloading Issues4:38
First, we now know that we have a product, right? And by default, it's not in stock. So let's say this assertFalse. And give it a run. Hmm, does not exist. You know what, it's because I changed the name. Let's say Composer::dumpAutoload. And real quick, we do that because database seeders are not namespaced. So when we change the class name, Composer lost track of it. So we have to tell it to redump the autoload file.
So when we change the class name, Composer lost track of it. So we have to tell it to redump the autoload file. Okay, but anyways, that passes, which means I can bring this back, and then we'll just update this final assertion using this one. So after we run the artisan command, and after that API call returns that there are, or that there is stock available, if we check now on our local database, that should return true. And it passes. So let's reformat to remove some of those unused imports. And this is what we now have.
Asserting Command Output5:29
So let's reformat to remove some of those unused imports. And this is what we now have. A little bit cleaner. Now, I don't think it's really necessary, but if you want, we could even add expectations on the output. If you want some feedback when the artisan command is run, we could add an assertion here. We run it, and of course it fails. So that's our final step. Track command.
So that's our final step. Track command. We track all of the products. And then I can say this info all done. Give it another run, and it passes. And I think the entire test suite should be passing, and it is. Okay, so now we've organized things a little bit more. We have our ProductTest. We have our FeatureTest. We have a reusable database seeder anytime we need a retailer with a product.
Recap and Next Steps6:08
We have our feature test. We have a reusable database seeder anytime we need a Retailer with a Product. So I think we're all set to go. In the next episode, we will return to our Stock class and take a look at this. How are we going to clean that up?