در حال بارگذاری ...

Installing Faker Plugin0:00

All right, let's take another look at the test that we created in the last episode. This test looks nice, I'm happy with it, but it could be written in a more pesty style. And whenever I can do that, I like to because it helps fit in better with the testing framework we're using. So first of all, although we're accessing Faker using this currently, Pest actually offers a Faker plugin that would allow us to access Faker in a functional style, which has a couple of benefits. So first things first, we need to grab the Faker plugin and we can grab it from the Pest website. It's a simple composer install.

website. It's a simple composer install. So I'll jump into my terminal again and we'll paste that command and I'll hit install. Now once that's installed, we can jump back into our IDE and I'm going to replace all instances of this Faker with a simple call to Faker as a method. And I'll obviously do phpStorm's cleanup in order to import that function at the top. Now as soon as we're not using Faker on the test case anymore, I can simply remove this user statement and obviously simplify my imports at the top here. To show you this still works, let's run php artisan test. You can see everything still passes, but now we're making use of this Faker function instead.

To show you this still works, let's run php artisan test. You can see everything still passes, but now we're making use of this Faker function instead of any Faker property on the test case. Obviously one nice perk of using this instead of the property on the test case is you can make use of Faker in unit tests as well, which is really nice. If you wanted to use something other than the default locale for Faker, you can pass Faker a locale directly. So I could pass, say, EN_GB to use great British values instead of American values. Brilliant. So that's step one of making this test more pest-like.

Creating Custom Expectations1:50

Brilliant. So that's step one of making this test more pest-like. Let's take a look at these expectations that we created earlier. I'm quite happy with them apart from this phone number. This phone number sticks out to me as being a little weak as an expectation. Now wouldn't it be nice if I just duplicate this line a second, if there was actually an expectation called toBePhoneNumber. But as you can imagine, if I jump back to my terminal and run php artisan test, I'm going to get a failure. And basically the message is that there is no such expectation method as toBePhoneNumber.

to get a failure. And basically the message is that there is no such expectation method as toBePhoneNumber. So how can I get around the limitation of there not being a toBePhoneNumber expectation method in PEST? Well, I can actually extend the PEST PHP expectation API to include custom expectations that make sense for my application logic. We do all of that form of extension in the pest.php configuration file. So let's jump into there now. And you'll see there's a nice section dedicated to functions. And above that, we have this section dedicated to expectations, which is exactly what we're

And you'll see there's a nice section dedicated to functions. And above that, we have this section dedicated to expectations, which is exactly what we're going to want to look at next. Okay, I'm going to remove this default expectation that ships out of the box. But we're going to use the same syntax. So we'll start with a call to expect, but we pass no properties. Instead, I call the extend method on the expect API. And the first thing I need to pass is the name of the new macro, the extension that I want to create. So let's call this toBePhoneNumber.

I want to create. So let's call this toBePhoneNumber. Nice and straightforward. Now, the second parameter that I pass is a closure. So we'll pass that now. Now, if there was any properties that I wanted to pass to toBePhoneNumber, we would accept those properties here. So let's say you want to pass an areaCode. You would accept the areaCode here. For our example, we're not going to receive any properties.

You would accept the area code here. For our example, we're not going to receive any properties. So I'll leave that empty. Inside this extension, we can basically perform any logic that we want. So first of all, why don't we do the logic that we already have? That the string has to start with a plus. So we can say, expect this value, which is basically whatever you've passed to expect, in our case, the contact's phoneNumber. Expect this value to be string and to start with a plus. Okay?

Expect this value to be a string and to start with a +. Okay? And just to show that that's basically the same thing, if I jump back here and I remove this line now, we go into our terminal and run php artisan test again, you'll see I have the exact same passing results as I had before. But if I go into the IDE and I was to alter this phoneNumber to something that doesn't start with a +, let's say fooBar, and then run php artisan test once more, I'm going to get an error. So yes, you can use expectations inside custom expectations, which is really clean and nice. Let's revert this back to a valid phoneNumber and make sure our test suite's still passing.

Adding Phone Validation Rules4:51

So yes, you can use expectations inside custom expectations, which is really clean and nice. Let's revert this back to a valid phone number and make sure our test suite's still passing. Okay? And once we've done that, why don't we start looking at how we can extend this to be even more powerful? What's another thing we might want to check to make sure a phone number's valid? Well, one thing is that it should be, let's say, at least 6 characters long. If it's not 6 characters long, then it's not a valid phone number. So why don't we say, if strlen of this $value is less than 6, throw a new ExpectationFailedException.

So why don't we say, if string length of this value is less than 6, throw a new ExpectationFailedException. That ships with phpunit. It's part of PEST as well. And it's the exception you want to use when none of the default expectation methods suit your requirements. I'm going to throw a new ExpectationFailedException. And I'm going to say phoneNumbers must be at least 6 characters. Okay? And if we jump back into our example, and once again, let's put foobar in here, and

Okay? And if we jump back into our example, and once again, let's put foobar in here, and let's start it with a plus, right, so that it passes the other validation. And then I jump into my terminal and run php artisan test. Oh, hold in. I have a fully passing value. That's because foobar is now longer than six characters. If we remove a couple of characters there and jump back into the terminal, you're going to see, yes, phoneNumbers must be at least six characters. So our custom expectation is starting to take shape.

a numeric value, then that should throw another exception. So we'll say something like if string of this value after the initial plus, once you've removed any spaces or any dashes, and then we can say is_numeric, right? That's just a built-in function in php, is_numeric. If that is not the case, then I'll want to throw a new ExpectationFailedException. And I'll say phone numbers must be numeric. Okay, let's jump into the terminal, and I'll run php artisan test again. Phone numbers must be numeric. That's wonderful. So let's now jump back into the IDE, and let's switch this value back to what it was initially,

Fixing Object String Casting7:46

That's wonderful. So let's now jump back into the IDE, and let's switch this value back to what it was initially, which is an E164 phone number, back into the terminal, php artisan test. Hold him. We're still failing. So what could the issue be here? Well, this is an object, right? So what I need to do is I need to say that it has to be toString at the end to convert it back into a string value like so. And once I've done that, and if I actually get my parameters in the right place there,

into a string value like so. And once I've done that, and if I actually get my parameters in the right place there, we should be able to jump back into the terminal, run php artisan test, and everything passes. So you can see how powerful custom expectations really are. You can create any logic that you want, and you can really make a beautiful API for working in your application tests, very specific and extremely powerful going forwards. Okay. Let's go back to our test, which is now looking really quite clean. There's one more thing we can do. If you take a look at this test, you'll notice that every time we access the expectation call,

Using Higher-Order Expectations8:44

There's one more thing we can do. If you take a look at this test, you'll notice that every time we access the expect call, we talk about the exact same object, this Contact model. And you'll do this all the time in Laravel because we are often testing database models, Eloquent models. When we're doing that, we find ourselves repeating the exact same call to expect over and over again, but accessing different properties or methods on a single object. Again, in this case, the Contact model. Well, when you find yourself in that position, you can drastically simplify this by reaching for something called higher order expectations.

Well, when you find yourself in that position, you can drastically simplify this by reaching for something called higher order expectations. And these are one of my favorite features in Pest PHP. They're so clean. The basic idea is this. Instead of reaching for properties directly inside expect, you simply pass expect the top level object you want to interact with. So let's say expect contact, and you'll note I'm now going to leave the expectation. So I'm going to close the expectation off there, and I'm going to access the firstName directly on the expectation object.

So I'm going to close the expectation off there, and I'm going to access the firstName directly on the expectation object. Now, obviously, firstName is not part of the expectation API. So what's going to happen is Pest PHP is instead going to search for firstName on the Contact model. And if it finds it, it's going to create a brand new custom expectation for you where we can perform toBeString and notToBeEmpty. Just to show you this works, let's jump into our terminal from php artisan test. You'll see everything is still passing. So that is working correctly. Now, once we've performed one or more expectations, as we have done here,

So that is working correctly. Now, once we've performed one or more expectations, as we have done here, we can now reach for another property on the contact object. So I can obviously grab the lastName and perform the exact same checks. Again, let's jump into our terminal and run php artisan test, and everything once again is passing. You can see the power of this. We're able to build these very fluent chains very quickly. In fact, let's grab all of this here, and perhaps we can grab it like so. And we'll drop it in.

In fact, let's grab all of this here, and perhaps we can grab it like so. And we'll drop it in. We'll clean up the syntax so that it actually passes, okay, so that it's valid PHP. And once we've done that, we'll make sure it all works by jumping back into the terminal, running php artisan test. Everything is passing with flying colors, which is wonderful, which means I can get rid of all of these separate expect calls and have this single chain instead. Now, because I'm only accessing contact once now instead of over and over again, I can even inline this variable here,

Now, because I'm only accessing contact once now instead of over and over again, I can even inline this variable here, which means I'm left with this gorgeous single chain to make use of. So that's higher order expectations, and it's a beautiful way to use PHP, especially when working with Eloquent models in Laravel. So to recap this session, we've taken a look at using the Faker plugin, which allows us to remove traits like with Faker that we might have to reach for otherwise. We've also taken a look at implementing our own expectations by extending the expectation API, in this case for our very special 2B phone number expectation.

by extending the Expectation API, in this case for our very special 2B phone number expectation. And finally, we've looked at how to use higher order expectations to simplify testing against the same object in your php and Laravel tests.

Pest PluginsHigher Order ExpectationsCustom Expectations

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟