# Testing API Requests

You have defined your API in `swagger.yaml`, provided a detailed [schema](/flat/develop/reference/openapi-7/validation.md) and wrote [flows](/flat/develop/reference/openapi-4/routing.md) for API paths. How can we test the flows?

Let's say you have invented an incredibly useful API route that can tell whether a given number is odd.

## Example

`swagger.yaml`:

```yaml
swagger: '2.0'
basePath: /api
info:
  title: Useful Tools
  version: '1.0'
x-flat-validate:
  request: true
paths:
  /is-odd:
    get:
      x-flat-flow: odd.xml
      description: tells whether {number} is odd
      parameters:
      - name: number
        in: query
        required: true
        description: the number
        type: number
```

Flow in `odd.xml`:

```markup
<flow>
  <if test="$request/get/number = 0">
    <set-response-headers>
    {
      "see-also": "https://en.wikipedia.org/wiki/Parity_of_zero"
    }
    </set-response-headers>
  </if>

  <template>
  {
    "odd":  {{ $request/get/number mod 2 != 0 }}
  }
  </template>
</flow>
```

## Tests

Now let's test that! We could write a [sub-flow](/flat/develop/reference/actions/sub-flow.md) based test like in [Testing Templates](/flat/develop/cookbook/test-templates.md). But this time, we want to actually *call* our API to make sure that validation works, status codes are correct and so on.

The [`test-request` action](/flat/develop/reference/actions/test-request.md) does just that: You define the API `path` that should be called and all necessary [`request`](/flat/develop/reference/actions/request.md) parameters.

The `test-request` sets these variables so that you can easily inspect the result:

* `$status` the HTTP status code (number)
* `$response` the response body (string)
* `$headers` the response headers (array)

This is what we will use to assert that everything works as expected:

`tests/test-even.xml`:

```markup
<flat-test>
  <test-request>
  {
    "path": "/api/is-odd?number=4"
  }
  </test-request>

  <assert>
  [
    [ "$status", 200, "even is 200, too" ],
    [ "json-parse($response)/odd", false, "4 is not odd" ]
  ]
  </assert>
</flat-test>
```

Note that we have used `json-parse()` to check the `odd` property.

`tests/test-odd.xml`:

```markup
<flat-test>
  <test-request>
  {
    "path": "/api/is-odd?number=4711"
  }
  </test-request>

  <assert>
  [
    [ "$status", 200, "odd is 200" ],
    [ "json-parse($response)/odd", true, "4711 is odd" ]
  ]
  </assert>
</flat-test>
```

`tests/test-zero.xml`:

```markup
<flat-test>
  <test-request>
  {
    "path": "/api/is-odd?number=0"
  }
  </test-request>

  <assert>
  [
    [ "$status", 200 ],
    [ "json-parse($response)/odd", false, "zero is even" ],
    [ "$headers/see-also", "https://en.wikipedia.org/wiki/Parity_of_zero", "aha!" ]
  ]
  </assert>
</flat-test>
```

Run the tests with `flat test`:

```bash
$ flat test tests/*.xml
```

```
1..3
ok 1 GET /api/is-odd?number=4 (tests/test-even.xml): 2 assertions
ok 2 GET /api/is-odd?number=4711 (tests/test-odd.xml): 2 assertions
ok 3 GET /api/is-odd?number=0 (tests/test-zero.xml): 3 assertions
passed: 3, failed: 0
```

> 📝 **Exercise:** Add a test for negative numbers, for numbers with fractional parts (and correct the schema accordingly) and that also verifies that the `see-also` header is not set.

## See also

* [Testing Templates](/flat/develop/cookbook/test-templates.md) (cookbook)
* [Testing Upstream Requests](/flat/develop/cookbook/test-backend.md) (cookbook)
* [Test Framework](/flat/develop/reference/testing.md) (reference)
* [`test-request`](/flat/develop/reference/actions/test-request.md) (reference)
* [`assert`](/flat/develop/reference/actions/assert.md) (reference)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sevenval.gitbook.io/flat/develop/cookbook/test-api-request.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
