---
layout: documentation
title: Testing
---
- [Testing with fbp-spec](#testing-with-fbp-spec)
  - [Running fbp-spec](#running-fbp-spec)
  - [Writing fbp-spec tests](#writing-fbp-spec-tests)
- [Testing with Mocha](#testing-with-mocha)

## Testing with fbp-spec

fbp-spec is a test runner designed for testing any flow-based graphs or components. It provides a way to define tests in a data-driven way, with a fixture [graph](/documentation/graphs/), a set of input data to send to a component, and expectations on resulting output data.

* Read more: [fbp-spec usage guide](https://github.com/flowbased/fbp-spec#usage).

### Running fbp-spec tests

To run fbp-spec tests, you need two pieces: a NoFlo runtime, and the fbp-spec test runner. Install these as development dependencies in your project:

```bash
$ npm install noflo-nodejs fpb-spec --save-dev
```

fbp-spec runs the tests in the following way:

1. Load all fbp-spec `.yaml` files from your `spec/` folder
2. Start a NoFlo runtime with `noflo-nodejs`
3. For each test suite, start a NoFlo network, send input data, and run expectations on the results

All of the communications between fbp-spec and your NoFlo environment are done via the [FBP Network Protocol](https://flowbased.github.io/fbp-protocol/) meaning that they can run on different machines, tests can be executed against running NoFlo installations, and more.

However, the typical way is to use fbp-spec as the runner executed via NPM. Add it to the `scripts` section of your `package.json`:

```json
{
  "scripts": {
    "test": "fbp-spec --secret test --address ws://localhost:3333 --command 'noflo-nodejs --port 3333 --capture-output --secret test' spec/"
  }
}
```

Once you have some test files in your `spec/` folder, you can run them with:

```bash
$ npm test
```

### Writing fbp-spec tests

fbp-spec tests are defined in [YAML format](http://yaml.org/). At its simplest, you can define a test against a component or graph by just setting the test topic. So if you have a component `DoSomething`, create a file `spec/DoSomething.yaml` with the contents:

```yaml
topic: DoSomething
cases: []
```

When testing a basic component, you usually don't need a fixture graph. When you define the topic, fbp-spec knows how to expose it for testing. Test cases are written by providing a sequence of input data, and then expectations on output data. The file above with two simple test cases would look like:

```yaml
topic: DoSomething
cases:
-
  name: sending a boolean
  assertion: should repeat the same
  inputs:
    in: true
  expect:
    out:
     equals: true
-
  name: sending a number
  assertion: should repeat the same
  inputs:
    in: 1000
  expect:
    out:
      equals: 1000
```

Read more in [writing fbp-spec tests](https://github.com/flowbased/fbp-spec#writing-tests).

## Testing with Mocha

In addition to testing tools tailored for flow-based program testing, you can of course test NoFlo components or graphs with regular JavaScript testing frameworks like [Mocha](https://mochajs.org/).

The easiest way to run a NoFlo component in Mocha is to use [NoFlo's `asCallback` method](/documentation/embedding) which wraps a component or graph into a simple callback function.

Here is an example:

```javascript
const noflo = require('noflo');
let baseDir = 'my-project';
if (!noflo.isBrowser()) {
  // Tests are running on Node.js, load chai and set project baseDir to project root
  const chai = require('chai');
  const path = require('path');
  baseDir = path.resolve(__dirname, '../');
}

describe('My component', () => {
  // Wrap your component into a function
  let mycomp = null;
  before(() => {
    // We need to provide the name of the component/graph we're
    // testing, and the project basedir where NoFlo looks for
    // components
    mycomp = noflo.asCallback('my_project/MyComponent', {
      baseDir: baseDir,
    });
  });
  // Then run it inside your tests
  it('should add one to the data it receives', (done) => {
    mycomp(1, (err, result) => {
      // If there was an error, fail the test
      if (err) { return done(err); }
      // Test the result
      chai.expect(result).to.equal(2);
      done()
    });
  });
});
```
