Discovering superfluous API requests in your test suite
NOTE: this code assumes RSpec but the principles still apply in other test frameworks.
You may find yourself in the situation where your project’s build is rapidly slowing down as the number of tests and code increases. In some cases this is a direct correlation with application code that consumes information from external APIs. There are many great resources in dealing with stubbing/mocking these external responses (see VCR, WebMock, etc) but this post focuses on identifying when particular external responses have become a burden on your test suite.
Let’s say you have a class in your code that GETs an HTTP response like so:
def response @response ||= Faraday.get('http://sushi.com/nigiri/sake.json') end
This response may get called any number of times in your application. The request is memoized so it won’t be executed more than once in the same instance of the class, however; there may be various times where this request is made unnecessarily during the test suite (particularly during integration tests). You may or may not find that your test suite is making a lot of extra HTTP requests that are unnecessary and slowing down the build.
One extremely simple way to find out A) How many times your particular HTTP request is being executed, and B) Where in your tests superfluous API requests are being made is to add a counter that can be incremented every time an API call is made.
Add this module into your rails_helper.rb
(or spec_helper.rb
if you’re on older versions of RSpec)
module APICounter mattr_accessor :count do 0 end end
In your RSpec.configure
block add
config.after(:suite) do puts "Total API requests: #{APICounter.count}" end
Then you can increment the counter in the code that makes the API request.
def response @response ||= begin APICounter.count += 1 Faraday.get('http://sushi.com/nigiri/sake.json') end end
This will give you the total number of times that API request was called in the test suite. You can also narrow down when API requests are made by printing some sort of statement when the API counter is increased and running the tests with a formatter that will show you which test was being run at the time.
def response @response ||= begin APICounter.count += 1 puts "API Request #{APICounter.count} Executed" Faraday.get('http://sushi.com/nigiri/sake.json') end end
$ rspec -f d
Now that you’ve identified the superfluous API requests you can work on eliminating them by stubbing them out in the cases where a legitimate response is not necessary.