WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.016 --> 00:00:07.106 align:middle
Where did this metrics string come from
- this metrics.http.requests.count?

00:00:07.746 --> 00:00:10.176 align:middle
There are two things I want to say about this.

00:00:10.176 --> 00:00:15.746 align:middle
First, Blackfire stores tons
of raw data about your profile

00:00:15.926 --> 00:00:18.746 align:middle
in little "categories" called metrics.

00:00:19.206 --> 00:00:20.426 align:middle
More on that soon.

00:00:21.006 --> 00:00:23.406 align:middle
And second, inside the assert() call,

00:00:23.606 --> 00:00:28.226 align:middle
you're using a special "expression"
language that's similar to JavaScript.

00:00:28.816 --> 00:00:32.396 align:middle
It's technically Symfony's
ExpressionLanguage if you want to read more.

00:00:32.966 --> 00:00:36.366 align:middle
Behind-the-scenes, metrics
is probably some object...

00:00:36.366 --> 00:00:40.706 align:middle
and we're referencing an http
property, then a requests...

00:00:40.706 --> 00:00:45.126 align:middle
property then a count property &amp;
then we're comparing that to 1.

00:00:46.126 --> 00:00:47.386 align:middle
Ok, cool. So...

00:00:47.496 --> 00:00:53.576 align:middle
how the heck did I know to use this
exact string to get the HTTP call count?

00:00:54.506 --> 00:00:57.546 align:middle
This goes back to the Blackfire timeline.

00:00:58.316 --> 00:01:00.786 align:middle
On the profile, click the timeline link.

00:01:00.846 --> 00:01:06.616 align:middle
When we talked about the timeline earlier,
we talked about how, on the left side,

00:01:06.876 --> 00:01:10.296 align:middle
there are these "timeline" metrics.

00:01:10.296 --> 00:01:15.746 align:middle
At that point, these were just a nice way to
add color to different sections of the timeline.

00:01:16.136 --> 00:01:21.736 align:middle
But now we understand that there is
a lot more power behind this info:

00:01:22.346 --> 00:01:27.556 align:middle
this shows us all the pieces of
data we can use in our tests...

00:01:27.556 --> 00:01:30.236 align:middle
and in other places that we'll talk about soon.

00:01:30.236 --> 00:01:36.086 align:middle
For example, there's a metric called
symfony.events.count which equals seven.

00:01:36.676 --> 00:01:41.276 align:middle
You could use that in a metric if,
for some reason, you wanted to assert

00:01:41.306 --> 00:01:44.026 align:middle
that a certain number of events were dispatched.

00:01:44.836 --> 00:01:49.896 align:middle
If I needed to do an assertion
about the number of HTTP requests,

00:01:49.896 --> 00:01:52.636 align:middle
I would probably search the metrics for http.

00:01:53.386 --> 00:01:54.966 align:middle
Apparently there are two...

00:01:55.246 --> 00:02:01.696 align:middle
and if you looked closer, you'd
find that http.requests is perfect.

00:02:02.446 --> 00:02:09.496 align:middle
Most of these metrics have data about multiple
dimensions: we can say http.requests.count

00:02:09.696 --> 00:02:15.856 align:middle
to get the actual number or http.requests.memory
to get how much memory they used.

00:02:16.936 --> 00:02:19.916 align:middle
In the test system, we start with metrics.

00:02:20.096 --> 00:02:22.626 align:middle
then use anything we find here.

00:02:23.636 --> 00:02:28.566 align:middle
We now have a performance bug in our
application that we've proven with a test.

00:02:29.156 --> 00:02:35.016 align:middle
And at this point, the actual way we fix that
bug is not as important: all we care about is

00:02:35.016 --> 00:02:38.026 align:middle
that we can change some code
and get this test to pass.

00:02:39.276 --> 00:02:44.156 align:middle
The logic for the API calls lives
in src/GitHub/GitHubApiHelper.php:

00:02:44.156 --> 00:02:51.386 align:middle
it has two public function and
each makes one API request.

00:02:52.486 --> 00:02:56.606 align:middle
How can we make this page
only make 1 HTTP request?

00:02:57.226 --> 00:02:59.266 align:middle
Well, if you looked closely..

00:02:59.646 --> 00:03:01.186 align:middle
Ah! Too close!

00:03:01.846 --> 00:03:06.646 align:middle
Ahh. You'd find that you can
get all the information you need

00:03:06.856 --> 00:03:10.796 align:middle
by only making this second HTTP request.

00:03:11.536 --> 00:03:14.756 align:middle
The details aren't important
- so let's just jump in.

00:03:15.526 --> 00:03:19.766 align:middle
Add a new property called
$githubOrganizations set to an empty array.

00:03:21.336 --> 00:03:25.296 align:middle
As we loop over the repositories
for a specific organization,

00:03:25.606 --> 00:03:28.616 align:middle
we will store that organization's info.

00:03:29.916 --> 00:03:33.916 align:middle
Add a new variable called
$publicRepoCount set to 0:

00:03:35.236 --> 00:03:39.536 align:middle
the number of public repositories
an organization has is one

00:03:39.536 --> 00:03:41.146 align:middle
of the pieces of data we need.

00:03:41.576 --> 00:03:47.266 align:middle
Then, inside the foreach: if
$repoData['private'] === false -

00:03:47.636 --> 00:03:53.026 align:middle
that's one of the keys on
$repoData - say ++$publicRepoCount.

00:03:53.976 --> 00:03:58.806 align:middle
So, as we're looping over the repositories,
we're counting how many are public.

00:03:58.966 --> 00:04:07.326 align:middle
Finally, at the bottom, if not isset($this
-&gt;githubOrganizations[$organization]),

00:04:07.946 --> 00:04:14.736 align:middle
then $this-&gt;githubOrganizations[$organization]
= new GitHubOrganization().

00:04:15.416 --> 00:04:17.026 align:middle
This needs two arguments.

00:04:17.786 --> 00:04:19.816 align:middle
The first is the organization name.

00:04:20.196 --> 00:04:22.906 align:middle
We can probably use the $organization
argument...

00:04:23.136 --> 00:04:29.596 align:middle
or you can use $data[0] - to get the first
repository - then ['owner']['login'].

00:04:29.596 --> 00:04:35.706 align:middle
For the second argument, pass $publicRepoCount.

00:04:37.066 --> 00:04:39.146 align:middle
Now, each time we call this method,

00:04:39.376 --> 00:04:44.736 align:middle
we capture the organization's
information and store it on this property.

00:04:44.736 --> 00:04:49.486 align:middle
So if we call this method first
and then the other method...

00:04:49.916 --> 00:04:55.196 align:middle
we could cheat and return the GitHubOrganization
object that's stored on the property.

00:04:55.756 --> 00:04:57.126 align:middle
It's property caching!

00:04:57.836 --> 00:05:04.776 align:middle
Check it out: if isset($this
-&gt;githubOrganizations[$organization]) then

00:05:04.776 --> 00:05:08.036 align:middle
return that immediately without doing any work.

00:05:09.156 --> 00:05:13.966 align:middle
So... are we calling these two methods in
the "correct" order to get this to work?

00:05:14.806 --> 00:05:15.556 align:middle
Check out the controller.

00:05:16.666 --> 00:05:23.866 align:middle
Nope! Swap these two lines so the first
call will set up the caching for the second.

00:05:24.136 --> 00:05:25.636 align:middle
Phew! Let's see if that helps.

00:05:26.156 --> 00:05:28.136 align:middle
It was a complicated fix...

00:05:28.176 --> 00:05:31.936 align:middle
but thanks to our test, we will
know for sure if it worked.

00:05:32.726 --> 00:05:35.686 align:middle
Go! They pass!

00:05:36.306 --> 00:05:41.266 align:middle
This proves that we reduced
the HTTP calls from two to one.

00:05:42.176 --> 00:05:46.256 align:middle
What I love about the metrics system
is that there are many to choose from.

00:05:46.806 --> 00:05:52.136 align:middle
What I don't love is that you need to
manually look up everything that's available.

00:05:52.136 --> 00:05:57.366 align:middle
Fortunately, if you make a
typo - the error is great.

00:05:58.246 --> 00:06:06.576 align:middle
Change count to vount and re-run the test:
An error occurred when profiling the test

00:06:06.576 --> 00:06:10.406 align:middle
And when we follow the profile link...

00:06:14.376 --> 00:06:16.116 align:middle
check out that error!

00:06:16.816 --> 00:06:19.026 align:middle
The following assertions are not valid...

00:06:19.446 --> 00:06:23.116 align:middle
Property "vount" does not
exist, available ones are: ...

00:06:23.516 --> 00:06:25.366 align:middle
and it lists all the properties.

00:06:25.876 --> 00:06:27.296 align:middle
That's super friendly.

00:06:27.366 --> 00:06:29.166 align:middle
Fix the typo.

00:06:30.536 --> 00:06:36.086 align:middle
The one downside to adding Blackfire assertions
in your tests is that they do slow things

00:06:36.086 --> 00:06:41.966 align:middle
down because instrumentation happens and we need
to wait for Blackfire to create the profile.

00:06:42.846 --> 00:06:44.976 align:middle
Because of that, as a best practice,

00:06:45.296 --> 00:06:50.996 align:middle
we usually like to isolate our
performance tests from our normal tests.

00:06:51.076 --> 00:06:54.426 align:middle
Check it out: copy the test
method name, paste it below,

00:06:54.736 --> 00:06:59.246 align:middle
and call it
testGetGitHubOrganizationBlackfireHttp

00:06:59.246 --> 00:07:00.026 align:middle
Requests().

00:07:01.476 --> 00:07:05.066 align:middle
And... copy the contents of the
original method and paste here.

00:07:08.176 --> 00:07:13.166 align:middle
Now... we only need to create the
$client, create $blackfireConfig and,

00:07:13.266 --> 00:07:16.546 align:middle
inside assertBlackfire(), just make the request.

00:07:17.446 --> 00:07:20.296 align:middle
Back in the original method, we can simplify...

00:07:20.696 --> 00:07:25.756 align:middle
in fact we can go all the way back to
the way it was before: create the client,

00:07:25.956 --> 00:07:27.706 align:middle
make the request, assert something.

00:07:28.506 --> 00:07:30.166 align:middle
Why is this useful?

00:07:30.726 --> 00:07:36.906 align:middle
Because now we can skip the Blackfire tests
if we're just trying to get something to work.

00:07:37.776 --> 00:07:42.486 align:middle
How? Above the performance
test, add @group blackfire.

00:07:43.906 --> 00:07:46.356 align:middle
Thanks to that, we can add --

00:07:46.566 --> 00:07:52.796 align:middle
exclude-group=blackfire to
avoid the Blackfire tests: Yep!

00:07:52.996 --> 00:07:55.196 align:middle
Just one test, two assertions.

00:07:55.946 --> 00:08:00.126 align:middle
Another nice detail is to add
@requires extension blackfire.

00:08:00.996 --> 00:08:04.266 align:middle
Now, if someone is missing
the Blackfire extension,

00:08:04.706 --> 00:08:07.946 align:middle
instead of the tests exploding,
they'll be marked as skipped.

00:08:09.116 --> 00:08:13.876 align:middle
The last thing I want to mention
about assertions is this: please,

00:08:13.876 --> 00:08:18.126 align:middle
please please avoid time-based assertions.

00:08:18.546 --> 00:08:20.826 align:middle
They're the easiest to create - I know.

00:08:21.346 --> 00:08:24.136 align:middle
It's super tempting to want
to create an assertion

00:08:24.296 --> 00:08:27.886 align:middle
that the request should take
less than 500 milliseconds.

00:08:28.736 --> 00:08:32.566 align:middle
If you do this, you will hate your tests.

00:08:32.606 --> 00:08:39.216 align:middle
Why? Because there's way too much variability
in time: the request might run fast enough

00:08:39.216 --> 00:08:42.656 align:middle
on one machine, but not fast enough on another.

00:08:43.036 --> 00:08:45.736 align:middle
Or your server might just have a bad day...

00:08:45.986 --> 00:08:48.046 align:middle
and suddenly your tests are failing.

00:08:48.706 --> 00:08:51.866 align:middle
Relying on time makes your tests fragile.

00:08:53.116 --> 00:08:56.326 align:middle
Next, we're going to talk more
about metrics and assertions.

00:08:56.836 --> 00:09:02.266 align:middle
We know that we can add assertions to
profiles that are created inside our tests.

00:09:02.676 --> 00:09:10.946 align:middle
But we an also add global assertions: tests that
run any time you create a profile for any page!

00:09:10.986 --> 00:09:17.546 align:middle
If you want to make sure that a specific
page - or any page - doesn't make more than,

00:09:17.676 --> 00:09:22.606 align:middle
I don't know, 10 database queries,
you can add an "assertion" for that

00:09:22.606 --> 00:09:26.106 align:middle
and see a big failure if you break the rules.

