تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Code Coverage Overview0:00

Since this whole video course is about testing, we also have to talk about code coverage or test coverage. So how much of our code, of the code that we've written, is covered with tests? So that's what this means. And this is what we can measure. And of course, this also works with PEST. And on the PEST documentation for coverage, you can see that we can use the coverage flag like you would do with phpunit. The only thing you need is to have XDebug enabled or not extension,

like you would do with phpunit. The only thing you need is to have XDebug enabled or not extension, but we're going to work with XDebug. And here we also have to make sure that the XDebug is set to coverage. But again, there are also some other options here, which you can use to enable code coverage for your PEST tests. And then we just have to append coverage to our test comment. And then we will see after the tests have run, the coverage of our code. All right, so let's try this out.

Enabling Xdebug Coverage0:56

the coverage of our code. All right, so let's try this out. And just before, let's make sure that XDebug is enabled. You can see we have it here. XDebug is enabled. It's good. And now what we're going to do, we're going to run our test, but now with coverage. So let's see, code coverage driver not available. So this will you see if you haven't set coverage for the XDebug mode. So let's do this together.

So this will you see if you haven't set coverage for the XDebug mode. So let's do this together. I have here my ini file for XDebug. And you can see I have set the mode to develop and debug, but let's also add coverage here. All right, let's run this again. And let's see what happens now. First, of course, our tests are going to be run and then we should see the code coverage. Or not, we see an error here.

Fixing Interface Mismatch1:46

and then we should see the code coverage. Or not, we see an error here. Let's check this out. Declaration not with the tweet must be compatible. Oh, I think we forgot something here. Oh, yeah, we did. Oh, yeah, I know what is because in the last video, we added also the string status as a parameter here to our interface. So this means we also have to put this now here to our now TwitterClient and this is status.

So this means we also have to put this now here to our now Twitter client and this is status. Yep. All right, let's try again and let's see if it now works. All right, so our tests have now run successfully and we now see code coverage for our code. And interesting thing for us is, of course, the total coverage because this gives us now an idea of how much of our code has been covered with tests. And we got 77.1%, which is already pretty good.

has been covered with tests. And we got 77.1%, which is already pretty good. So what should you aim for? So what is the percentage that you need for your project to have good cover test? Of course, 100% would be perfect. But yeah, in the end, mostly this is not possible because there are files which cannot be really tested or doesn't make sense to be tested. So it doesn't make sense to aim for 100%.

or doesn't make sense to be tested. So it doesn't make sense to aim for 100%. What I always recommend is to aim for at least 80%. Because yeah, this gives you a good sign about the coverage of your code. It's quite high and this usually is a good thing. So yeah, we are not there yet. So let's take a look at if we can improve something here. And we can see here a lot of files, 100% coverage is good. But then there are also files where we have zero coverage like here for Fortify. This comes from Laravel.

But then there are also files where we have zero coverage like here for Fortify. This comes from Level. But currently the most I'm interested in are the files that we have created. So let's take a look. Most of the things here are with 100%, which is good. Here is also provider with 0%. But this is not something that I want to test. But yeah, here we have two files, the nullTwitterClient and the TwitterClient. Both have zero percentage test coverage.

Unit Testing Null Client3:59

and the TwitterClient. Both have zero percentage test coverage. And yeah, these are two files that we just created. So it's a good idea to also add tests for them. And then hopefully we also get to our 80% test coverage. All right, where do we start? Let's start with the NullTwitterClient. And by the way, I think we should rename this now also to be a Client. Because yeah, it's a Client the same as the real TwitterClient is. But this is now a NullTwitterClient.

Because yeah, it's a client the same as the real Twitter client is. But this is now a null Twitter client. So I think client is a better naming here. Now let's also create a new test. This is going to be now a unit test because we are not going to need any external services. We're not going to need the database. So now this for me is a real unit test because we just want to make sure that we can create an instance of this client and probably that we can return an empty array

because we just want to make sure that we can create an instance of this client and probably that we can return an empty array because that's all this class does. And we're going to call this NullTwitterClient test. All right, so what do we want to test? It returns empty array for a tweet car. That's actually the only thing we are doing. All right, so we're creating here a new NullTwitterClient. Let's clean up the code here. And what do we want to make sure now?

Let's clean up the code here. And what do we want to make sure now? So we have now a new instance of our Client. Now what we want to do is we want to run the tweet method. And we're going to provide a string, our tweet. And then actually we want it to be array. And I think we also got to be empty. Yeah, like this. All right, let's run this. And it already works.

Mocking TwitterOAuth Client5:40

All right, let's run this. And it already works. Pretty cool. So this was pretty easy because the null Twitter client is not actually doing anything. It will be now a little bit more interesting with the Twitter client itself. So let's create another unit test. This will be now the TwitterClientTest. All right, and before we think about how we do this,

This will be now the TwitterClient test. All right, and before we think about how we do this, let's check out the TwitterClient again. So with our TwitterClient as a class, we're also using a facade. But here we're using the real class, which we're using as the TwitterOAuth class. And here when we run our tweet method, we are actually calling the post method on the TwitterOAuth class on this service.

we are actually calling the post method on the TwitterOAuth class on this service. And this is how we're going to send out the instruction to Twitter to tweet our status. So this is actually what we're interested in, that this method is being called with these arguments. Okay, so what we want to make sure is now it calls the OAuth client for a tweet like this. Now, actually, we don't really want to call the class itself. We want to mock it.

Now, actually, we don't really want to call the class itself. We want to mock it. And there is a nice mock plugin for Pest, which we can use, and it's called Pest Plugin Mock. And we also need it only for the dev environment. Let's run this. And here we go. Nice. So we are now creating a new mock. And we have now this new global mock helper.

So we are now creating a new mock. And we have now this new global mock helper. And we want to mock the TwitterOAuth class by Abraham, this one here. And let's clean up the code here. It's a little bit nicer to read. And here we don't need a variable. It's a function which we're actually calling. And now we want to make sure that this mock should receive a call to the post method with some arguments,

And now we want to make sure that this mock should receive a call to the post method with some arguments, which is an array. And the first argument is the endpoint, I think, which we have here. It's this one here, status/update. That's the endpoint of the Twitter API. And then the second argument is an array with the status. And the status is something that we define now. Let's call it myTweetMessage.

And the status is something that we define now. Let's call it myTweetMessage. All right. And then we want to return something. And here we want to return. So here we're making sure that we receive these arguments. So this is where we're checking. We want to make sure that we receive a POST request with those arguments. And now we also want to return something.

with those arguments. And now we also want to return something because this is then what we can also check later, what we're going to return when we call the method on the client later. So this means we're going to return the same thing that the client does, which is an array with the status and the same message, myTweetMessage. And then we're going to get the mock here as well. All right, then next,

And then we're going to get the mock here as well. All right, then next, we are going to call TwitterClient. So let's create a new one, TwitterClient. And the only dependency is now our mock here. That's because, again, our TwitterClient needs this instance of the TwitterAuth class. And of course, we assign here the client. So this, by the way, is our assertPath because we're already making an assertion.

So this, by the way, is our assertPath because we're already making an assertion. And this is now our actPath. And then now here we have another assertPath. So we're now going to expect when we call our TwitterClient, tweet with myTweetMessage. And this should be equal now to what we get back and which is an array with the status of myTweetMessage. All right, let's go through it together again. So we are using the mock helper method.

All right, let's go through it together again. So we are using the mock helper method by pass to mock a specific service, which is the TwitterAuth service. We want to make sure later when we call this tweet method here, actually, this is where we're calling it. Actually, we can call this act and assert as well. All right, we want to make sure that it receives a call to the post method with specific arguments. So this is what we're going to expect.

a call to the post method with specific arguments. So this is what we're going to expect. This will be assertion. And then we want to return something. So this is what we're going to return. And this is what we then later test here if we get back this here. All right, let's take a look. Let's run this and see if it works. And you can see it's already working.

Let's run this and see if it works. And you can see it's already working. And I really like how we can use the mock helper here to mock some external services which don't belong to us or which we don't want to test, actually. We just want to make sure that they are caught and that they return what they should return. All right, so let's take another look at our code coverage. And with a little bit of luck, we should now have more than 80%,

And with a little bit of luck, we should now have more than 80%, which my goal was for this course. Oh, close, but we're still not there. 79.1%. All right, so I can't leave you without having 80%. So let's take a look at what else can we do. Yeah, TwitterServiceProvider. That's interesting because I thought about that myself. So yeah, especially this thing here.

Testing Service Provider Binding11:11

That's interesting because I thought about that myself. So yeah, especially this thing here. So we haven't tested that this is really working. So if we are production environment, we get back the TwitterClient. But if we are any other environment, we get back the null TwitterClient. So let's create a test for this. This will be a feature test again because we're going to use the container of Laravel.

This will be a feature test again because we're going to use the container of Laravel. So feature test and let's call this TwitterServiceProviderTest. All right, so what we want to test is actually what we're most interested in is if we are in the testing environment, we only get a null Twitter instance back, right? Yeah, I think so. So it returns null Twitter client for testing environment. So this means we also don't have to set anything for the environment.

So it returns null TwitterClient for testing environment. So this means we also don't have to set anything for the environment because by default, it's already testing. All right, so we're at and asserting here. So we're going to expect now that when we ask the service container for the TwitterClientInterface, which gives us back the client. And we want to make sure that it is an instance of the NullTwitterClient class. All right, clean this up.

of the null TwitterClient class. All right, clean this up. Let's take a look again. Let's run it. And it already works. This looks good. And I think I'm fine with this already. Let's run our coverage again. And with a little bit of help, we should now have 80% coverage and we do.

And with a little bit of help, we should now have 80% coverage and we do. And this is the least amount, the amount that I aimed for when creating this course that we have at least 80% test coverage. Of course, we can take a look at some more of those files here and try to make it even higher. But for now, for this course, I'm really fine with 80%. And yeah, make sure to check out this coverage feature of phpunit and PHP and give it a look because it is really helpful.

And yeah, make sure to check out this coverage feature of phpUnit and PaaS and give it a look because it is really helpful. And sometimes it tells you if there are any classes like our clients, which you haven't tested yet.

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