00:00:14.839
hi everyone today I'm going to talk to
00:00:16.600
you about on the topic of test I'll talk
00:00:18.560
to you about speeding up your test Suite
00:00:21.279
uh so I'll show you an example on our
00:00:23.800
current uh codebase honb I work at hosp
00:00:27.160
and just a brief introduction we are a
00:00:29.439
online group grocery delivery services
00:00:31.080
company so we have a flexible Workforce
00:00:33.559
of drivers and Shoppers who we call as
00:00:35.559
bees and they are available so as in
00:00:38.079
when orders come in we dispatch it to
00:00:39.760
our flexible Workforce of bees and they
00:00:42.079
execute the orders so uh very quickly
00:00:44.480
I'll talk you through the use case that
00:00:46.120
I'll show you uh for the purposes of
00:00:49.440
tests first things first if there were
00:00:52.160
no tests there would be no slow test and
00:00:54.320
in that case we wouldn't really have to
00:00:56.199
spend so much time uh in today's talk or
00:00:58.760
you know ever writing test right but
00:01:01.239
then tests are important um how many of
00:01:04.360
us have had moments where we have
00:01:06.040
changed a line of code and then side and
00:01:08.119
said thank God there were tests for this
00:01:10.280
particular piece of code I certainly
00:01:12.840
have had many of those
00:01:14.600
moments and tests are not only important
00:01:17.280
they also need to be really fast true
00:01:20.240
fact there was a point in time where our
00:01:22.880
test cases took 35 minutes to run
00:01:25.479
doesn't seem like a big number but
00:01:27.240
imagine what the consequences every time
00:01:30.040
I make one line of code change I need to
00:01:32.439
wait for 35 minutes to make sure my
00:01:34.200
tests pass if something goes wrong if
00:01:36.560
there is a unstable test I wait for
00:01:38.799
another 35 minutes times the number of
00:01:40.920
developers in the company so that's
00:01:43.119
really a lot of time spent waiting for
00:01:44.640
test cases to run so we brought it down
00:01:47.759
to 10 minutes and we actually use really
00:01:49.960
simple steps to bring it down to that
00:01:52.079
that particular time frame so let's see
00:01:54.000
what those are before I get started uh
00:01:56.920
the test framework is our speec uh and
00:01:59.439
I'm using Factory girl for those of you
00:02:01.159
who haven't used Factory girl it's just
00:02:02.840
used to create model objects in your
00:02:04.759
test
00:02:06.360
fixtures so uh a very quick introduction
00:02:10.440
of our database so you understand uh how
00:02:12.319
the tests look later we have orders that
00:02:14.879
come in the orders come in uh and they
00:02:16.920
belong to many many different stores so
00:02:18.760
one order can have sub orders which we
00:02:20.480
call as Order fulfillments each of them
00:02:22.560
have stores that are basically Outlets
00:02:24.519
of a particular uh brand and then you
00:02:26.800
have the brand and you know you can
00:02:28.239
imagine that this goes on so there are
00:02:30.319
products and so on so that's how the
00:02:32.560
database looks
00:02:34.480
like all right so uh before I get
00:02:37.519
started I'm going to quickly load my uh
00:02:40.640
oh sorry before that let me just tell
00:02:42.640
you one thing uh in order to know
00:02:45.000
whether your tests are slow or fast the
00:02:46.680
first thing is to measure them and the
00:02:48.200
process of measurement has to be
00:02:49.680
painless and efficient and this is where
00:02:53.120
I really recommend you to try Zeus um or
00:02:55.879
spring so what happens in rails is that
00:02:58.000
every single time you run your test you
00:03:00.400
have to wait for your rails environment
00:03:01.879
to load every single time and so you
00:03:04.159
don't only wait for your test to load
00:03:05.640
but you also wait for your rails
00:03:06.680
environment which is kind of unnecessary
00:03:09.200
uh whereas what Zeus does is it allows
00:03:11.000
you to load your environment um once and
00:03:14.159
for all and then you can keep running
00:03:15.799
your test cases you can even run your
00:03:17.840
migrations but for the purposes of this
00:03:20.239
topic we'll talk about
00:03:22.319
tests okay before I talk about the
00:03:24.480
actual tips let me just uh quickly show
00:03:27.720
you what the uh scenario is and mean
00:03:29.959
I'll just start running the test because
00:03:31.360
they will be
00:03:33.319
slow okay so this is what my um oh okay
00:03:38.319
that's unfortunate I thought I could
00:03:40.200
show you my class um can I do that
00:03:47.879
actually
00:03:52.040
oops sorry technical
00:03:55.920
issues need to go to okay yeah yeah all
00:04:01.200
right so because this is this takes so
00:04:04.439
much time I'm just going to do it once
00:04:06.079
uh okay so basically this is my service
00:04:09.599
and what what the service does is it
00:04:11.200
sends out notification to our Shoppers
00:04:13.159
every single time they finish an order
00:04:14.879
and when they get the notification uh
00:04:17.280
they there's a bunch of uh numbers in
00:04:18.840
the notification that tell them how many
00:04:21.280
order uh how many items have they Sho
00:04:23.240
for which kind of indicates what's their
00:04:25.000
salary going to be so you see I just ran
00:04:27.280
my test cases and there's seven test
00:04:29.400
cases and they took about um over here
00:04:32.280
you'll see 22 seconds it's a little bit
00:04:34.000
slower but uh generally if you run run
00:04:35.960
it a couple of times it takes about uh
00:04:39.199
15 seconds not more than that so I'll
00:04:42.360
just go back to my presentation and from
00:04:43.919
here on I'll just uh show everything via
00:04:46.240
the presentation
00:04:54.960
itself all right so uh one thing that
00:04:59.600
that we did in our test cases was this
00:05:02.120
statement right here which is forceful
00:05:04.120
database clean now this seems a very
00:05:05.960
natural thing to do because you want to
00:05:07.919
make sure that every time you run your
00:05:09.199
tests you're running them on a very on a
00:05:11.160
clean database but this is not only very
00:05:13.880
expensive but it's also unnecessary
00:05:15.800
because rspec runs your test cases in a
00:05:17.880
transaction which is rolled back at the
00:05:19.520
end of the test so you actually don't
00:05:21.520
really need to do this and removing it I
00:05:24.520
intended to show it to you through by
00:05:26.080
running my test cases but uh trust me in
00:05:28.199
this it brings it down to 7 Seconds uh
00:05:30.880
which is 47% savings on what it was uh
00:05:34.240
previously about 15 15 seconds step
00:05:37.919
number three to declare and reuse your
00:05:40.680
associations now one common issue that
00:05:42.840
people have with Factory girl is that
00:05:45.000
you you saw the model that I showed you
00:05:46.680
just now which had order and Order
00:05:48.160
fulfillment now if I create an order
00:05:50.520
fulfillment uh which is basically the
00:05:52.600
small sub order but I don't specify the
00:05:54.600
order Factory girl will just end up
00:05:56.960
spinning new orders for each ful
00:05:59.440
fulfillment that I create and new stores
00:06:01.360
for each fulfillment and so on so you
00:06:02.919
can imagine that every Association that
00:06:04.520
I don't specify gets spun out and gets
00:06:06.840
created in the datab base and that's the
00:06:08.360
most expensive part of your tests as
00:06:10.240
well so what I typically do to deal with
00:06:13.000
this is uh I would declare a common you
00:06:15.960
know hook uh in our speec it's basically
00:06:18.280
something that runs before all your
00:06:19.759
examples and in that I will declare
00:06:21.840
anything that is you know going to be
00:06:24.120
initialized more often than once and
00:06:26.639
then in my test cases you see uh
00:06:29.919
uh I'll basically use it each time it's
00:06:32.479
the thing is misplaced but basically I
00:06:34.080
would use it for order uh I would reuse
00:06:36.400
an order inside the order fulfillment
00:06:38.319
every single time so when I do that in
00:06:41.240
my test cases um it comes down to 5
00:06:44.120
Seconds which is down from you know two
00:06:46.240
more seconds from 7
00:06:49.000
Seconds step number four use Bild St
00:06:52.479
until you really cannot use
00:06:54.479
it now what does that uh what does that
00:06:57.400
mean Factory girl has three different
00:06:59.400
different strategies one is create two
00:07:01.599
is build and three is build stop create
00:07:04.000
actually is the slowest because it act
00:07:05.840
it creates the object inside the
00:07:07.960
database build does not create it but
00:07:10.879
also does not give an ID so even though
00:07:13.080
your object is not created all the
00:07:14.840
associations that are linked to it will
00:07:16.280
be created in the database build stubbed
00:07:18.599
is like a sweet spot in between which
00:07:20.599
gives a mock ID to your object so your
00:07:22.120
associations can load and if your test
00:07:24.080
is not really doing any saves to the
00:07:25.840
database you are actually good to use
00:07:27.840
this option so
00:07:30.240
what I did here for example for two of
00:07:32.199
my uh two of my test cases I replaced
00:07:34.840
instead of actually creating an audit
00:07:36.199
fulfillment I just used a build stopped
00:07:38.440
and when I do that uh it does bring the
00:07:41.280
time a little bit down but this example
00:07:43.800
is a little contrived because I'm only
00:07:45.360
using it on two out of my seven specs so
00:07:47.319
it's only 4.8 seconds but if you choose
00:07:50.280
to use it more widely your cost savings
00:07:52.360
will be higher and one tip here would be
00:07:54.479
that sometimes I would just replace all
00:07:56.360
the creates with Bill stub in a
00:07:57.879
particular test suite and and then see
00:07:59.720
what fails and then go you know from
00:08:02.039
there I figure out whether I can use a
00:08:03.800
create or a build
00:08:05.240
stubbed step number five is to use mocks
00:08:07.840
and stuffs to imitate slow operations
00:08:10.039
and uh if you notice the test cases
00:08:13.080
previously there was a post request that
00:08:15.360
was being sent to the par application
00:08:17.479
that we used to send notifications to
00:08:19.319
our bees now this is really not
00:08:21.720
necessary again because one it's slow
00:08:24.080
and two if pars is down our test cases
00:08:26.680
fail again so it's better in such
00:08:28.879
situation patients to not do integration
00:08:31.120
test and and instead use mocks so you
00:08:34.719
basically just imitate uh what the
00:08:36.880
method should R return and you return
00:08:38.919
that instead and when I do that so you
00:08:41.279
see over here I do that and then when I
00:08:42.959
do that it brings it down to from to to
00:08:46.200
3 seconds so from 15 seconds it's come
00:08:49.120
down to 3 seconds which is 80% savings
00:08:51.480
on seven examples just in the last 7
00:08:54.160
minutes and so imagine when you try it
00:08:56.440
on all your different test cases across
00:08:58.320
your code base imagine the savings then
00:09:01.120
so try it out and also don't forget to
00:09:02.760
check out our jobs portal thank
00:09:09.600
you