Easily handle JSON in RSpec and Cucumber
Easily handle JSON in RSpec and Cucumber
json_spec defines five new RSpec matchers:
be_json_eqlinclude_jsonhave_json_pathhave_json_typehave_json_sizeThe new matchers could be used in RSpec as follows:
…json_spec also provides some useful helpers for RSpec tests:
parse_jsonnormalize_jsongenerate_normalized_jsonload_jsonTo start using them add an include them in your RSpec configuration:
RSpec.configure do |config|
config.include JsonSpec::Helpers
endYou can find usage examples for the helpers in spec/json_spec/helpers_spec.rb
json_spec ignores certain hash keys by default when comparing JSON:
idcreated_atupdated_atIt's oftentimes helpful when evaluating JSON representations of newly-created ActiveRecord records so that the new ID and timestamps don't have to be known. These exclusions are globally customizeable:
JsonSpec.configure do
exclude_keys "created_at", "updated_at"
endNow, the id key will be included in json_spec's comparisons. Keys can also be excluded/included
per matcher by chaining the excluding or including methods (as shown above) which will add or
subtract from the globally excluded keys, respectively.
Each of json_spec's matchers deal with JSON "paths." These are simple strings of "/" separated hash keys and array indexes. For instance, with the following JSON:
{
"first_name": "Steve",
"last_name": "Richert",
"friends": [
{
"first_name": "Catie",
"last_name": "Richert"
}
]
}We could access the first friend's first name with the path "friends/0/first_name".
json_spec provides Cucumber steps that utilize its RSpec matchers and that's where json_spec really shines. This is perfect for testing your app's JSON API.
In order to use the Cucumber steps, in your env.rb you must:
require "json_spec/cucumber"You also need to define a last_json method. If you're using Capybara, it could be as simple as:
def last_json
page.source
endNow, you can use the json_spec steps in your features:
…The background steps above aren't provided by json_spec and the "visit" steps are provided by Capybara. The remaining steps, json_spec provides. They're versatile and can be used in plenty of different formats:
…All instances of "should" above could be followed by "not" and all instances of "JSON" could be downcased and/or followed by "response."
Another step exists that uses Cucumber's table formatting and wraps two of the above steps:
Then the JSON should have the following:
| path/0 | {"key":"value"} |
| path/1 | ["entry","entry"] |Any number of rows can be given. The step above is equivalent to:
Then the JSON at "path/0" should be {"key":"value"}
And the JSON at "path/1" should be ["entry","entry"]If only one column is given:
Then the JSON should have the following:
| path/0 |
| path/1 |This is equivalent to:
Then the JSON should have "path/0"
And the JSON should have "path/1"There's one more Cucumber step that json_spec provides which hasn't been used above. It's used to memorize JSON for reuse in later steps. You can "keep" all or a portion of the JSON by giving a name by which to remember it.
Feature: User API
Scenario: Index action includes full user JSON
Given the following user exists:
| id | first_name | last_name |
| 1 | Steve | Richert |
And I visit "/users/1.json"
And I keep the JSON response as "USER_1"
When I visit "/users.json"
Then the JSON response should be:
"""
[
%{USER_1}
]
"""You can memorize JSON at a path:
Given I keep the JSON response at "first_name" as "FIRST_NAME"You can remember JSON at a path:
Then the JSON response at "0/first_name" should be:
"""
%{FIRST_NAME}
"""You can also remember JSON inline:
Then the JSON response at "0/first_name" should be %{FIRST_NAME}Check out the specs and features to see all the various ways you can use json_spec.
If you come across any issues, please tell us. Pull requests (with tests) are appreciated. No pull request is too small. Please help with:
If you report a bug and don't include a fix, please include a failing test.
Copyright © 2011 Steve Richert
See LICENSE for details.
No open issues yet, or sync has not completed.