#tyr: test your REST
a node
test generator for API endpoints using mocha
and superagent
tyr is a test generator developed out of the frustration of writing redundant endpoint tests for APIs. if we build using conventions we should be able to use those conventions to mitigate redundancy in our applications, as well as share resources, like tests! assuming your routes are resource based and follow a convention like json-api, tyr will generate a series of mocha/superagent endpoint tests for your API.
examples IRL:
Týr is a greek god of law and and heroic glory. he martyred his hand in battle and we'll use that hand to make sure your API is heroically successful and convention based.
Tyr's hand is also a sweet Netrunner card.
tyr is comprised of 5 elements:
-
test_template.js
: the test suite templatethis contains
superagent
tests for (in order):POST /collection
: create an instance of a resourceGET /element/:id
: retrieve an instance of a resourceGET /collection
: retrieve a collection of resourcesPUT /element/:id
: update an instance of a resourceDELETE /element/:id
: delete an instance of a resource
-
tyr.js
: the test buildera node script that builds a test file for each resource in the
resources
array inconfig.js
using thetest_template.js
. each test file is deposited in the same location astyr.js
and is named<resource_name>_test.js
. -
config.js
: array of resources to generate tests for, api-server host, port, namespace -
/mocks
: a folder containing a mocks object for every resource to be tested -
db_utils.js
: a utility for reseting your db, requires a databaseconfig
file and aknexfile
in order to test a POST
and a PUT
, you will need 2 objects, respectively. when you create a resource for your application, create a file in /mocks
with the name of the resource. inside this file, export an object with two attributes: mock_resource
and mock_update
. these will be required in tyr.js
and each assigned, respectively, to variables of the same name.
the last task here is to set the update_attr
variable. this variable represents the attribute that is being update between the mock_resource
and the mock_update
. this variable should be set as a string. this is important because it determines what the tests will check after the PUT
test. you can see the code for that here on line 69 of test_template.js
.
for example:
// /mocks/books.js
var mock_resource = {
author_id: 1,
title: "Spacecats! An astronomical tutorial on building single page web applications with AngularJS",
date_published: "jan 1 2015"
};
var mock_update = {
author_id: 1,
title: "Spacecats! An astronomical tutorial on building single page web applications with AngularJS",
date_published: "jan 30 2015"
};
var update_attr = "date_published";
exports.mock_resource = mock_resource;
exports.mock_update = mock_update;
exports.update_attr = update_attr;
the config.js
file in tyr is where you will specify the host
, port
, and namespace
for your API server.
additionally, and most importantly, this is where you list your resources. you should list the path to your resources as strings in the resources
array. tyr assumes that the path points to a folder named after the resource that contains a model.js
file.
be sure to add your resources in the correct order according to their relations. this is critical, as most APIs built on relational databases define the related resource_id
attribute on a resource as non-nullable. if you put them in the wrong order, and you have related resources, the tests should fail immediately, as the POST
in the beforeEach
of the tests will fail.
an example:
// /test/config.js
module.exports = {
host: 'http://0.0.0.0',
port: ':8080',
namespace: '/api/1/',
resources: ['authors', 'books', 'chapters', 'series']
};
because a book
resource requires an author_id
, if books were listed first, the POST
would fail because no author
resources would exist.
in order for the tests to be accurate, it's best we reset our DB before each test. db_utils.js
has a utility function for doing just this.
this utility, as it is written in the included file, assumes that you are using knex
and bookshelf
. at the top of the file, point the constant DB
to a require
of your bookshelf config file, and point the constant config
to a require
of your knexfile
.
for example:
// db_utils.js
const DB = require('../api/classes/database');
const config = require('../knexfile');
// .. rest of file
if you are using something different for SQL queries and/or an ORM, simply rewrite the file to export a reset()
function, as this is all that tyr anticipates. for a closer look: the util is required on line 15 of test_template.js
and the reset
function is used on line 18 of test_template.js
.
you're all done! step 1, 2, and 3 are all that's required to get a base set of endpoints tests for each resource in your API.
- build the tests:
node tyr.js
- run the tests:
mocha <resource_name>_test.js
we recommend that you automate the running of all the tests so that you don't have to manually run each. however, we do believe that having generated each suite individually is important. you may want to debug a single resource and having to run a whole set of tests each time can be a pain. additionally, now you can reuse your models/endpoints and have a test suite that's portable :)