Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ can be useful if you are using a different vm like the [sc-forks version of pyet
directory. `dir` allows you to define a relative path from the root directory to those assets.
`dir: "./<dirname>"` would tell solidity-coverage to look for `./<dirname>/contracts/` and `./<dirname>/test/`
+ **copyNodeModules**: *{ Boolean }* : When true, will copy `node_modules` into the coverage environment. False by default, and may significantly increase the time for coverage to complete if enabled. Only enable if required.
+ **skipFiles**: *{ Array }* : An array of contracts (with paths expressed relative to the `contracts` directory) that should be skipped when doing instrumentation. `Migrations.sol` is skipped by default, and does not need to be added to this configuration option if it is used.

**Example .solcover.js config file**
```javascript
Expand All @@ -97,7 +98,7 @@ the extra events. If this is the case, then the coverage may be incomplete. To a

**Using `require` in `migrations.js` files**: Truffle overloads Node's `require` function but
implements a simplified search algorithm for node_modules packages
([see Truffle issue #383](https://github.com/trufflesuite/truffle/issues/383)).
([see Truffle issue #383](https://github.com/trufflesuite/truffle/issues/383)).
Because solidity-coverage copies an instrumented version of your project into a temporary folder, `require`
statements handled by Truffle internally won't resolve correctly.

Expand Down
14 changes: 9 additions & 5 deletions bin/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const workingDir = config.dir || '.'; // Relative path to contracts folder
let port = config.port || 8555; // Port testrpc listens on
const accounts = config.accounts || 35; // Number of accounts to testrpc launches with
const copyNodeModules = config.copyNodeModules || false; // Whether we copy node_modules when making coverage environment
let skipFiles = config.skipFiles || []; // Which files should be skipped during instrumentation

// Silence shell and script logging (for solcover's unit tests / CI)
if (config.silent) {
Expand Down Expand Up @@ -89,7 +90,7 @@ try {
// Coverage network opts specified: use port if declared
if (truffleConfig && truffleConfig.networks && truffleConfig.networks.coverage) {
port = truffleConfig.networks.coverage.port || port;

// Coverage network opts NOT specified: default to the development network w/ modified
// port, gasLimit, gasPrice. Export the config object only.
} else {
Expand All @@ -114,18 +115,19 @@ try {
cleanUp(msg + err);
}

// For each contract except migrations.sol:
// For each contract except migrations.sol (or those in skipFiles):
// 1. Generate file path reference for coverage report
// 2. Load contract as string
// 3. Instrument contract
// 4. Save instrumented contract in the coverage environment folder where covered tests will run
// 5. Add instrumentation info to the coverage map
skipFiles = skipFiles.map(contract => `${coverageDir}/contracts/` + contract);
skipFiles.push(`${coverageDir}/contracts/Migrations.sol`);

let currentFile;
try {
shell.ls(`${coverageDir}/contracts/**/*.sol`).forEach(file => {
const migrations = `${coverageDir}/contracts/Migrations.sol`;

if (file !== migrations) {
if (!skipFiles.includes(file)) {
log('Instrumenting ', file);
currentFile = file;

Expand All @@ -135,6 +137,8 @@ try {
const instrumentedContractInfo = getInstrumentedVersion(contract, canonicalPath);
fs.writeFileSync(contractPath, instrumentedContractInfo.contract);
coverage.addContract(instrumentedContractInfo, canonicalPath);
} else {
log('Skipping instrumentation of ', file);
}
});
} catch (err) {
Expand Down
22 changes: 22 additions & 0 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,28 @@ describe('cli', () => {
collectGarbage();
});

it('contracts are skipped: should generate coverage, cleanup & exit(0)', () => {
// Skip instrumentation of some contracts
assert(pathExists('./coverage') === false, 'should start without: coverage');
assert(pathExists('./coverage.json') === false, 'should start without: coverage.json');
const testConfig = Object.assign({}, config);

testConfig.skipFiles = ['Owned.sol'];
mock.installInheritanceTest(testConfig);

shell.exec(script);
assert(shell.error() === null, 'script should not error');

assert(pathExists('./coverage') === true, 'script should gen coverage folder');
assert(pathExists('./coverage.json') === true, 'script should gen coverage.json');

const produced = JSON.parse(fs.readFileSync('./coverage.json', 'utf8'));
const firstKey = Object.keys(produced)[0];
assert(Object.keys(produced).length === 1, 'coverage.json should only contain instrumentation for one contract');
assert(firstKey.substr(firstKey.length - 9) === 'Proxy.sol', 'coverage.json should only contain instrumentation for Proxy.sol');
collectGarbage();
});

it('truffle tests failing: should generate coverage, cleanup & exit(1)', () => {
assert(pathExists('./coverage') === false, 'should start without: coverage');
assert(pathExists('./coverage.json') === false, 'should start without: coverage.json');
Expand Down