HATT is a tool, and a pattern, for testing HTTP APIs (RESTful or otherwise). It can be used to construct fully automated tests, and also provides support for simple manual testing.
HATT is a Ruby tool and gem. It leverages the full power of Ruby. That said, HATT should be usable by those with little familiarity of Ruby, but some knowledge of scripting languages in general. HATT works with standard Ruby testing frameworks like RSpec and MiniTest.
- Easily configure and interact with one or more HTTP services (RESTful services).
- "Point" tests and requests at various deployment environments (eg, QA, Staging, Production)
- Using RSpec or MiniTest or any other testing framework, construct fully automated tests.
- Easily define a "DSL", or domain-specific-language for interacting with your API in your own terms. This allows for writing self-documenting, easy to understand tests.
- Easily integrates into popular Continuos Integration tools like Jenkins. This means your tests can run on a central server where all team members can access them.
The code for this entire example lives at [https://github.com/rschultheis/hatt_example]. Looking through that project shows examples of using nearly every hatt feature, and examples of many kinds of tests and assertions against APIs.
This example is based on a free API: OpenWeatherMap. While the API is free, one must sign-up for an API key here: [http://openweathermap.org/appid]. Keep your API key handy you will need it soon...
gem install hatt
mkdir open_weather_map_api_test_suite
cd open_weather_map_api_test_suite
hatt_services:
# shothand of owm for "open weather map api"
owm:
url: http://api.openweathermap.org
We need a special place to put our API key. For that make a file called hatt.secret.yml. This is a file that is generally not to be checked into source control, it should be used for configuring any secrets (like API keys or passwords). Put this one line into the file:
owm_app_id: <your api key here>
mkdir hattdsl
def weather_for city
owm.get "/data/2.5/weather?q=#{URI.encode(city)}&APPID=#{appid}"
end
def appid
hatt_configuration['owm_app_id']
end
hatt -v weather_for "Pleasantville, NY"
And that returns something like this:
... <detailed logging showing full request / response>
D: [06/14/17 17:07:53][hatt] - HATT method 'weather_for' returned:
{"coord"=>{"lon"=>-73.79, "lat"=>41.13}, "weather"=>[{"id"=>800, "main"=>"Clear", "description"=>"clear sky", "icon"=>"01d"}], "base"=>"stations", "main"=>{"temp"=>299.68, "pressure"=>1014, "humidity"=>39, "temp_min"=>296.15, "temp_max"=>303.15}, "visibility"=>16093, "wind"=>{"speed"=>4.1, "deg"=>190}, "clouds"=>{"all"=>1}, "dt"=>1497480900, "sys"=>{"type"=>1, "id"=>1980, "message"=>0.0057, "country"=>"US", "sunrise"=>1497432119, "sunset"=>1497486575}, "id"=>5131757, "name"=>"Pleasantville", "cod"=>200}
So, at this point we are able to call the API, and see the full details of the request and response. We can manually test a lot at this point. But HATT can do more....
[
'New York, NY',
'Toronto, Canada',
'Paris, France',
'Tokyo, Japan',
'Sydney, Australia',
].each do |city|
weather = weather_for city
kelvin = weather['main']['temp']
celcius = (kelvin - 273.15).round
puts "#{city}: #{celcius} celcius"
end
hatt -q -f temperatures.rb
And get this nice output (-q supresses all the detailed request/response logging, leaving only the puts in the script):
New York, NY: 18 celcius
Toronto, Canada: 7 celcius
Paris, France: 18 celcius
Tokyo, Japan: 16 celcius
Sydney, Australia: 14 celcius
Using the included Hatt::Mixin and Hatt::SingletonMixin module, testing an api becomes easy. Lets setup a simple RSpec example here.
gem install rspec
mkdir spec
require 'hatt'
RSpec.configure do |config|
config.include Hatt::SingletonMixin
config.before(:all) do
hatt_initialize
end
end
require 'spec_helper'
describe "getting weather reports" do
it "should know the weather for New York City" do
response = weather_for 'New York, NY'
expected_items = ['temp', 'temp_min', 'temp_max', 'humidity', 'pressure']
# the actual assertions here
expect(response['main'].keys).to include(*expected_items)
# the temp is in kelvin, so it looks kinda wierd
expect(response['main']['temp']).to be_between(100, 400)
end
end
rspec
And get back:
... <detailed logging showing all request response details> ...
1 example, 0 failures
And THAT is the basic way to use HATT to test an API.
For more information, and more detailed examples of how to do nearly anything using HATT, see the example project: [https://github.com/rschultheis/hatt_example]