runas-core
Version:
The adhesive orchestrator
313 lines (231 loc) • 8.84 kB
Markdown
---
title: Testing
layout: doc_page.html
order: 16
---
# Testing Runas
There are to ways to test runas recipes: `unit testing` and `functional testing (integration)`. Both could be functional but the main difference is that `unit testing` runs as a node library inside the test and `functional testing (integration)` runs the recipe as a system executable using require('child_process').exec.
1. [Unit Testing](#unitTesting)
1. [Functional Testing (integration)](#functionalTesting)
## <a name="unitTesting"></a> Unit testing
1. [Testing steps](#testingSteps)
1. [Testing plugins](#testingPlugins)
1. [Testing contexts](#testingContexts)
Needed to test `steps`, `plugins` (coming soon) and `contexts` (coming soon)
- These tests reside on the `test` folder of a recipe module.
- It just needs the recipe to be tested and its dependencies.
- You could generate coverage with this kind of tests
### <a name="testingSteps"></a> Testing steps
Steps only need dependency to runas on devDependencies. Add dependencies to mocha and chai too.
`NOTE:` If you need a context definition for the step execution, then the dependency to the context has to be on devDependencies too. for example `runas-contexts`
package.json:
```json
{
"...":"...",
"scripts": {
"deps": "npm install",
"test": "node_modules/.bin/mocha -u tdd --recursive"
},
"devDependencies": {
"chai": "*",
"mocha": "*",
"runas": "^1.0.0"
},
"...":"..."
}
```
Writing a test for runas. First require stepTester
```javascript
const tester = require('runas/lib/tests/stepTester');
```
1. [command object](#command)
1. [setLoggerLevel(level) method](#setLoggerLevel)
1. [loadStep(command) method](#loadStep)
1. [runStep(command) method](#runStep)
#### <a name="command"></a>command object.
The command object is the configuration parameter that runas uses to run the test.
| Param | Type | Optional | Description |
| --- | --- | --- | --- |
| name | String | No | The name of the step |
| context | Array | Yes | Array of the contexts runned |
| baseDir | String | Yes | Folder where the step is going to be runned. Default is the root of the recipe. |
| params | Object | Yes | All params passed for the execution |
#### <a name="setLoggerLevel"></a>setLoggerLevel(level) method
`logger.setLoggerLevel(level)` set logger level for runas. [See logger for more information](./14-logger.md)
| Param | Type | Optional | Description |
| --- | --- | --- | --- |
| level | Number | No | 0...5 log levels |
#### <a name="loadStep"></a>loadStep(command) method
`logger.loadStep(command)` Load local step with all plugins and all runas configuration. **Returns** step object with all runas features loaded.
| Param | Type | Optional | Description |
| --- | --- | --- | --- |
| command | Object | No | See [command object](#command) |
#### <a name="runStep"></a>runStep(command) method
`logger.runStep(command)` Run one local step from the recipe. **Returns** a promise with the execution of the step.
| Param | Type | Optional | Description |
| --- | --- | --- | --- |
| command | Object | No | See [command object](#command) |
This is a example of an entire test file.
```javascript
'use strict';
const path = require('path');
const tester = require('runas/lib/tests/stepTester');
const expect = require('chai').expect;
const assert = require('assert');
/* global define, it, describe, before, beforeEach, afterEach, after */
// configure
tester.setLoggerLevel(0);
// constants
const stepName = 'askHello';
const contexts = ['world'];
const message = 'Unit Framework hola!';
describe('Unit testing framework for askHello step', () => {
it('Should return the step to test', (done) => {
const step = tester.loadStep({
name: stepName,
context: contexts
});
expect(step).not.equal(null);
expect(step.name).to.equal(stepName);
done();
});
it('Should run the step to test', (done) => {
tester.setLoggerLevel(0);
tester.runStep({
name: stepName,
context: contexts,
baseDir: path.join(__dirname, 'world'),
params: {
paramInquire: message
}
})
.then(() => {
done();
})
.catch((err) => {
done(err);
})
});
it('Should run the step with plugins to test', (done) => {
tester.setLoggerLevel(0);
tester.runStep({
name: 'emittingHello',
context: contexts,
baseDir: path.join(__dirname, 'world'),
params: {
paramInquire: message
}
})
.then(() => {
done();
})
.catch((err) => {
done(err);
})
});
});
```
### <a name="testingPlugins"></a> Testing plugins
(comming soon)
### <a name="testingContexts"></a> Testing contexts
(comming soon)
## <a name="functionalTesting"></a> Functional testing (integration)
1. [Configure the recipe](#configureRecipe)
1. [Writing tests](#writeTest)
1. [Running tests](#runningTest)
The functional testing features are:
- It is used to test only recipes by executing externally all its commands.
- It is possible to test `flows` and `steps`.
- Executes the recipe command so a configured environment is needed.
- Tests are located on an external module, outside of the recipe. Test modules have to be dependencies of the recipe.
### <a name="configureRecipe"></a> Configuring the recipe for testing
1. Add `"test" : "bin/runas.js -ft"` to the `scripts` object in package.json.
1. Add dependencies to one or more functional-testing modules.
Fragment of package.json of a recipe.
```json
{
"scripts": {
"deps": "npm install",
"test": "bin/runas.js -ft"
},
"keywords": [
"runas-recipe"
],
"bin": {
"cells": "bin/runas.js"
},
"dependencies": {
"runas": "^1.1.0"
},
"devDependencies": {
"runas-functional-tests": "^1.0.1-beta"
},
"...":"..."
}
```
### <a name="writeTest"></a> Writing the tests (the functional testing module)
- This module must have `functional-tests` keyword
- Dependencies to testing frameworks should be on dependencies not on devDependencies
- Dependency to runas is not necessary.
Fragment of package.json of the functional testing module:
```json
{
"...":"...",
"keywords": [
"functional-tests"
],
"dependencies": {
"chai": "*",
"mocha": "*"
},
"...":"..."
}
```
Now tests must execute the command `runasExec` that is injected as an environment variable.
This is an example of tests that we can be written. This test proves the creation of an app using cells-cli recipe.
```javascript
'use strict';
const pctp = require('runas-callback-to-promise');
const u = require('../utils');
const fs = require('fs-extra');
const path = require('path');
const exec = require('child_process').exec;
/* global define, it, describe, before, beforeEach, afterEach, after */
// constants
const baseApp = `${__dirname}/../tmp`;
// ---- Tests --------
describe('Run cells app:create', function() {
const allOk = '[ create ] finished';
this.timeout(6000);
it(`Should create a list of apps and say "${allOk}" on all apps`, function(done) {
pctp.c2p(fs.ensureDir, baseApp)
.then(() => pctp.c2p(exec, `${process.env.runasExec} app:create --scaffoldDir scaffold --appName test-app`, {cwd: baseApp}))
.catch((err) => pctp.logError(err, done));
});
afterEach('Should delete the tmp directory', (done) => {
u.remove([ baseApp ])
.then(() => done());
});
});
```
Let's see this example:
- Note that executable is a env variable: `process.env.runasExec`
- We are using pctp module that converts callbacks to promises.
### <a name="runningTest"></a> Running functional tests
- From the recipe just with `npm test` or `bin/runas.js -ft`
- In the functional testing module just executing mocha. First is needed to export the runasExec parameter to environment:
```bash
export runasExec="node /Users/sbonacho/projects/cells-cli/bin/runas.js"
mocha -u tdd --recursive test --timeout 5000 --grep "Unit testing framework for askHello step"
```
`NOTE:` Is possible to test docker by changing `runasExec` value:
```bash
export runasExec="docker run -ti --rm -p 8000-8100:8000-8100 -p 3000-3100:3000-3100 -v ~/.gradle:/home/runas/.gradle -v ~/.bowerrc:/home/runas/.bowerrc -v ~/.npmrc:/home/runas/.npmrc -v ~/.netrc:/home/runas/.netrc -v ~/.ssh:/home/runas/.ssh -v `pwd`:/home/runas/workspace runas/cells-bundle"
```
The execution of `runas -ft` or `runas --functionalTests` starts with these messages on stdout. Showing the number of functional testing modules in the recipe, theirs names and versions.
```bash
[14:32:49] Number of functional testing modules detected: 1
[14:32:49] Executing runas functional tests from runas-functional-tests ( 1.0.15 )
Runas context world validation
✓ Should return ....
```