Add API documentation (#447)
parent
3612a815e6
commit
f2cdb63498
@ -0,0 +1,368 @@ |
||||
# Solidity-Coverage API Documentation |
||||
|
||||
`solidity-coverage`'s API provides test coverage measurement for the Solidity language. |
||||
The repository contains two complete coverage tool/plugin implementations (for Buidler and Truffle) |
||||
which can be used as sources if you're building something similar. |
||||
|
||||
`solidity-coverage`'s core algorithm resembles the one used by [Istanbul][3] for javascript programs. |
||||
It tracks line and branch locations by 'instrumenting' solidity contracts with special solidity |
||||
statements and detecting their execution in a coverage-enabled EVM. As such, its API spans the |
||||
full set of tasks typically required to run a solidity test suite. |
||||
|
||||
+ compile |
||||
+ ethereum client launch |
||||
+ test |
||||
+ report outcome and exit |
||||
|
||||
[3]: https://github.com/gotwarlost/istanbul |
||||
|
||||
The API's corresponding methods are: |
||||
|
||||
+ `instrument`: Rewrites contracts for instrumented compilation. Generates an instrumentation data map. |
||||
+ `ganache`: Launches a ganache client with coverage collection enabled in its VM. As the client |
||||
runs it will mark line/branch hits on the instrumentation data map. |
||||
+ `report`: Generates a coverage report from the data collected by the VM after tests complete. Converts |
||||
the instrumentation data map into an object IstanbulJS can process. |
||||
+ `finish`: Shuts client down |
||||
|
||||
The library also includes some file system [utilities](#Utils) which are helpful for managing the |
||||
disposable set of contracts/artifacts which coverage must use in lieu of the 'real' contracts/artifacts. |
||||
|
||||
# Table of Contents |
||||
|
||||
- [API Methods](#api) |
||||
* [constructor](#constructor) |
||||
* [instrument](#instrument) |
||||
* [ganache](#ganache) |
||||
* [report](#report) |
||||
* [finish](#finish) |
||||
* [getInstrumentationData](#getinstrumentationdata) |
||||
* [setInstrumentationData](#setinstrumentationdata) |
||||
- [Utils Methods](#utils) |
||||
* [loadSolcoverJS](#loadsolcoverjs) |
||||
* [assembleFiles](#assemblefiles) |
||||
* [getTempLocations](#gettemplocations) |
||||
* [setupTempFolders](#setuptempfolders) |
||||
* [save](#save) |
||||
* [finish](#finish-1) |
||||
|
||||
# API |
||||
|
||||
**Example** |
||||
```javascript |
||||
const CoverageAPI = require("solidity-coverage/api"); |
||||
const api = new CoverageAPI(options); |
||||
``` |
||||
|
||||
## constructor |
||||
|
||||
Creates a coverage API instance. Configurable. |
||||
|
||||
**Parameters** |
||||
|
||||
- `options` **Object** : API options |
||||
|
||||
| Option <img width=200/>| Type <img width=200/> | Default <img width=1300/> | Description <img width=800/> | |
||||
| ------ | ---- | ------- | ----------- | |
||||
| port | *Number* | 8555 | Port to launch client on | |
||||
| silent | *Boolean* | false | Suppress logging output | |
||||
| client | *Object* | `require("ganache-core")` | JS Ethereum client | |
||||
| providerOptions | *Object* | `{ }` | [ganache-core options][1] | |
||||
| skipFiles | *Array* | `[]` | Array of contracts or folders (with paths expressed relative to the `contracts` directory) that should be skipped when doing instrumentation. | |
||||
| istanbulFolder | *String* | `./coverage` | Folder location for Istanbul coverage reports. | |
||||
| istanbulReporter | *Array* | `['html', 'lcov', 'text', 'json']` | [Istanbul coverage reporters][2] | |
||||
|
||||
[1]: https://github.com/trufflesuite/ganache-core#options |
||||
[2]: https://istanbul.js.org/docs/advanced/alternative-reporters/ |
||||
|
||||
-------------- |
||||
|
||||
## instrument |
||||
|
||||
Instruments a set of sources to prepare them for compilation. |
||||
|
||||
:warning: **Important:** Instrumented sources must be compiled with **solc optimization OFF** :warning: |
||||
|
||||
**Parameters** |
||||
|
||||
- `contracts` **Object[]**: Array of solidity sources and their paths |
||||
|
||||
Returns **Object[]** in the same format as the `contracts` param, but with sources instrumented. |
||||
|
||||
**Example** |
||||
```javascript |
||||
const contracts = [{ |
||||
source: "contract Simple { uint x = 5; }", |
||||
canonicalPath: "/Users/user/project/contracts/Simple.sol", |
||||
relativePath: "Simple.sol" // Optional, used for pretty printing. |
||||
},...] |
||||
|
||||
const instrumented = api.instrument(contracts) |
||||
``` |
||||
|
||||
-------------- |
||||
|
||||
## ganache |
||||
|
||||
Enables coverage data collection on an in-process ganache server. By default, will return |
||||
a url after server has begun listening on the port specified in the [config](#constructor) |
||||
(or 8555 by default). When `autoLaunchServer` is false, method returns`ganache.server` |
||||
so the consumer can control the 'server.listen' invocation themselves. |
||||
|
||||
**Parameters** |
||||
|
||||
- `client` **Object**: (*Optional*) ganache module |
||||
- `autoLaunchServer` **Boolean**: (*Optional*) |
||||
|
||||
Returns **Promise** Address of server to connect to, or initialized, unlaunched server |
||||
|
||||
**Example** |
||||
```javascript |
||||
const client = require('ganache-cli'); |
||||
|
||||
const api = new CoverageAPI( { client: client } ); |
||||
const address = await api.ganache(); |
||||
|
||||
> http://127.0.0.1:8555 |
||||
|
||||
// Alternatively... |
||||
|
||||
const server = await api.ganache(client, false); |
||||
await pify(server.listen()(8545)); |
||||
``` |
||||
|
||||
-------------- |
||||
|
||||
## report |
||||
|
||||
Generates coverage report using IstanbulJS |
||||
|
||||
**Parameters** |
||||
|
||||
- `istanbulFolder` **String**: (*Optional*) path to folder IstanbulJS will deposit coverage reports in. |
||||
|
||||
Returns **Promise** |
||||
|
||||
**Example** |
||||
```javascript |
||||
await api.report('./coverage_4A3cd2b'); // Default folder name is 'coverage' |
||||
``` |
||||
|
||||
------------- |
||||
|
||||
## finish |
||||
|
||||
Shuts down coverage-enabled ganache server instance |
||||
|
||||
Returns **Promise** |
||||
|
||||
**Example** |
||||
```javascript |
||||
const client = require('ganache-cli'); |
||||
|
||||
await api.ganache(client); // Server listening... |
||||
await api.finish(); // Server shut down. |
||||
``` |
||||
|
||||
------------- |
||||
|
||||
## getInstrumentationData |
||||
|
||||
Returns a copy of the hit map created during instrumentation. Useful if you'd like to delegate |
||||
coverage collection to multiple processes. |
||||
|
||||
Returns **Object** instrumentation data; |
||||
|
||||
|
||||
**Example** |
||||
```javascript |
||||
const contracts = api.instrument(contracts); |
||||
const data = api.getInstrumentationData(); |
||||
save(data); |
||||
``` |
||||
|
||||
------------- |
||||
|
||||
## setInstrumentationData |
||||
|
||||
Sets the hit map object generated during instrumentation. Useful if you'd like |
||||
to collect or convert data to coverage for an instrumentation which was generated |
||||
in a different process. |
||||
|
||||
**Example** |
||||
```javascript |
||||
const data = load(data); |
||||
api.setIntrumentationData(data); |
||||
|
||||
// Client will collect data for the loaded map |
||||
const address = await api.ganache(client); |
||||
|
||||
// Or to `report` instrumentation data which was collected in a different process. |
||||
const data = load(data); |
||||
api.setInstrumentationData(data); |
||||
|
||||
api.report(); |
||||
``` |
||||
|
||||
---------------------------------------------------------------------------------------------------- |
||||
|
||||
# Utils |
||||
|
||||
```javascript |
||||
const utils = require('solidity-coverage/utils'); |
||||
``` |
||||
|
||||
Many of the utils methods take a `config` object param which |
||||
defines the absolute paths to your project root and contracts directory. |
||||
|
||||
**Example** |
||||
```javascript |
||||
const config = { |
||||
workingDir: process.cwd(), |
||||
contractsDir: path.join(process.cwd(), 'contracts'), |
||||
} |
||||
``` |
||||
------------- |
||||
|
||||
## loadSolcoverJS |
||||
|
||||
Loads `.solcoverjs`. Users may specify options described in the README in `.solcover.js` config |
||||
file which your application needs to consume. |
||||
|
||||
**Parameters** |
||||
|
||||
- `config` **Object**: [See *config* above](#Utils) |
||||
|
||||
Returns **Object** Normalized coverage config |
||||
|
||||
|
||||
**Example** |
||||
```javascript |
||||
const solcoverJS = utils.loadSolcoverJS(config); |
||||
const api = new CoverageAPI(solcoverJS); |
||||
``` |
||||
|
||||
------------- |
||||
|
||||
## assembleFiles |
||||
|
||||
Loads contracts from the filesystem in a format that can be passed directly to the |
||||
[api.instrument](#instrument) method. Filters by an optional `skipFiles` parameter. |
||||
|
||||
**Parameters** |
||||
|
||||
- `config` **Object**: [See *config* above](#Utils) |
||||
- `skipFiles` **String[]**: (*Optional*) Array of files or folders to skip |
||||
[See API *constructor*](#constructor) |
||||
|
||||
Returns **Object** with `targets` and `skipped` keys. These are Object arrays of contract sources |
||||
and paths. |
||||
|
||||
**Example** |
||||
```javascript |
||||
const { |
||||
targets, |
||||
skipped |
||||
} = utils.assembleFiles(config, ['Migrations.sol']) |
||||
|
||||
const instrumented = api.instrument(targets); |
||||
``` |
||||
|
||||
-------------- |
||||
|
||||
## getTempLocations |
||||
|
||||
Returns a pair of canonically named temporary directory paths for contracts |
||||
and artifacts. Instrumented assets can be compiled from and written to these so the unit tests can |
||||
use them as sources. |
||||
|
||||
**Parameters** |
||||
|
||||
- `config` **Object**: [See *config* above](#Utils) |
||||
|
||||
Returns **Object** with two absolute paths to disposable folders, `tempContractsDir`, `tempArtifactsDir`. |
||||
These directories are named `.coverage_contracts` and `.coverage_artifacts`. |
||||
|
||||
**Example** |
||||
```javascript |
||||
const { |
||||
tempContractsDir, |
||||
tempArtifactsDir |
||||
} = utils.getTempLocations(config) |
||||
|
||||
utils.setupTempFolders(config, tempContractsDir, tempArtifactsDir) |
||||
|
||||
// Later, you can call `utils.finish` to delete these... |
||||
utils.finish(config, api) |
||||
``` |
||||
|
||||
---------- |
||||
|
||||
## setupTempFolders |
||||
|
||||
Creates temporary directories to store instrumented contracts and their compilation artifacts in. |
||||
|
||||
**Parameters** |
||||
|
||||
- `config` **Object**: [See *config* above](#Utils) |
||||
- `tempContractsDir` **String**: absolute path to temporary contracts directory |
||||
- `tempArtifactsDir` **String**: absolute path to temporary artifacts directory |
||||
|
||||
**Example** |
||||
```javascript |
||||
const { |
||||
tempContractsDir, |
||||
tempArtifactsDir |
||||
} = utils.getTempLocations(config) |
||||
|
||||
utils.setupTempFolders(config, tempContractsDir, tempArtifactsDir); |
||||
``` |
||||
------------- |
||||
|
||||
## save |
||||
|
||||
Writes an array of instrumented sources in the object format returned by |
||||
[api.instrument](#instrument) to a temporary directory. |
||||
|
||||
**Parameters** |
||||
|
||||
- `contracts` **Object[]**: array of contracts & paths generated by [api.instrument](#instrument) |
||||
- `originalDir` **String**: absolute path to original contracts directory |
||||
- `tempDir` **String**: absolute path to temp contracts directory (the destination of the save) |
||||
|
||||
**Example** |
||||
```javascript |
||||
const { |
||||
tempContractsDir, |
||||
tempArtifactsDir |
||||
} = utils.getTempLocations(config) |
||||
|
||||
utils.setupTempFolders(config, tempContractsDir, tempArtifactsDir); |
||||
|
||||
const instrumented = api.instrument(targets); |
||||
|
||||
utils.save(instrumented, config.contractsDir, tempContractsDir); |
||||
``` |
||||
|
||||
------------- |
||||
|
||||
## finish |
||||
|
||||
Deletes temporary folders and shuts the ganache server down. Is tolerant - if folders or ganache |
||||
server don't exist it will return silently. |
||||
|
||||
**Parameters** |
||||
|
||||
- `config` **Object**: [See *config* above](#Utils) |
||||
- `api` **Object**: (*Optional*) coverage api instance whose own `finish` method will be called |
||||
|
||||
Returns **Promise** |
||||
|
||||
**Example** |
||||
```javascript |
||||
await utils.finish(); |
||||
``` |
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in new issue