{
  "doc": {
    "id": "app/tooling/code-coverage",
    "title": "Measuring Code Coverage in Cypress",
    "description": "Learn how to measure code coverage in Cypress and the difference between UI Coverage and Code Coverage.",
    "section": "app",
    "source_path": "/llm/markdown/app/tooling/code-coverage.md",
    "version": "ce02913654e2655ee63448bdc92bb92c7b46a619",
    "updated_at": "2026-04-22T19:37:51.587Z",
    "headings": [
      {
        "id": "app/tooling/code-coverage#measure-code-coverage-in-cypress",
        "text": "Measure Code Coverage in Cypress",
        "level": 1
      },
      {
        "id": "app/tooling/code-coverage#what-youll-learn",
        "text": " What you'll learn",
        "level": 5
      },
      {
        "id": "app/tooling/code-coverage#introduction",
        "text": "Introduction",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#code-coverage",
        "text": "Code Coverage",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#ui-coverage",
        "text": "UI Coverage",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#instrumenting-code",
        "text": "Instrumenting code",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#using-nyc",
        "text": "Using NYC",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#using-code-transpilation-pipeline",
        "text": "Using code transpilation pipeline",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#e2e-code-coverage",
        "text": "E2E code coverage",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#install-the-plugin",
        "text": "Install the plugin",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#see-code-coverage-summary",
        "text": "See code coverage summary",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#code-coverage-as-a-guide",
        "text": "Code coverage as a guide",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#combining-code-coverage-from-parallel-tests",
        "text": "Combining code coverage from parallel tests",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#e2e-and-unit-code-coverage",
        "text": "E2E and unit code coverage",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#full-stack-code-coverage",
        "text": "Full stack code coverage",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#videos",
        "text": "Videos",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#how-to-instrument-react-scripts-web-application-for-code-coverage",
        "text": "How to instrument react-scripts web application for code coverage",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#get-code-coverage-reports-from-cypress-tests",
        "text": "Get code coverage reports from Cypress tests",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#excluding-code-from-code-coverage-reports",
        "text": "Excluding code from code coverage reports",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#check-code-coverage-robustly-using-3rd-party-tool",
        "text": "Check code coverage robustly using 3rd party tool",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#adding-code-coverage-badge-to-your-project",
        "text": "Adding code coverage badge to your project",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#show-code-coverage-in-commit-status-check",
        "text": "Show code coverage in commit status check",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#checking-code-coverage-on-pull-request",
        "text": "Checking code coverage on pull request",
        "level": 3
      },
      {
        "id": "app/tooling/code-coverage#examples",
        "text": "Examples",
        "level": 2
      },
      {
        "id": "app/tooling/code-coverage#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Measure Code Coverage in Cypress"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 5,
        "children": [
          {
            "type": "text",
            "value": " What you'll learn"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "The difference between Code Coverage and Cypress's UI Coverage"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to instrument your application code for code coverage"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to collect code coverage from Cypress tests"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to merge code coverage from parallel tests"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to collect code coverage from different testing types"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Introduction"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "As you write more and more end-to-end tests, you will find yourself wondering -\ndo I need to write more tests? Are there parts of the application still\nuntested? Are there parts of the application that perhaps are tested too much?"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress offers a couple of solutions to help answer these questions:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "#Code-Coverage",
                    "children": [
                      {
                        "type": "text",
                        "value": "Code coverage"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - find out which lines of the application's source code were executed"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "#UI-Coverage",
                    "children": [
                      {
                        "type": "text",
                        "value": "UI coverage"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - find out which parts of the UI were tested"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Code Coverage"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Code coverage is a metric that helps you understand how much of your application\ncode is covered by your tests. If there are important\nsections of the application's logic that were not executed from the tests,\nthen a new test can be added to ensure that the application logic for these sections is\nalso tested."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Computing the source code lines that were executed during the test is done\nthrough code coverage. Code coverage requires inserting additional counters\ninto your source code before running it using instrumentation.\nThis document will be focused on code coverage and the instrumentation required to set it up."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "UI Coverage"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "UI Coverage is a visual test coverage report based on the interactive elements that make up your application.\nIt highlights areas of missed test coverage directly within every page of your application,\nthat you can use to make data-driven testing decisions."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "UI Coverage also seamlessly integrates with your Cypress tests, building on the tests you've already\nwritten — no extra instrumentation is required like with code coverage."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To learn more about UI coverage,\nplease see our "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/ui-coverage/get-started/introduction.md",
            "children": [
              {
                "type": "text",
                "value": "UI Coverage"
              }
            ]
          },
          {
            "type": "text",
            "value": " guide."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Instrumenting code"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Instrumentation takes code that looks like this..."
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": "title='add.js'",
        "value": "function add(a, b) {\n  return a + b\n}\nmodule.exports = { add }"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "...and parses it to find all functions, statements, and branches and then\ninserts counters into the code. For the above code it might look like this:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "// this object counts the number of times each\n// function and each statement is executed\nconst c = (window.__coverage__ = {\n  // \"f\" counts the number of times each function is called\n  // we only have a single function in the source code thus it starts with [0]\n  f: [0],\n  // \"s\" counts the number of times each statement is called\n  // we have 3 statements and they all start with 0\n  s: [0, 0, 0],\n})\n\n// the original code + increment statements\n// uses \"c\" alias to \"window.__coverage__\" object\n// the first statement defines the function, let's increment it\nc.s[0]++\nfunction add(a, b) {\n  // function is called and then the 2nd statement\n  c.f[0]++\n  c.s[1]++\n\n  return a + b\n}\n// 3rd statement is about to be called\nc.s[2]++\nmodule.exports = { add }"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Imagine we load the above instrumented source file from our test spec file.\nImmediately some counters will be incremented!"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": "title='add.cy.js'",
        "value": "const { add } = require('./add')\n// JavaScript engine has parsed and evaluated \"add.js\" source code\n// which ran some of the increment statements\n// __coverage__ has now\n// f: [0] - function \"add\" was NOT executed\n// s: [1, 0, 1] - first and third counters were incremented\n// but the statement inside function \"add\" was NOT executed"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We want to make sure every statement and function in the file `add.js` has been\nexecuted by our tests at least once. Thus we write a test:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": "title='add.cy.js'",
        "value": "const { add } = require('./add')\n\nit('adds numbers', () => {\n  expect(add(2, 3)).to.equal(5)\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When the test calls `add(2, 3)`, the counter increments inside the \"add\"\nfunction are executed, and the coverage object becomes:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "{\n  // \"f\" keeps count of times each function was called\n  // we only have a single function in the source code\n  // thus it starts with [0]\n  f: [1],\n  // \"s\" keeps count of times each statement was called\n  // we have 3 statements, and they all start with 0\n  s: [1, 1, 1]\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This single test has achieved 100% code coverage - every function and every\nstatement has been executed at least once. But, in real world applications,\nachieving 100% code coverage requires multiple tests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Once the tests finish, the coverage object can be serialized and saved to disk\nso that a human-friendly report can be generated. The collected coverage\ninformation can also be sent to external services and can help during pull request\nreviews."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you are unfamiliar with code coverage or want to learn more, take a look at\nthe \"Understanding JavaScript Code Coverage\" blog post\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://medium.com/engineering-semantics3/understanding-code-coverage-1074e8fccce0/",
            "children": [
              {
                "type": "text",
                "value": "Part 1"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nand\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://medium.com/engineering-semantics3/understanding-javascript-code-coverage-part-2-9aedaa5119e5/",
            "children": [
              {
                "type": "text",
                "value": "Part 2"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress does not instrument your code - you need to do it yourself. The golden\nstandard for JavaScript code instrumentation is the battle-hardened\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://istanbul.js.org",
            "children": [
              {
                "type": "text",
                "value": "Istanbul"
              }
            ]
          },
          {
            "type": "text",
            "value": " and, luckily, it plays very nicely with Cypress.\nYou can instrument the code as a build step through one of two ways:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Using the "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/istanbuljs/nyc",
                    "children": [
                      {
                        "type": "text",
                        "value": "nyc"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " module - a command-line\ninterface for the "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://istanbul.js.org",
                    "children": [
                      {
                        "type": "text",
                        "value": "Istanbul"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " library"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "As part of your code transpilation pipeline using the\n"
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/istanbuljs/babel-plugin-istanbul",
                    "children": [
                      {
                        "type": "text",
                        "value": "`babel-plugin-istanbul`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "\ntool"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Using NYC"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To instrument the application code located in your `src` folder and save it in\nan `instrumented` folder use the following command:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "shell",
        "meta": null,
        "value": "npx nyc instrument --compact=false src instrumented"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We are passing the `--compact=false` flag to generate human-friendly output."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The instrumentation takes your original code like this fragment..."
          }
        ]
      },
      {
        "type": "code",
        "lang": "js",
        "meta": "title='src/index.js'",
        "value": "const store = createStore(reducer)\n\nrender(\n  <Provider store={store}>\n    <App />\n  </Provider>,\n  document.getElementById('root')\n)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "...and wraps each statement with additional counters that keep track of how many\ntimes each source line has been executed by the JavaScript runtime."
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "const store = (cov_18hmhptych.s[0]++, createStore(reducer))\ncov_18hmhptych.s[1]++\nrender(\n  <Provider store={store}>\n    <App />\n  </Provider>,\n  document.getElementById('root')\n)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Notice the calls to `cov_18hmhptych.s[0]++` and `cov_18hmhptych.s[1]++` that\nincrement the statement counters. All counters and additional book-keeping\ninformation are stored in a single object attached to the browser's `window`\nobject. We can see the counters if we serve the `instrumented` folder instead of\n`src` and open the application."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If we drill into the coverage object we can see the statements executed in each\nfile. For example the file `src/index.js` has the following information:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In green, we highlighted the 4 statements present in that file. The first three\nstatements were each executed once and the last statement was never executed (it\nprobably was inside an `if` statement). By using the application, we can both\nincrement the counters and flip some of the zero counters into positive numbers."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Using code transpilation pipeline"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Instead of using the `npx instrument` command, we can use\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/istanbuljs/babel-plugin-istanbul",
            "children": [
              {
                "type": "text",
                "value": "`babel-plugin-istanbul`"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nto instrument the code as part of its transpilation. Add this plugin to the\n`.babelrc` file."
          }
        ]
      },
      {
        "type": "code",
        "lang": "json",
        "meta": "title='.babelrc'\"",
        "value": "{\n  \"presets\": [\"@babel/preset-react\"],\n  \"plugins\": [\"transform-class-properties\", \"istanbul\"]\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We can now serve the application and get instrumented code without an\nintermediate folder, but the result is the same instrumented code loaded by the\nbrowser, with the same `window.__coverage__` object keeping track of the\noriginal statements."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Check out\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage#examples",
            "children": [
              {
                "type": "text",
                "value": "`@cypress/code-coverage#examples`"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nfor full example projects showing different code coverage setups."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "A really nice feature of both "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/istanbuljs/nyc",
            "children": [
              {
                "type": "text",
                "value": "nyc"
              }
            ]
          },
          {
            "type": "text",
            "value": " and\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/istanbuljs/babel-plugin-istanbul",
            "children": [
              {
                "type": "text",
                "value": "`babel-plugin-istanbul`"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nis that the source maps are generated automatically, allowing us to collect code\ncoverage information, but also interact with the original, non-instrumented code\nin the Developer Tools. In the screenshot above, the bundle (green arrow) has\ncoverage counters, but the source mapped files in the green rectangle show the\noriginal code."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The `nyc` and `babel-plugin-istanbul` only instrument the application code and\nnot 3rd party dependencies from `node_modules`."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "E2E code coverage"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To handle code coverage collected during each test, there is a\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage",
            "children": [
              {
                "type": "text",
                "value": "`@cypress/code-coverage`"
              }
            ]
          },
          {
            "type": "text",
            "value": " Cypress\nplugin. It merges coverage from each test and saves the combined result. It also\ncalls `nyc` (its peer dependency) to generate static HTML reports for human\nconsumption."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Install the plugin"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Please consult the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage",
            "children": [
              {
                "type": "text",
                "value": "`@cypress/code-coverage`"
              }
            ]
          },
          {
            "type": "text",
            "value": "\ndocumentation for up-to-date installation instructions."
          }
        ]
      },
      {
        "type": "code",
        "lang": "shell",
        "meta": null,
        "value": "npm install @cypress/code-coverage --save-dev"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Then add the code below to the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/configuration.md#e2e",
            "children": [
              {
                "type": "text",
                "value": "supportFile"
              }
            ]
          },
          {
            "type": "text",
            "value": " and\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/plugins/plugins-guide.md#Using-a-plugin",
            "children": [
              {
                "type": "text",
                "value": "setupNodeEvents"
              }
            ]
          },
          {
            "type": "text",
            "value": " function."
          }
        ]
      },
      {
        "type": "code",
        "lang": "js",
        "meta": null,
        "value": "// cypress/support/e2e.js\nimport '@cypress/code-coverage/support'"
      },
      {
        "type": "code",
        "lang": "js",
        "meta": null,
        "value": "require('@cypress/code-coverage/task')(on, config)\n// include any other plugin code...\n\n// It's IMPORTANT to return the config object\n// with any changed environment variables\nreturn config"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When you run the Cypress tests now, you should see a few commands after the\ntests finish. We have highlighted these commands using a green rectangle below."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After the tests complete, the final code coverage is saved to a `.nyc_output`\nfolder. It is a JSON file from which we can generate a report in a variety of\nformats. The\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage",
            "children": [
              {
                "type": "text",
                "value": "`@cypress/code-coverage`"
              }
            ]
          },
          {
            "type": "text",
            "value": " plugin\ngenerates the HTML report automatically - you can open the `coverage/index.html`\npage locally after the tests finish. You can also call `nyc report` to generate\nother reports, for example, sending the coverage information to 3rd party\nservices."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "See code coverage summary"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To see the summary of the code coverage after tests run, run the command below."
          }
        ]
      },
      {
        "type": "code",
        "lang": "shell",
        "meta": null,
        "value": "npx nyc report --reporter=text-summary\n\n========= Coverage summary =======\nStatements   : 76.3% ( 103/135 )\nBranches     : 65.31% ( 32/49 )\nFunctions    : 64% ( 32/50 )\nLines        : 81.42% ( 92/113 )\n=================================="
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Tip: store the `coverage` folder as a build artifact on your continuous\nintegration server. Because the report is a static HTML page, some CIs can show\nit right from their web applications. The screenshot below shows the coverage\nreport stored on CircleCI. Clicking on `index.html` shows the report right in\nthe browser."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Code coverage as a guide"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Even a single test can cover a lot of the application code. For example, let's\nrun the following test that adds a few items, then marks one of them as\ncompleted."
          }
        ]
      },
      {
        "type": "code",
        "lang": "js",
        "meta": null,
        "value": "it('adds and completes todos', () => {\n  -{cy.visit('/')::cy.mount(<AddTodo />)}-\n  cy.get('.new-todo').type('write code{enter}')\n  cy.get('.new-todo').type('write tests{enter}')\n  cy.get('.new-todo').type('deploy{enter}')\n\n  cy.get('.todo').should('have.length', 3)\n\n  cy.get('.todo').first().find('.toggle').check()\n\n  cy.get('.todo').first().should('have.class', 'completed')\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After running the test and opening the HTML report, we see 76% code coverage in\nour application."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Even better, we can drill down into the individual source files to see what code\nwe missed. In our example application, the main state logic is in the\n`src/reducers/todos.js` file. Let's see the code coverage in this file:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Notice how the ADD_TODO action was executed 3 times - because our test has\nadded 3 todo items, and the COMPLETE_TODO action was executed just once -\nbecause our test has marked 1 todo item as completed."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The source lines not covered, marked in yellow (the switch cases the test missed)\nand red (regular statements) are a great guide for writing more end-to-end\ntests. We need tests that delete todo items, edit them, mark all of them as\ncompleted at once and clear completed items. When we cover every switch\nstatement in `src/reducers/todos.js` we probably will achieve close to 100% code\ncoverage. Even more importantly, we will cover the main features of the\napplication the user is expected to use."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We can write more E2E tests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The produced HTML report shows 99% code coverage"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Every source file but one is covered at 100%. We can have great confidence in our\napplication, and safely refactor the code knowing that we have a robust set of\nend-to-end tests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If possible, we advise implementing\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/tooling/visual-testing.md",
            "children": [
              {
                "type": "text",
                "value": "visual testing"
              }
            ]
          },
          {
            "type": "text",
            "value": " in addition to Cypress\nfunctional tests to avoid CSS and visual regressions."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Combining code coverage from parallel tests"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you execute Cypress tests in\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/smart-orchestration/parallelization.md",
            "children": [
              {
                "type": "text",
                "value": "parallel"
              }
            ]
          },
          {
            "type": "text",
            "value": ", each machine ends\nup with a code coverage report that only shows a portion of the code exercised.\nTypically an external code coverage service would merge such partial reports for\nyou. If you do want to merge the reports yourself:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "on every machine running Cypress tests, copy the produced code coverage report\ninto a common folder under a unique name to avoid overwriting it"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "after all E2E tests finish, combine the reports yourself using the `nyc merge`\ncommand"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can find an example of merging partial reports in our\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-example-conduit-app",
            "children": [
              {
                "type": "text",
                "value": "cypress-io/cypress-example-conduit-app"
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "E2E and unit code coverage"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Let's look at the one file that has a \"missed\" line. It is the\n`src/selectors/index.js` file shown below."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The source line not covered by the end-to-end tests shows an edge case NOT\nreachable from the UI. Yet this switch case is definitely worth testing - at\nleast to avoid accidentally changing its behavior during future refactoring."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We can directly test this piece of code by importing the `getVisibleTodos`\nfunction from the Cypress spec file. In essence we are using Cypress as a unit\ntesting tool (find more unit testing recipes\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-example-recipes#unit-testing",
            "children": [
              {
                "type": "text",
                "value": "here"
              }
            ]
          },
          {
            "type": "text",
            "value": ")."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Here is our test to confirm that the error is thrown."
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "// cypress/e2e/selectors.cy.js\nimport { getVisibleTodos } from '../../src/selectors'\n\ndescribe('getVisibleTodos', () => {\n  it('throws an error for unknown visibility filter', () => {\n    expect(() => {\n      getVisibleTodos({\n        todos: [],\n        visibilityFilter: 'unknown-filter',\n      })\n    }).to.throw()\n  })\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The test passes, even if there is no web application visited."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Previously we instrumented the application code (either using a build step or\ninserting a plugin into the Babel pipeline). In the example above, we are NOT\nloading an application, instead we are only running the test files by\nthemselves."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If we want to collect the code coverage from the unit tests, we need to\ninstrument the source code of our spec files. The simplest way to do this is\nto use the same `.babelrc` with\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/istanbuljs/babel-plugin-istanbul",
            "children": [
              {
                "type": "text",
                "value": "`babel-plugin-istanbul`"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nand tell the Cypress built-in bundler to use `.babelrc` when bundling specs. One\ncan use the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage",
            "children": [
              {
                "type": "text",
                "value": "`@cypress/code-coverage`"
              }
            ]
          },
          {
            "type": "text",
            "value": " plugin\nagain to do this by adding the code below to the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/plugins/plugins-guide.md#Using-a-plugin",
            "children": [
              {
                "type": "text",
                "value": "setupNodeEvents"
              }
            ]
          },
          {
            "type": "text",
            "value": " function."
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "require('@cypress/code-coverage/task')(on, config)\n// tell Cypress to use .babelrc file\n// and instrument the specs files\n// only the extra application files will be instrumented\n// not the spec files themselves\non('file:preprocessor', require('@cypress/code-coverage/use-babelrc'))\n\nreturn config"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For reference, the `.babelrc` file is shared between the example application and\nthe spec files, thus Cypress tests are transpiled the same way the application\ncode is transpiled."
          }
        ]
      },
      {
        "type": "code",
        "lang": "json",
        "meta": null,
        "value": "{\n  \"presets\": [\"@babel/preset-react\"],\n  \"plugins\": [\"transform-class-properties\", \"istanbul\"]\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When we run Cypress with\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/istanbuljs/babel-plugin-istanbul",
            "children": [
              {
                "type": "text",
                "value": "`babel-plugin-istanbul`"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nincluded and inspect the `window.__coverage__` object in the spec iframe, we\nshould see the coverage information for the application source files."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The code coverage information in unit tests and end-to-end tests has the same\nformat; the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage",
            "children": [
              {
                "type": "text",
                "value": "`@cypress/code-coverage`"
              }
            ]
          },
          {
            "type": "text",
            "value": " plugin\nautomatically grabs both and saves the combined report. Thus we can see the code\ncoverage from the `cypress/e2e/selectors.cy.js` file after running the test."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Our unit test is hitting the line we could not reach from the end-to-end tests,\nand if we execute all spec files - we will get 100% code coverage."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Full stack code coverage"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "A complex application might have a Node back end with its own complex logic.\nFrom the front end web application, the calls to the API go through layers of\ncode. It would be nice to track what back end code has been exercised during\nCypress end-to-end tests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Are our end-to-end tests that are so effective at covering the web application\ncode also covering the back end server code?"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Long story short: yes. You can collect the code coverage from the back end,\nand let the `@cypress/code-coverage` plugin merge it with the front end\ncoverage, creating a single full stack report."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The full source code for this section can be found in the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-example-conduit-app",
            "children": [
              {
                "type": "text",
                "value": "cypress-io/cypress-example-conduit-app"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nrepository."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can run your Node server and instrument it using nyc on the fly. Instead of\nthe \"normal\" server start command, you can run the command\n`npm run start:coverage` defined in the `package.json` like this:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "json",
        "meta": null,
        "value": "{\n  \"scripts\": {\n    \"start\": \"node server\",\n    \"start:coverage\": \"nyc --silent node server\"\n  }\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In your server, insert another middleware from `@cypress/code-coverage`. If you\nuse an Express server, include `middleware/express`:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "const express = require('express')\nconst app = express()\n\nrequire('@cypress/code-coverage/middleware/express')(app)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If your server uses hapi, include `middleware/hapi`"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "if (global.__coverage__) {\n  require('@cypress/code-coverage/middleware/hapi')(server)\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Tip: you can conditionally register the endpoint only if there is a global\ncode coverage object, and you can\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md",
            "children": [
              {
                "type": "text",
                "value": "exclude the middleware code from the coverage numbers"
              }
            ]
          },
          {
            "type": "text",
            "value": ":"
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "/* istanbul ignore next */\nif (global.__coverage__) {\n  require('@cypress/code-coverage/middleware/hapi')(server)\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For any other server type, define a `GET /__coverage__` endpoint and return the\n`global.__coverage__` object."
          }
        ]
      },
      {
        "type": "code",
        "lang": "javascript",
        "meta": null,
        "value": "if (global.__coverage__) {\n  // handle \"GET __coverage__\" requests\n  onRequest = (response) => {\n    response.sendJSON({ coverage: global.__coverage__ })\n  }\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In order for the `@cypress/code-coverage` plugin to know that it should request\nthe back end coverage, add the new endpoint to the Cypress configuration\nenvironment settings under `env.codeCoverage.url` key. For example, if the\napplication back end is running at port 3000 and we are using the default \"GET\n/coverage\" endpoint, set the following:"
          }
        ]
      },
      {
        "type": "code",
        "lang": "ts",
        "meta": null,
        "value": "{\n  env: {\n    codeCoverage: {\n      url: 'http://localhost:3000/__coverage__'\n    }\n  }\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "From now on, the front end code coverage collected during end-to-end tests will\nbe merged with the code coverage from the instrumented back end code and saved\nin a single report. Here is an example report from the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-example-conduit-app",
            "children": [
              {
                "type": "text",
                "value": "cypress-io/cypress-example-conduit-app"
              }
            ]
          },
          {
            "type": "text",
            "value": "\nexample:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can explore the above combined full stack coverage report at the\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://coveralls.io/github/cypress-io/cypress-example-conduit-app",
            "children": [
              {
                "type": "text",
                "value": "coveralls.io/github/cypress-io/cypress-example-conduit-app"
              }
            ]
          },
          {
            "type": "text",
            "value": "\ndashboard. You can also find full stack code coverage in our\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "RealWorld App"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Even if you only want to measure the back end code coverage Cypress can help."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Videos"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "There is a series of videos we have recorded showing code coverage in Cypress"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "How to instrument react-scripts web application for code coverage"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Get code coverage reports from Cypress tests"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Excluding code from code coverage reports"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Check code coverage robustly using 3rd party tool"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Adding code coverage badge to your project"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Show code coverage in commit status check"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Checking code coverage on pull request"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Examples"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can find full examples showing different code coverage setups in the\nfollowing repositories:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/cypress-io/cypress-realworld-app",
                    "children": [
                      {
                        "type": "text",
                        "value": "cypress-io/cypress-realworld-app"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "\nor RWA is a full stack example application that demonstrates best practices\nand scalable strategies with Cypress in practical and realistic scenarios.\nThe RWA achieves full code coverage with end-to-end tests\n"
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/guides/cross-browser-testing.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "across multiple browsers"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " and\n"
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/viewport.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "device sizes"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/lluia/cypress-typescript-coverage-example",
                    "children": [
                      {
                        "type": "text",
                        "value": "lluia/cypress-typescript-coverage-example"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "\nshows coverage for a React App that uses TypeScript."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/ericorruption/cypress-code-coverage-typescript-webpack-ts-loader",
                    "children": [
                      {
                        "type": "text",
                        "value": "ericorruption/cypress-code-coverage-typescript-webpack-ts-loader"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "\nshows how to collect coverage for a TypeScript + webpack project using\n`ts-loader` instead of `babel-loader`."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Find the full list of examples linked in\n"
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/code-coverage#external-examples",
            "children": [
              {
                "type": "text",
                "value": "cypress-io/code-coverage#external-examples"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "See also"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/ui-coverage/get-started/introduction.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "UI Coverage"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "The official\n"
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/cypress-io/code-coverage",
                    "children": [
                      {
                        "type": "text",
                        "value": "@cypress/code-coverage"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " plugin"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "token_estimate": 4063
}