UNPKG

7.54 kBMarkdownView Raw
1# API Test
2
3API testing made simple
4
5## Install
6`npm install api-test --save-dev`
7
8## Usage
9Create a test file 'test/api-test/sample.md' to test the 'item/get' endpoint, like this:
10```
11# item/get
12## Setup
13### item in items
14 name: 'Salad'
15 price: 500
16## Invalid request
17### Post
18 randomId()
19### Out 400
20 error:
21 code: 200
22## Valid request
23### Post
24 item.id
25### Out
26 name: item.name
27 price: item.price
28```
29
30And in your mocha testing code:
31```javascript
32require('api-test')('test/api-test', {
33 mongoUri: 'mongodb://localhost:27017/api_test',
34 baseUrl: 'http://localhost:8000/'
35})
36```
37
38## Concepts
39Testing is, at the same time:
40
41* *very* great because it lets you trust code is ready for production!
42* extremely *boring* to write, because test code is dumb and repetitive
43
44This module tries to solve this by making testing code more concise and unifying testing and documentation.
45
46Markdown was choosen because it's easy to write/read and it's not code!
47
48## Test structure
49A test is divided in two parts:
50
51### Test setup
52This is an optional section called 'Setup' that lets you insert documents, declare variables and clear mongo collections to prepare the database before the test cases run.
53
54#### Inserting documents
55The syntax is simply:
56```
57### _docName_ in _collection_
58 _docDescription_
59```
60
61At the first insertion in a collection, it will be cleared. This is important to make every test isolated. You may refer to this object by its _docName_.
62
63The syntax for _docDescription_ is described bellow.
64
65Most of times, documents have a base strucuture with some default fields. You do not need to repeat yourself in this case, see the option `defaultDocuments` bellow.
66
67#### Clearing collections
68The syntax is simply:
69```
70### Clear _collection_
71```
72
73Use this only when you won't insert any document in that collection, but want it to be cleared.
74
75All documents in that collection will be removed, indexes will be kept
76
77#### Declaring variables
78You can declare and define a variable to use in test cases, db insertions and more:
79```
80### _varName_ is
81 _variableContent_
82```
83
84This will make _varName_ available to every following object block.
85
86### Test cases
87A test case has three optional sections:
88
89* `Post`: the JSON body to send by POST. Must start with a header like `### Post [_url_]`. Default: empty JSON object `{}`. The _url_ is optional and defaults to the test name
90* `Out`: the expected JSON output. Must start with a header like `### Out [_statusCode_]`. Default: no output checking. The _statusCode_ is optional and defaults to 200
91* `Finds`: optional DB assertions. Must start with a header like `### Find in _collection_`
92
93In all cases, the syntax is described bellow
94
95## Skipping test cases
96By appending ` (skip)` to a test case name (see an [example](https://github.com/clubedaentrega/api-test/blob/master/test/api-test/recursive/user-login.md#wrong-password-skip)) it will be simply ignored. This puts them in a pending state, and is favoured over removing tests which you may forget to add back again.
97
98You can also append ` (skip)` to a test file header (see an [example](https://github.com/clubedaentrega/api-test/blob/master/test/api-test/recursive/skip.md)) to skip the whole file.
99
100## Object syntax
101The syntax was designed to be concise and expressive. The values will be eval'ed as normal JS with a context with special variables (see `default context` bellow).
102
103The object can be a simple JS value, like:
104```
105new Date
106```
107
108Or an object with one property by line and tabs used to declare sub-objects:
109```
110user:
111 name:
112 first: 'Happy'
113 last: 'Customer'
114 age: 37 + 2
115 country: 'cm'.toUpperCase()
116```
117
118Or mixins, like:
119```
120user with name.first: 'Unhappy'
121```
122
123Learn more about the syntax in the file [doc-syntax.md](https://github.com/clubedaentrega/api-test/blob/master/doc-syntax.md)
124
125## Default context
126
127* `ObjectId()`: the mongo object id constructor
128* `randomId()`: return a random mongo-id as a 24-hex-char string
129* `randomStr([len=7], [alphabet=a-zA-Z0-9+/])`
130* `randomHex([len=7])`
131* `randomCode([len=7])`
132* `randomEmail([domain='example.com'])`
133* `randomUrl([base='http://example.com'])`
134* `random([min=0],[max=1])`
135* `randomInt([min=0],[max=100])`
136* `randomBool()`
137* `randomDate([interval=1day], [base=now])`
138* `randomOf(...values)`: return one of its arguments
139* `empty`: the empty object `{}`
140* `post`: the request body of the current test case
141* `out`: the response body of the current test case
142* `prev`: an object wity keys:
143 * `post`: the request body of the previous request
144 * `out`: the response body of the previous request
145
146## Options
147* `mongoUri`: the mongo uri to connect to. The hostname SHOULD be 'localhost' and the db name SHOULD contains 'test'. If not, the code will ask for confirmation. This protects one from dropping production data, since the tests automatically clear collections, before inserting docs.
148* `baseUrl`: the base API url. Every request url will be composed from this base and the test name.
149* `name`: (optional) the test name (given to root `describe(name, ...)` call)
150* `defaultDocuments`: (optional) the default structure for documents in each collection. See [issue #1](https://github.com/clubedaentrega/api-test/issues/1) for details
151* `describe`, `it`, `before`: (optional) the mocha interface. Defaults to global mocha functions
152* `context`: (optional) define your own variables/functions accessible to object definitions
153* `recursive`: (optional) whether to look for *.md files inside subfolders (default: false)
154* `strict`: (optional) whether the output check should be strict and complain about unexpected keys (default: true)
155* `ca`: (optional) CA certificate (useful when using a self-signed certificate in the server)
156* `ignoredFindKeys`: (optional) document keys to ignore in finds (default: `['_id', '__v']`)
157* `filterFile`: (optional) a function that will be called for every file and should return true if this file should be parsed
158* `preParse`: (optional) a function that will be called with all pre-parsed tokens (Header and Obj). This lets you do crazy stuff with the parsing if you want
159* for more low-level options, see `index.js`
160
161## Type checking
162
163If you don't know the exact value for an API response or field in the collection, you can check for its type:
164```
165## Testing types
166### Post
167 ...
168### Out
169 token: String
170### Find in users
171 password: String
172 lastLogin: Date
173```
174
175The valid type values are: `String`, `Number`, `Boolean`, `Object`, `Array`, `Date`, `RegExp`, `ObjectId`.
176
177## Custom context
178You can use custom context to help writing tests. All default context variables and methods will still be accessible (unless overwritten).
179
180For example: if all endpoints return errors like this: `{error: {code: _code_, message: _aDebugString_}}`, you can pass as context:
181```javascript
182options.context = {
183 error: function (code) {
184 return {
185 error: {
186 code: code,
187 message: String
188 }
189 }
190 }
191}
192```
193
194And then write a test case like this:
195```
196## Invalid email should give error 200
197### Post
198 user:
199 email: randomEmail()
200### Out
201 error(200)
202```
203
204Instead of repeating yourself with:
205```
206 error:
207 code: 200
208 message: String
209```
210
211## Examples
212See more test examples in the folder [test/api-test](https://github.com/clubedaentrega/api-test/tree/master/test/api-test)
213
214## Run test
215Run `npm test` in the project root folder.
\No newline at end of file