Summarized using AI

Lightning Talk: Speeding Up Your Test Suite

Ankita Gupta • June 23, 2016 • Singapore • Lightning Talk

In this lightning talk, Ankita Gupta, a Full-Stack Software Engineer at Honestbee, discusses strategies for speeding up test suites, particularly focusing on RSpec and FactoryGirl to enhance testing efficiency. She emphasizes that while tests are invaluable for ensuring code quality, slow test execution can hinder developer productivity. Here are the main points covered in the talk:

  • Importance of Tests: Gupta opens with the acknowledgment that testing is crucial in software development, even though slow tests can be a significant drawback. She highlights how having tests has saved her from potential issues after making code changes.
  • Initial Problems: The speaker shares her experience where test cases in her team took as long as 35 minutes to run, which was drastically detrimental to workflow, especially when needing to repeatedly check results after minor changes.
  • Reduced Execution Time: Gupta details how she and her team improved test execution time to 10 minutes by implementing several key strategies:

    • Measurement of Test Speed: Emphasizing the need for effective measurement, she recommends using tools like Zeus or Spring to avoid the overhead of loading the Rails environment on each test run.
    • Database Management: She advises against unnecessary database cleaning since RSpec already manages transactions that can roll back changes. This adjustment alone reduced test time significantly.
    • Associations Optimization: Gupta stresses the importance of reusing test setups. By declaring and reusing associations, tests can avoid the overhead of generating unnecessary database records, resulting in faster execution.
    • Using FactoryGirl Options Wisely: Different strategies in FactoryGirl—such as 'build' and 'build_stubbed'—can vastly decrease the time taken for object creation in tests. Gupta illustrates how these simple changes can optimize the testing process more effectively.
    • Mocking External Calls: Finally, she recommends using mocks to simulate slow operations instead of executing real calls during tests. By doing so, her team managed to cut down overall test times immensely.
  • Concluding Thoughts: Gupta concludes the talk by showcasing that while reducing test execution times may seem daunting initially, implementing these strategies crossed a significant threshold of efficiency. She encourages attendees to explore these approaches to achieve faster and more reliable testing processes.

Overall, the session reiterated how efficient testing can dramatically enhance productivity in development cycles, allowing for quicker iteration and smoother project flows.

Lightning Talk: Speeding Up Your Test Suite
Ankita Gupta • June 23, 2016 • Singapore • Lightning Talk

Speaker: Ankita Gupta, Full-Stack Software Engineer, Honestbee

We often hear about Test Driven Development (TDD), and RSpec is a great aid in doing so. However what could be one of the biggest disadvantages of writing tests? The answer is slow tests. Yes, its true that if there were no tests then there would not be a slow test suite. But that's not the point. Tests are a developer's friend, and in this talk I will talk more about how to use FactoryGirl appropriately to speed up your RSpecs.

Speaker's Bio
Ankita is working as a full-stack software engineer at honestbee. In her free time, she works on her non-profit project Jugnuu, a low-cost, mobile-based English language solution for children.

Event Page: http://www.reddotrubyconf.com/

Produced by Engineers.SG

Help us caption & translate this video!

http://amara.org/v/ONqX/

Red Dot Ruby Conference 2016

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
Explore all talks recorded at Red Dot Ruby Conference 2016
+17