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

Email Edge Case Fails0:56

Now if we were to switch out for their email address, and I'm going to show you this and you're going to laugh, but this is a real email address that is by the RFC of email addresses completely valid. Something like Luke Downing wrapped in quotes at downing.tech. If I jump into the terminal and run php artisan test, you can see we're going to get a failure. And we get that failure because we're not now redirecting to the correct route. There is a session error when we try and store a Contact. So we receive this error in our test suite. So the thing is we don't want to be updating our tests or changing our tests each and every time a new invalid email address comes in.

So the thing is we don't want to be updating our tests or changing our tests each and every time a new invalid email address comes in. I'd rather specify the original faker email address and this new address at the same time. So how would I go about doing that? Well obviously I could take this entire test here, so I could grab this entire test, and I could paste it underneath, and then I could change it. It can store a contact using a previously invalid email address. And then I could update the email here to be our invalid email address, luke.downing@downing.tech. And obviously now if I jump into the terminal and run php artisan test, I still get a failing

Avoid Duplicate Tests2:10

at downing.tech. And obviously now if I jump into the terminal and run php artisan test, I still get a failing test. But you can see we do have two tests here. But this is a really poor way of writing tests because there is so much duplication in our code. Now we're taught that in our application logic, we should avoid as much duplication as possible. And we do our very best to keep our code dry. Why should that be different when we come into the test? It's important that you keep your test code as maintainable as possible, because this

Why should that be different when we come into the test? It's important that you keep your test code as maintainable as possible, because this is the very thing that proves that your application actually works in the first place. So we want to avoid rewriting the exact same logic twice in two different tests. But how can we test two different emails, a faker email and this invalid email? And what about other emails that we might want to check in the future when other problems arise in our code base? Wouldn't it be nice if we could accept parameters in our pest tests, if we could accept an email and instead of using fakeEmail here, we simply pass the email in as a property. As you can imagine, if I jump back into my terminal and run php artisan test, it's going

Introducing Pest Datasets3:12

and instead of using fake email here, we simply pass the email in as a property. As you can imagine, if I jump back into my terminal and run php artisan test, it's going to fail. But check out the message that we get. Pest exceptions data set missing a test with the description it can store a contact has one argument email and no data sets. So we want to look for something called data sets in Pest. Data sets allow us to pass parameters to our closure, to our test closure. And if we can work out how to use data sets, then we can pass dynamic email addresses into our test.

And if we can work out how to use data sets, then we can pass dynamic email addresses into our test. Well, data sets are super simple in Pest. All you do is at the end of your test, right on the end of the closing parentheses, you're going to pass a with chained method. So with is how we create a new data set and you pass with an array. So I'm going to pass an array. And in this array, I'm going to provide as many email addresses as I'd like. So I'm going to provide a fake email. And then I'm going to provide luke.downing@downing.tech.

So I'm going to provide a fake email. And then I'm going to provide Luke Downing at downing.tech. Okay, just like that. I'm going to jump back into php artisan test. And you'll see that we now have two tests as we had before when we manually copied and pasted the test. But note that the description is dynamically changing based on the email address being used in our data set. So it's the exact same test logic, but with dynamic properties or parameters, I should say, being passed in.

Fixing Email Validation4:39

So it's the exact same test logic, but with dynamic properties or parameters, I should say, being passed in. You can see it tells us exactly which one failed. So we can go and debug why this one would be broken. Now, if we jump back into our IDE, and we'll take a look at the ContactsController, you'll see in the store method that we have this custom isValidEmailAddress rule. And if we jump into there, you'll see we do a preg_match_all, where we're basically checking for one or more non-whitespace characters, followed by an @, followed by one or more non-whitespace characters, followed by a ., followed by one or more non-whitespace characters. So in case you didn't already know, it's a really bad idea to implement your own regex

non-whitespace characters, followed by a dot, followed by one or more non-whitespace characters. So in case you didn't already know, it's a really bad idea to implement your own regex solutions for email addresses. They are incredibly complex, and you will almost always get it wrong. We should instead use Laravel's built-in email validation, and it's so easy. All I'm going to do is rip this out and replace it with email. I should say, by the way, that I created that rule specifically for this episode. Jonathan and the team at Inertia did not write that terrible email address rule, so rest assured on that one. But in any case, if I jump back into the terminal now and run php artisan test again, they all

assured on that one. But in any case, if I jump back into the terminal now and run php artisan test again, they all pass. With this power in mind, we are obviously able to add as many email addresses as we'd like. So if I wanted to jump a little further into this, and perhaps there's another one I want to try, which is a .co.uk address, I could say info@me.co.uk. I could jump back into the terminal, run php artisan test, and of course you can see that test here. Now, that's just scratching the surface of what is possible with datasets.

Passing Multiple Dataset Values6:20

here. Now, that's just scratching the surface of what is possible with datasets. You'll see at the moment we're passing an email address in, but what if we wanted to pass in multiple pieces of data? Well, we could pass in multiple pieces of data as separate parameters. So maybe I accept a firstName as well. And in order to pass those in together, I'm going to have to wrap each of these items in an array. And then I can pass in a firstName. So I could say like Dave.

And then I can pass in a firstName. So I could say like Dave. Obviously I should probably say Luke. And then for this info, let's say Sharon. And if I do that, and I switch out Faker firstName with the dynamic firstName, run the tests again, you'll see everything still passes. So that's how you can pass multiple parameters in a dataset. What if I wanted to optionally choose which of these properties to pass in each and every time I create a dataset item? Well, obviously instead of passing these like so, I can just pass an array where I set an

time I create a dataset item? Well, obviously instead of passing these like so, I can just pass an array where I set an email to Faker email. And I could set a firstName to Dave. And then instead up here, I'm going to receive an array of data. And what we'll do as soon as we're in PHP 8.0 plus, I can actually spread out an array inside like so, and I can pass my custom data, which I'll also spread out like so. And if I do that and replace this again with Faker firstName and Faker email, then what that's going to allow me to do is basically use maybe a standard empty array to start. So just the generic data that's already defined.

that's going to allow me to do is basically use maybe a standard array to start. So just the generic data that's already defined. But then in the second instance, why don't we say we want to pass this as the email address and nothing else. And let's run the tests again. You'll see we have a failure on the third one because obviously we've now defined that incorrectly. But that's completely fine as well. Maybe this time we want to test both the email and the firstName. So I can pass that just like so.

Maybe this time we want to test both the email and the firstName. So I can pass that just like so. Run php artisan test again. And now we have 16 passing tests. So super easy to add these cases. And now that we're passing an array in, we're obviously able to pass any sort of data we want to test out any field we want. So in the case of, I don't know, let's say the postalCode, the postalCode should have a maximum characters of 25. So why don't we test that you can actually put 25 characters in there?

a maximum characters of 25. So why don't we test that you can actually put 25 characters in there? All I do is pass another data set item and we'll say postalCode. And let's say str_repeat and we'll do a 25 times. If I jump back into the terminal run php artisan test, you can see we have our new item, which is this array of endless A's. But that does give a valid postcode and indeed checks that it's correct. In fact, if I make this 26 and run php artisan test again, you'll see we get a failure as you might well expect. So that's the basics of data sets.

Naming and Sharing Datasets9:24

you might well expect. So that's the basics of data sets. A couple of extra tips here. If you want to add a custom name, you can do that by passing a key to the data set array. So I could say, for example, this is generic. Then I might say that this is email with spaces. We might say that this one here is .co.uk with Sharon. And this one here is a postcode with 25 characters. Nice and descriptive keys. And once you've done that, if you jump back into the terminal run php artisan test, you'll

Nice and descriptive keys. And once you've done that, if you jump back into the terminal run php artisan test, you'll see instead of dynamically coming up with the descriptions for each item in the data set, it's going to use the key that you've provided. So that might make it just easier to quickly reference why that data set item exists in the first place and allow you to solve the bugs even faster in your code base. Another thing that you may find when using data sets is that you want to reuse a data set across multiple tests or even across multiple test files. So let's go back to making this just about emails. And you may think, right, I need some valid email addresses to use across lots of different

So let's go back to making this just about emails. And you may think, right, I need some valid email addresses to use across lots of different tests in my code base. So how do you do that? You don't want to copy and paste this array everywhere because that's going to become an absolute pain to maintain. So what you can do instead is you can make a shared data set. So let's create a shared data set. Now I'm going to jump into the terminal. I'm going to run php artisan test:data-set and we'll call it emails.

Now I'm going to jump into the terminal. I'm going to run php artisan test and we'll call it emails. And you'll see that it's going to create a tests/data/sets/email.php file for us. Let's find that out now and you'll see that it's already created this data set. So you can define a global data set using the dataSet function. You could pass a key and this key can be anything. In fact, I'm going to change this to validEmails because we may have in here an invalidEmails as well. And then much like tests, we have a closure and then we return an array from the closure and the array that you return is your data set.

And then much like tests, we have a closure and then we return an array from the closure and the array that you return is your data set. So in our case, I'm going to take this array here and I'm going to drop it straight into our shared data set. Once I've done that, instead of adding an array as the first parameter of the with method, I'm just going to pass the key of our global data set. So validEmails. And once I do that, and obviously I update the code here. So we'll change this back to being email and we'll drop the email in here and remove this mergedData.

So we'll change this back to being email and we'll drop the email in here and remove this merged data. If I go back to the terminal on php artisan test, you'll see I have 17 passing tests and you can see each of those emails being pulled in from the shared data set. So shared data sets are super useful for cleaning up multiple tests which use the same exact data.

DatasetsShared Datasets

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