Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch coverage data sent to combineCoverage to prevent timeouts #877

Merged
Merged
2 changes: 2 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ workflows:
jobname:
- all-files
- backend
- batch-send-coverage
- before-all-visit
- before-each-visit
- cra-e2e-and-ct
Expand Down Expand Up @@ -174,6 +175,7 @@ workflows:
- test-code-coverage-plugin
- test-all-files
- test-backend
- test-batch-send-coverage
- test-before-all-visit
- test-before-each-visit
- test-cra-e2e-and-ct
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -549,14 +549,21 @@ Deeply nested objects will sometimes have `[object Object]` values printed. You
DEBUG_DEPTH=10 DEBUG=code-coverage npm run dev
```

### Common issues
## Common issues

Common issue: [not instrumenting your application when running Cypress](#instrument-your-application).

If the plugin worked before in version X but stopped after upgrading to version Y, please try the [released versions](https://github.com/cypress-io/code-coverage/releases) between X and Y to see where the breaking change was.

If you decide to open an issue in this repository, please fill in all information the [issue template](https://github.com/cypress-io/code-coverage/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) asks for. The issues most likely to be resolved have debug logs, screenshots, and hopefully public repository links so we can try running the tests ourselves.

### Coverage reporting timeouts

If the plugin times out when sending coverage report data to be merged, this may be due to a very large
report being sent across processes. You can batch the report by setting the `sendCoverageBatchSize` environment
variable in your `cypress.config.js` file's 'env' section. Assign the variable an integer value representing
the number of report keys to send per batch.

## Contributing

You can test changes locally by running tests and confirming that the code coverage has been calculated and saved.
Expand Down
14 changes: 13 additions & 1 deletion support-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,19 @@ function fixSourcePaths(coverage) {
})
}

/**
* Validates and returns the configured batch size for
* sending coverage to the backend
*/
function getSendCoverageBatchSize() {
const batchSize = Cypress.env('sendCoverageBatchSize')
const parsedBatchSize = parseInt(batchSize)
const isValid = !isNaN(parsedBatchSize) && parsedBatchSize > 0
return isValid ? parsedBatchSize : null
}

module.exports = {
fixSourcePaths,
filterFilesFromCoverage
filterFilesFromCoverage,
getSendCoverageBatchSize
}
40 changes: 35 additions & 5 deletions support.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

const dayjs = require('dayjs')
var duration = require('dayjs/plugin/duration')
const { filterFilesFromCoverage } = require('./support-utils')
const {
filterFilesFromCoverage,
getSendCoverageBatchSize
} = require('./support-utils')

dayjs.extend(duration)

Expand All @@ -16,10 +19,37 @@ const sendCoverage = (coverage, pathname = '/') => {

const totalCoverage = filterFilesFromCoverage(coverage)

// stringify coverage object for speed
cy.task('combineCoverage', JSON.stringify(totalCoverage), {
log: false
})
const envBatchSize = getSendCoverageBatchSize()
const keys = Object.keys(totalCoverage)

if (envBatchSize && envBatchSize < keys.length) {
sendBatchCoverage(totalCoverage, envBatchSize)
} else {
cy.task('combineCoverage', JSON.stringify(totalCoverage), {
log: false
})
}
}

/**
* Sends collected code coverage object to the backend code
* in batches via "cy.task".
*/
const sendBatchCoverage = (totalCoverage, batchSize) => {
const keys = Object.keys(totalCoverage)

for (let i = 0; i < keys.length; i += batchSize) {
const batchKeys = keys.slice(i, i + batchSize)
const batchCoverage = {}

batchKeys.forEach((key) => {
batchCoverage[key] = totalCoverage[key]
})

cy.task('combineCoverage', JSON.stringify(batchCoverage), {
log: false
})
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions test-apps/batch-send-coverage/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["istanbul"]
}
4 changes: 4 additions & 0 deletions test-apps/batch-send-coverage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Test Case: Batch Send Coverage
This test app tests that all expected files are covered when using
the `sendCoverageBatchSize` environment variable in the Cypress
configuration file.
14 changes: 14 additions & 0 deletions test-apps/batch-send-coverage/cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { defineConfig } = require('cypress')

module.exports = defineConfig({
fixturesFolder: false,
env: {
sendCoverageBatchSize: 1
},
e2e: {
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config)
},
baseUrl: 'http://localhost:1234'
}
})
24 changes: 24 additions & 0 deletions test-apps/batch-send-coverage/cypress/e2e/spec.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// <reference types="cypress" />
it('works', () => {
cy.visit('/')
cy.contains('Page body')

cy.window()
.invoke('reverse', 'super')
.should('equal', 'repus')

cy.window()
.invoke('numsTimesTwo', [1, 2, 3])
.should('deep.equal', [2, 4, 6])

cy.window()
.invoke('add', 2, 3)
.should('equal', 5)

cy.window()
.invoke('sub', 5, 2)
.should('equal', 3)

// application's code should be instrumented
cy.window().should('have.property', '__coverage__')
})
4 changes: 4 additions & 0 deletions test-apps/batch-send-coverage/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = (on, config) => {
require('@cypress/code-coverage/task')(on, config)
return config
}
1 change: 1 addition & 0 deletions test-apps/batch-send-coverage/cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@cypress/code-coverage/support'
1 change: 1 addition & 0 deletions test-apps/batch-send-coverage/cypress/support/e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./commands')
17 changes: 17 additions & 0 deletions test-apps/batch-send-coverage/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<body>
Page body
<script src="main.js"></script>
<script src="second.js"></script>
<script src="third.js"></script>
// use functions creates in "main.js"
if (add(2, 3) !== 5) {
throw new Error('wrong addition')
}
if (sub(2, 3) !== -1) {
throw new Error('wrong subtraction')
}
if (reverse('foo') !== 'oof') {
throw new Error('wrong string reverse')
}
</script>
</body>
3 changes: 3 additions & 0 deletions test-apps/batch-send-coverage/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
window.add = (a, b) => a + b

window.sub = (a, b) => a - b
Loading
Loading