-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Code Coverage #346
Comments
There is nothing currently built into Cypress to do this. Adding code coverage around If you can supply the processes / code you used to add coverage via Protractor that would be helpful. The problem is that your typical JS It is possible to add code coverage to JS files served by a webserver though, so it's something we might be able to solve. IE: using something like this: https://github.com/gotwarlost/istanbul-middleware But in doing so, the problem is that it would have to be integrated at your server level, and is specific to each way you build your It may be possible for Cypress to do this at the network proxy level, but it would unlikely to be easy. |
In our application we actually used Karma along with Istanbul (karma-coverage) to calculate code coverage on our unit tests. We setup a Grunt task which uses the karma-coverage plugin to generate a coverage report on the unit tests. We have a karma config file similar to the one in the karma-coverage link above where we specify which JavaScript files to test. What we were hoping to do as an alternate to karma and karma-coverage is to just call Istanbul and Mocha directly (or use something else if more appropriate) on the tests. This does not work because cypress has some special variables (like cy) which are not recognized by Mocha. This is an example of how we would expect to call Istanbul and mocha if we were just using mocha directly, instead of cypress. So I think we are most interested in coverage for unit testing. |
@agduncan94 thanks for that explanation. To clarify - doing unit testing when it comes to code coverage is fairly straightforward and absolutely can be done. To date Cypress has been primarily used as With |
This might be a bit naïve, but would it be possible to use the new code coverage tool in the chrome dev tools to accomplish this? Admittedly, I haven't looked into it much, and it would only work in chrome for now. https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage |
There should be a way to instrument the tests to extract coverage and even export it to https://coveralls.io/ ( lemurheavy/coveralls-public#1023 ) Any chance to see this happening ? What do we need ? |
Cypress is open source, so you're welcome to take a look around to see what we'd need to do. Code coverage during e2e tests is completely different than unit tests. There is no dependency tree, there are 3rd party libs, and there is no access to the original source (even with source maps) due to the browser build process that every JS codebase undergoes. Cypress could theoretically instrument the code for you at the network layer, as its headed for the browser. But this has substantial challenges - it would be unidirectional, and we'd have no way of mapping the underlying built JS code back to the original (even with source maps its not enough). So while we could provide code coverage on the final built JS files, it would be mostly garbage from babel, typescript, or whatever else you're using to transpile. It would also include all of the 3rd party code you import in. All in all, not very useful. We'd likely need to expose and build an API on top of Cypress's backend process that your server could send the original source files which we could map against the transpiled versions to come up with a lightweight set of instrumented files. We could then use those to determine the standard code coverage. To be clear - this isn't a challenge as long as the code is instrumented properly, Cypress like every other tool could easily generate code coverage. The problem is that during e2e tests we receive the final built JS code where trying to go backwards to instrument is not really going to work. Another option is that your own webserver could send the instrumented code (that you'd have to manage yourself). After you do that, it would be fairly trivial to have Cypress be able to read off the instrumented reports after test execution and then aggregate the results. Lot of potential directions to go here, and is likely a good bit of work to champion something that's generic enough to work in most situations but easy enough so people could drop it in without writing a lot of code for their unique situation. |
Thanks for the explanation BTW! |
@denis-yuen are you trying to compute code coverage for your tests (they should be executing all lines, so 100% right away...) or production code? If production code, maybe stick https://github.com/bahmutov/was-tested between server and Cypress and get code coverage from there - but we do not think code coverage is helpful in production E2E tests. We are thinking about a different type of coverage - UI element coverage. You are probably more interested in knowing if all buttons or menu elements on the page were exercised by the Cypress end to end tests, rather than all code. |
I have set up coverage for Cypress if anyone wants to try. First you need to instrument your code, for this I have used istanbul-instrumenter-loader with webpack. Then add this code in your const istanbul = require('istanbul-lib-coverage');
const map = istanbul.createCoverageMap({});
Cypress.on('window:before:unload', e => {
const coverage = e.currentTarget.__coverage__;
if (coverage) {
map.merge(coverage);
}
});
after(() => {
cy.window().then(win => {
const coverage = win.__coverage__;
if (coverage) {
map.merge(coverage);
}
cy.writeFile('.nyc_output/out.json', JSON.stringify(map));
cy.exec('nyc report --reporter=html');
});
}); Here you also need to install |
NICE @atfzl !!! |
Been looking at this but so far have not quite figured out how to get things working. Getting an out.json file but its empty. @atfzl can you shed some more light on what steps you took to config istanbul-instrumenter-loader? |
@9fingerdev this is where i used the rules: [
{
test: /\.(jsx|js|tsx|ts)$/,
include: path.resolve(__dirname, '../src'),
rules: (isDebug
? [
{
loader: 'istanbul-instrumenter-loader',
options: {
esModules: true,
},
},
]
: []
).concat([{ loader: 'awesome-typescript-loader' }]),
}, I'll create a recipe project on weekend showing complete process. |
@atfzl any progress on that recipe project? We are using Mithril.js + WebPack and keep running into problems. |
@9fingerdev, project showcasing cypress coverage: https://github.com/atfzl/react-redux-typescript-boilerplate |
For some reason |
To instrument code with babel, there is no need to change the webpack config, just add the istanbul plugin. {
"presets": [
"react",
"flow",
[
"es2015",
{
"modules": false
}
],
"stage-2"
],
"plugins": [
"transform-runtime",
"lodash",
"transform-decorators-legacy",
"istanbul"
],
"env": {
"test": {
"plugins": [
"transform-es2015-modules-commonjs"
]
}
},
"retainLines": true
}
|
@atfzl This is exactly what I was looking for. We're using gulp though. Would the configuration be similar? |
@gkemp94 if you are using babel then you only need to add plugin in .babelrc, should work with gulp as well. |
@atfzl Can you please highlight how can I configure it with grunt? I'm not using webpack at all. Thanks. |
Instrumenting the codes will do ONLY with non-compressed JS. However, a typical process of shipping the normal web application would be: Linting & UT passed (source code or transpiled) -> Packaging (minified & mangled) -> E2E/Integration testing (against compressed version of JS) -> promote to production It would be difficult to calculate the coverage in the above pipeline unless we create a separated one only for the E2E coverage |
@atfzl Can you please show light on to find code coverage when running tests in isolation mode? Cypress version: 3.0.1 |
@abataub the steps i have mentioned also works in isolation mode. Let me know what is the exact issue. |
Thanks, @atfzl. I just made changes and it works. |
Thanks @atfzl that was super helpful! In order to end up with cumulative coverage across multiple |
@atfzl have you tried this with |
The v3 solution I got working.. it's probably overkilling it in some form, but this allowed for the node stored map to be reused across all of the tests merging them along the way. I set the env coverage to In plugins: if(config.env.coverage) {
const istanbul = require('istanbul-lib-coverage');
coverageMap = istanbul.createCoverageMap({});
on('task', {
'coverage'(coverage) {
coverageMap.merge(coverage);
return JSON.stringify(coverageMap);
}
});
} In support: if(Cypress.env('coverage')) {
afterEach(function() {
const coverageFile = `${ Cypress.config('coverageFolder') }/out.json`;
cy.window().then(win => {
const coverage = win.__coverage__;
if(!coverage) return;
cy.task('coverage', coverage).then(map => {
cy.writeFile(coverageFile, map);
if(Cypress.env('coverage') === 'open') {
cy.exec('nyc report --reporter=html');
}
});
});
});
} My npm script is essentially: |
This week I have made a presentation at Øredev showing what we think is a good replacement for code coverage for end-to-end tests. Look at the slides here https://slides.com/bahmutov/well-tested-software and in particular read the following blog posts:
I think both element coverage and state machine coverage are a lot more meaningful than code statement coverage, and we will develop these ideas more in the future. |
@bahmutov i assume state coverage would need a lib for each state management solution? Vuex, redux, etc. |
Even worse/better - it refers to modeling application as a state transition machines, something like “xstate” library for example
…Sent from my iPhone
On Nov 22, 2018, at 18:22, Anton Frattaroli ***@***.***> wrote:
@bahmutov i assume state coverage would need a lib for each state management solution? Vuex, redux, etc.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@rwwagner90 merging mocha and cypress coverage - nice idea. I notice the cited repo now uses Jest. Is that a recent change? What was the reason for using Jest instead of Cypress for UI component testing? If you're not using Cypress for UI component testing does then what coverage are you merging? |
@Vandivier we're no longer merging coverage. We're just using Jest and it does its own coverage. We no longer try to get coverage out of Cypress. |
@rwwagner90 interested to know if there's any particular reason for not getting coverage from Cypress. I've contemplated putting something together. Is it not worth the effort? |
@ifiokjr we decided that ultimately, Cypress coverage was not a good representation of real coverage. You may "cover" 80% of lines just by booting the app up and visiting a page, but you're really only testing the functionality of one function. We decided coverage only made sense from unit tests, and we would wait for Cypress to expose more meaningful metrics like element coverage or application state coverage, as they mention here https://docs.cypress.io/faq/questions/general-questions-faq.html#Is-there-code-coverage |
Unit testing with cypress is a thing that can be done. Info doesn't directly impact the conversation but is something to consider. |
I find the coverage reports I can get from Cypress to be quite useful. Yes it doesn't tell you what is covered or not as false positives are high, but it can tell you what is definitely not covered. In some cases I discovered tests we thought were covering the use case, but weren't. However I generate coverage reports two ways. I merge a report across the entire code base when run headlessly, but I also run coverage tests isolated on particular tests from the gui. The coverage reports help me write better tests and can in some instances help catch dead code. They don't do the same job as unit test coverage, but it's useful data none-the-less. |
I am using TypeScript, I tried to adapt the code by @paulfalgout to make it work with TypeScript but got stuck. Thankfully someone kindly helped me in my question on stackoverflow, so if anyone is trying to make Cypress + TypeScript + IstanbulJS work together, it can be done as well, just check the accepted answer 😬 |
Hi everyone, I have blogged how to instrument application code and report code coverage from end-to-end tests:
Then read the following posts:
Recommended plugin: https://github.com/cypress-io/cypress-istanbul for merging code coverage information into correct object |
THANK YOU so much @bahmutov |
Closing this issue, as we have released plugin and detailed documentation how to get end-to-end, unit and full-stack code coverage
|
* Update answer about code coverage Since linked issue was closed I took the [closing comment](cypress-io/cypress#346 (comment)) and made it the new answer (with minimal wording tweaks suitable in the context of this document). I left the related resources in, since they still seems to be helpful and related to "coverage" in general. But I slightly modified the wording to - no longer sound like code coverage is not there - invite more links should anybody have one * style: Use "full stack" instead of "full-stack" * Update source/faq/questions/general-questions-faq.md Co-authored-by: Jennifer Shehane <shehane.jennifer@gmail.com>
Following up on cypress-io/cypress-example-recipes#3 and opening an issue here for discussion as recommended.
For context, we previously used Protractor paired with Istanbul ( https://github.com/gotwarlost/istanbul ) to calculate code coverage for our application. We were wondering if any one has experience with something similar when working with Cypress
FYI @agduncan94
The text was updated successfully, but these errors were encountered: