Created unity project
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"timestamp": 1702923274,
|
||||
"signature": "pc09yQExILlhb3S3yQDrf0JfDPjmso9VX834nifDFYMuUg6MLVrGSfOaw/9051ZXCE+RSKZpQv15IOHIZ2FUl1QOv9tgCxzv+rqpv9qL8+v+QWIpFP5l78a6h9qrRFuYb0nVD41dru5ZQm8xxwayHNdQn7++369J6memDVgdi0sArXq2v1IEA9xnA78hfC2ECpOnWUOMEybNpjdeJF42se3d5gnvZ425rd9HP0Yog/wXeecVUqP5cm+hwQNw21+Kk9E9z6jp95SHqaiaGXH637UjT52w3MQ617XgfOwBMyriClGqyhOcmgAjDyKqD9tNlG3TlEQbTFaQyd9HIN50ISDH3RS7Wf3nhAifpLeVF25jqvnqZEeUqZS+WdVgUq582pYKdhuJofgZsrk7iQlWaYTilXZyMuOpfHZI+YD3sflML6T0EeHvVLpNjVoPkr+980AbtflSrOaUhQ+1w9LKkN2AX0fPud6xz+x7GaQ3L/S6WuJIs+JGjO8KAkKF6pcg",
|
||||
"publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
# Changelog
|
||||
All notable changes to the Code Coverage package will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.2.5] - 2023-12-20
|
||||
|
||||
### Fixes
|
||||
- Fixed failing to generate code coverage for assemblies whose name starts with 'system' (case [COV-38](https://issuetracker.unity3d.com/issues/code-coverage-fails-to-generate-a-report-when-the-assembly-name-begins-with-the-word-system)).
|
||||
- Fixed results xml file not been correctly stored under the EditMode folder if it is written after a domain reload (case [COV-36](https://issuetracker.unity3d.com/issues/coverage-results-xml-file-is-not-categorized-as-editmode-if-it-is-written-after-domain-reload)).
|
||||
|
||||
## [1.2.4] - 2023-06-02
|
||||
|
||||
### Fixes
|
||||
- Fixed failing to gather code coverage for normal methods in generic classes (case [COV-27](https://issuetracker.unity3d.com/issues/non-generic-methods-in-generic-classes-always-show-no-coverage)).
|
||||
- Documentation: Corrected *Settings.json* path in `useProjectSettings` section in *-coverageOptions* (case [COV-26](https://issuetracker.unity3d.com/issues/documentation-for-useprojectsettings-references-incorrect-settings-dot-json-path)).
|
||||
- Make sure *Auto Generate Report* defaults to true when running from the command line (case [COV-25](https://issuetracker.unity3d.com/issues/useprojectsettings-does-not-generate-report-until-auto-generate-report-is-toggled-off-and-on-again)).
|
||||
|
||||
## [1.2.3] - 2023-04-14
|
||||
|
||||
### Fixes
|
||||
- Fixed failing to gather code coverage for generic methods (case [COV-17](https://issuetracker.unity3d.com/issues/coverage-package-fails-to-gather-any-coverage-for-generic-methods)).
|
||||
|
||||
### Improvements
|
||||
- Added `filtersFromFile` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html). This allows specifying an external Json file which contains path and assembly filtering rules. When this file contains relative paths, the `sourcePaths` option can be used to specify the source directories.
|
||||
<br/>**Note:** The `pathFiltersFromFile` option will be deprecated in the next package major release. Please use the new `filtersFromFile` option instead.
|
||||
- Make sure `--burst-disable-compilation` is [expected](https://docs.unity3d.com/Packages/com.unity.burst@latest/index.html?subfolder=/manual/getting-started.html#command-line-options) to be passed with two dashes, unlike other editor command line options.
|
||||
|
||||
## [1.2.2] - 2022-11-18
|
||||
|
||||
### Fixes
|
||||
- Temporary fix for the [Test Framework](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html) 1.3 issue where the *RunFinished* callback is not called when running from the command line and there is a domain reload (case [DSTR-692](https://issuetracker.unity3d.com/issues/registered-callbacks-dont-work-after-domain-reload)).
|
||||
|
||||
### Improvements
|
||||
- Reduced the number of logs for the default *Verbosity:Info*.
|
||||
- Added *Uncoverable lines* definition in [How to interpret the results](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/HowToInterpretResults.html#summary) page in the documentation.
|
||||
- Updated documentation to match version 1.2.2.
|
||||
|
||||
## [1.2.1] - 2022-10-27
|
||||
|
||||
### Fixes
|
||||
- Fixed compatibility with [Test Framework](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html) package version 1.3.
|
||||
|
||||
### Improvements
|
||||
- A single file summary version of the report is now generated in Json format, in addition to the XML and Markdown formats.
|
||||
- Added a warning when an invalid coverage option is passed in *-coverageOptions* in [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html).
|
||||
|
||||
## [1.2.0] - 2022-08-01
|
||||
|
||||
### Fixes
|
||||
- Ensure assemblies are removed from the Included Assemblies field if they no longer exist (case [1318668](https://issuetracker.unity3d.com/issues/code-coverage-the-included-assemblies-field-shows-assemblies-that-no-longer-exist)).
|
||||
- Ensure hidden sequence points are ignored (case [1372305](https://issuetracker.unity3d.com/issues/class-which-derives-from-methodbase-causes-incorrect-sequence-points-to-be-generated-by-coverage-api)).
|
||||
|
||||
### Changes
|
||||
- Updated Report Generator to version 5.0.4.
|
||||
- Updated the UI of the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html) moving the action buttons into a toolbar at the top.
|
||||
- Renamed *assemblyFilters* aliases in [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html); `<user>` was renamed to `<assets>` and `<project>` was renamed to `<all>`.
|
||||
- Replaced `pathStrippingPatterns` with `pathReplacePatterns` in [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html). The `pathReplacePatterns` option allows stripping and replacing specific sections from the paths that are stored in the coverage results xml files.
|
||||
|
||||
See the [Upgrade guide](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/upgrade-guide.html) if upgrading to Code Coverage package version 1.2.
|
||||
|
||||
### Improvements
|
||||
- The size of the coverage result files and the Code Coverage session duration have been optimized. At the start of the session a coverage xml result file is generated which includes all the lines but with zero coverage. The following coverage xml result files that are generated within a Code Coverage session include only the coverage data of the visited lines.
|
||||
- Added Help IconButton in the toolbar in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html).
|
||||
- Updated the mechanic for opening the containing folder, change the location or reset to the default location for *Results Location* and *Report History Location*.
|
||||
- Refactored the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html) UI to include a new *Report Options* section and removing the word 'Generate' from the options.
|
||||
- Introduced new selection buttons under the *Included Assemblies* dropdown in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html); use the *All* button to select all the assemblies in the project. Use the *Assets* button to select only the assemblies under the `Assets` folder. Use the *Packages* button to select only the Packages' assemblies. If searching, the buttons will apply only to the assemblies visible in the list.
|
||||
- Updated [What's new](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/whats-new.html) and [Upgrade guide](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/upgrade-guide.html) pages in the documentation.
|
||||
- Added [Using relative paths in path filters](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html#using-relative-paths-in-path-filters) section in documentation.
|
||||
- Updated the editor and console logs; added information about the assembly and path filters, improved coverage session logs.
|
||||
- Improved the progress bars for `Writing coverage results` and `Generating the report`.
|
||||
- Added an icon for the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html).
|
||||
- Updated documentation to match version 1.2.0.
|
||||
|
||||
### Features
|
||||
- Added `Pause Recording` and `Resume Recording` buttons in the toolbar in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html).
|
||||
- Added `Log Verbosity Level` setting in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html) which allows setting the verbosity level for the editor and console logs.
|
||||
- Added `Additional Reports` option in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html) which if checked [SonarQube](https://docs.sonarqube.org/latest/analysis/generic-test), [Cobertura](https://cobertura.github.io/cobertura) and [LCOV](https://github.com/linux-test-project/lcov) reports will be generated. Added `generateAdditionalReports` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html).
|
||||
- Added `Test Runner References` report option in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html) which if checked includes test references to the generated coverage results and enables the [Coverage by test methods](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/HowToInterpretResults.html#coverage-by-test-methods) section in the HTML report, allowing you to see how each test contributes to the overall coverage. Added `generateTestReferences` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html).
|
||||
- Added `Auto Open Report` option in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CodeCoverageWindow.html) which if checked the coverage report will open automatically after it has been generated.
|
||||
- Added `pathFiltersFromFile` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html) which allows specifying an external file which contains a list of path filters. When this file contains relative paths, the `sourcePaths` option can be used to specify the source directories.
|
||||
- Added `dontClear` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html) which allows coverage results to be accumulated after every code coverage session. If not passed the results are cleared before a new session. For more information see [Generate combined report from EditMode and PlayMode tests](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html#generate-combined-report-from-editmode-and-playmode-tests).
|
||||
- When the `pathFilters` option or the `pathFiltersFromFile` option in *-coverageOptions* contains relative paths, the `sourcePaths` option can be used to specify the source directories.
|
||||
|
||||
## [1.1.1] - 2021-12-17
|
||||
|
||||
### Fixes
|
||||
- Ensure assemblies are removed from the Included Assemblies field if they no longer exist (case [1318668](https://issuetracker.unity3d.com/issues/code-coverage-the-included-assemblies-field-shows-assemblies-that-no-longer-exist))
|
||||
|
||||
### Changes
|
||||
- Updated Report Generator to version 4.8.13
|
||||
|
||||
### Improvements
|
||||
- Added Help IconButton in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/CodeCoverageWindow.html) for Unity versions 2021.2.2f1 and above
|
||||
- Added [What's new](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/whats-new.html) and [Upgrade guide](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/upgrade-guide.html) pages in the documentation
|
||||
- Updated documentation to match version 1.1.1
|
||||
|
||||
|
||||
## [1.1.0] - 2021-06-09
|
||||
|
||||
### Fixes
|
||||
- Ensure Results and History folders are created if they do not exist (case [1334551](https://issuetracker.unity3d.com/issues/code-coverage-results-slash-history-location-path-is-reset-to-default-if-set-path-no-longer-exists))
|
||||
- Added support for [ExcludeFromCoverage/ExcludeFromCodeCoverage](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/UsingCodeCoverage.html#excluding-code-from-code-coverage) for lambda expressions and yield statements (case [1338636](https://issuetracker.unity3d.com/issues/code-coverage-excludefromcoverage-attribute-doesnt-exclude-lambda-expressions-and-yield-statements-from-coverage))
|
||||
- Added support for [ExcludeFromCodeCoverage](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/UsingCodeCoverage.html#excluding-code-from-code-coverage) for getter/setter properties (case [1338665](https://issuetracker.unity3d.com/issues/code-coverage-get-and-set-accessors-are-still-marked-as-coverable-when-property-has-excludefromcodecoverage-attribute))
|
||||
- *-coverageOptions* are only parsed when running from the command line ([feedback](https://forum.unity.com/threads/code-coverage-slowing-editor-on-enter-playmode-and-assembly-reload.1121566))
|
||||
|
||||
### Changes
|
||||
- Updated Report Generator to version 4.8.9
|
||||
|
||||
### Improvements
|
||||
- Implemented changes to support [Test Framework](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html) package version 1.2
|
||||
- Logs while the Report is generated are output per message rather than at the end of the generation
|
||||
- Do not log burst warning when `--burst-disable-compilation` is passed in the command line
|
||||
- Added [Ignoring tests for Code Coverage](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/CoverageBatchmode.html#ignoring-tests-for-code-coverage) section in documentation
|
||||
- Updated the [Generate combined report from separate projects](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/CoverageBatchmode.html#generate-combined-report-from-separate-projects) section in documentation
|
||||
- Updated documentation to match version 1.1.0
|
||||
|
||||
### Features
|
||||
- Added `Code Coverage session Events` [API](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/api/UnityEditor.TestTools.CodeCoverage.Events.html) to subscribe to events invoked during a Code Coverage session
|
||||
- Added `useProjectSettings` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/CoverageBatchmode.html) which allows using the settings specified in `ProjectSettings/Settings.json`
|
||||
- Added `pathStrippingPatterns` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/CoverageBatchmode.html) which allows stripping specific sections from the paths that are stored in the coverage results xml files
|
||||
- Added `sourcePaths` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.1/manual/CoverageBatchmode.html) which allows specifying the source directories which contain the corresponding source code
|
||||
|
||||
## [1.0.0] - 2021-03-09
|
||||
|
||||
### Fixes
|
||||
- Fixed issues with Path Filtering (cases [1318896](https://issuetracker.unity3d.com/issues/code-coverage-typing-comma-into-the-included-or-excluded-paths-list-will-start-adding-row-for-each-letter-you-type-afterwards), [1318897](https://issuetracker.unity3d.com/issues/code-coverage-clearing-last-included-paths-row-immediatly-jumps-to-the-first-excluded-paths-row-and-starts-editing-it))
|
||||
|
||||
### Improvements
|
||||
- Selection/focus is cleared when mouse is clicked outside of the individual settings' areas
|
||||
- Added [Quickstart guide](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/Quickstart.html) in documentation
|
||||
- Renamed the *Code Coverage Workshop* sample to *Code Coverage Tutorial*
|
||||
- Updated documentation and workshop to match version 1.0.0
|
||||
|
||||
**Note:** In Unity 2019 and 2020 you can enable Code Coverage in [General Preferences](https://docs.unity3d.com/Manual/Preferences.html). This was removed in Unity 2021; the user interface for managing Code Coverage is now entirely inside the Code Coverage package.
|
||||
|
||||
## [1.0.0-pre.4] - 2021-02-26
|
||||
|
||||
### Fixes
|
||||
- Fixed assembly version validation error due to internal libraries included in the ReportGeneratorMerged.dll (case [1312121](https://issuetracker.unity3d.com/issues/code-coverage-reportgeneratormerged-cant-be-loaded-due-to-assembly-version-validation-failure))
|
||||
|
||||
### Changes
|
||||
- Added *Enable Code Coverage* checkbox under Settings in [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/CodeCoverageWindow.html).<br/>**Note:** In Unity 2019 and 2020 you can enable Code Coverage in [General Preferences](https://docs.unity3d.com/Manual/Preferences.html). This was removed in Unity 2021; the user interface for managing Code Coverage is now entirely inside the Code Coverage package.
|
||||
- The settings and options passed in the command line override/disable the settings in the Code Coverage window and relevant warnings display to indicate this
|
||||
- Updated Report Generator to version 4.8.5
|
||||
- Updated documentation and workshop to match version 1.0.0-pre.4
|
||||
|
||||
### Improvements
|
||||
- Added `verbosity` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/CoverageBatchmode.html)
|
||||
- Added *Generate combined report from separate projects* section in documentation, under [Using Code Coverage in batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/CoverageBatchmode.html#generate-combined-report-from-separate-projects)
|
||||
|
||||
## [1.0.0-pre.3] - 2021-01-21
|
||||
|
||||
### Fixes
|
||||
- Updated Include Platforms to Editor only in the ReportGeneratorMerged.dll settings. Fixes an Android build error introduced in 1.0.0-pre.2 (case 1306557)
|
||||
|
||||
## [1.0.0-pre.2] - 2021-01-13
|
||||
|
||||
### Fixes
|
||||
- Fixed multiple reports generated in batchmode when passing `generateHtmlReport` in *-coverageOptions* without passing `-runTests`
|
||||
|
||||
### Changes
|
||||
- All project assemblies are included when there are included paths specified in *pathFilters* but no included assemblies in *assemblyFilters*, when running in batchmode
|
||||
- Updated Report Generator to version 4.8.4
|
||||
- Updated documentation to match version 1.0.0-pre.2
|
||||
|
||||
### Improvements
|
||||
- Introduced new *assemblyFilters* aliases in [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/CoverageBatchmode.html), used for referencing a group of assemblies to include or exclude. These are `<user>`, `<project>` and `<packages>`
|
||||
|
||||
## [1.0.0-pre.1] - 2020-11-12
|
||||
- *1.0.0-pre.1* matches *0.4.0-preview*
|
||||
|
||||
## [0.4.0-preview] - 2020-11-11
|
||||
|
||||
### Changes
|
||||
- Moved Code Coverage window under *Window* > *Analysis*
|
||||
- *Included Assemblies* now use a single dropdown instead of an editable text field which acted as a dropdown
|
||||
- Added CommandLineParser and removed dependency to internals in Test Framework
|
||||
- Removed the old *EditorPref* workflow from CoveragePreferences
|
||||
- Moved *Generate History* outside of *Generate HTML Report*. It is now disabled only if both *Generate HTML Report* and *Generate Badges* are not selected
|
||||
- Updated Report Generator to version 4.7.1
|
||||
- Updated documentation and workshop to match version 0.4.0-preview
|
||||
|
||||
### Improvements
|
||||
- Implemented `{ProjectPath}` alias in `Settings.json`
|
||||
- Added a console warning when *Burst Compilation* is enabled and an info HelpBox with a button to disable
|
||||
- Added Analytics to help improve the user experience
|
||||
- Disabled *Generate from Last* button when there are no assemblies selected
|
||||
- Display an info HelpBox when there are no assemblies selected
|
||||
- Paths are now stored with forward slashes on Windows
|
||||
- Added warning about Code Coverage not being supported currently when running PlayMode tests in standalone player
|
||||
- Refactored code; in Utils, Filtering, ResultWriter, Window and API classes
|
||||
- Added *CoverageWindow* and *Filtering* folders
|
||||
|
||||
### Features
|
||||
- Added *Included Paths* and *Excluded Paths* as ReorderableLists in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.4/manual/CodeCoverageWindow.html)
|
||||
- Added [support](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.4/manual/UsingCodeCoverage.html#excluding-code-from-code-coverage) for `ExcludeFromCoverage` and `ExcludeFromCodeCoverage` attributes
|
||||
- Added `CodeCoverage.VerbosityLevel` [API](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.4/api/UnityEditor.TestTools.CodeCoverage.CodeCoverage.html) to set the verbosity level used in editor and console logs
|
||||
|
||||
## [0.3.1-preview] - 2020-08-03
|
||||
|
||||
### Fixes
|
||||
- Fixed issue where CRAP calculation was incorrect when generic methods were parsed
|
||||
- Corrected Six Labors License copyright in Third Party Notices
|
||||
|
||||
### Changes
|
||||
- If `assemblyFilters` is not specified in *-coverageOptions* in batchmode, include only the assemblies found under the *Assets* folder
|
||||
- Updated Report Generator to version 4.6.4
|
||||
|
||||
## [0.3.0-preview] - 2020-05-20
|
||||
|
||||
### Fixes
|
||||
- Make sure *operator* and *anonymous function* names are generated correctly
|
||||
|
||||
### Changes
|
||||
- Added *Generate Additional Metrics* setting in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.3/manual/CodeCoverageWindow.html) and removed *Cyclomatic Complexity* (it is now included in Additional Metrics)
|
||||
- Updated Report Generator to version 4.5.8
|
||||
- Updated documentation to match version 0.3.0-preview
|
||||
|
||||
### Improvements
|
||||
- Added [Code Coverage Workshop](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.3/manual/CodeCoverageWorkshop.html) sample project
|
||||
- Using the [Settings Manager](https://docs.unity3d.com/Manual/com.unity.settings-manager.html) package to handle the serialization of project settings
|
||||
- Added an info HelpBox when *Code Optimization* is set to Release mode with a button to switch to Debug mode
|
||||
- Execute *Stop Recording* on the update loop, instead of the OnGUI (removes an *EndLayoutGroup* error)
|
||||
- Refactored code; in OpenCoverReporter class (to reduce Cyclomatic Complexity), in CodeCoverageWindow class and others
|
||||
|
||||
### Features
|
||||
- Added *History Location* and *Generate History* settings in the [Code Coverage window](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.3/manual/CodeCoverageWindow.html)
|
||||
- Added `coverageHistoryPath` and `generateHtmlReportHistory` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.3/manual/UsingCodeCoverage.html#using-code-coverage-in-batchmode)
|
||||
- Added `generateAdditionalMetrics` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.3/manual/UsingCodeCoverage.html#using-code-coverage-in-batchmode) and removed *enableCyclomaticComplexity* (it is now included in Additional Metrics)
|
||||
- Added *Crap Score* in Additional Metrics. See [How to interpret the results](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.3/manual/HowToInterpretResults.html).
|
||||
|
||||
## [0.2.3-preview] - 2020-02-18
|
||||
|
||||
### Fixes
|
||||
- *Included Assemblies* dropdown is now resizing to the longest assembly name ([1215600](https://issuetracker.unity3d.com/issues/there-is-no-way-to-view-the-full-name-of-an-assembly-when-selecting-it-in-a-small-code-coverage-window))
|
||||
- When closing (selecting outside of) the *Included Assemblies* dropdown, input is not accidentally propagated to the Code Coverage window
|
||||
|
||||
### Improvements
|
||||
- If more than one instance of the *-coverageOptions* command-line argument is specified, they will now be merged into a single instance
|
||||
- If more than one instance of the *-coverageResultsPath* command-line argument is specified, only the first instance will be accepted
|
||||
- Added *Generate combined report from EditMode and PlayMode tests* section in documentation, under [Using Code Coverage in batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.2/manual/UsingCodeCoverage.html#using-code-coverage-in-batchmode)
|
||||
|
||||
## [0.2.2-preview] - 2019-12-11
|
||||
|
||||
### Fixes
|
||||
- Fixed unassigned *CodeCoverageWindow.m_IncludeWarnings* warning in 2019.3
|
||||
|
||||
### Changes
|
||||
- The default *Included Assemblies* are now only the assemblies found under the project's *Assets* folder, instead of all project assemblies
|
||||
|
||||
### Improvements
|
||||
- After the report is generated, the file viewer window highlights the `index.htm` file, if *Generate HTML Report* is selected
|
||||
|
||||
## [0.2.1-preview] - 2019-12-04
|
||||
|
||||
### Improvements
|
||||
- Improved globbing for `pathFilters` and `assemblyFilters`
|
||||
- Added new sections and examples in documentation
|
||||
- Added confirmation dialogs when selecting *Clear Data* and *Clear History* buttons
|
||||
- Added warning and button to switch to debug mode, when using Code Optimization in release mode in 2020.1 and above
|
||||
|
||||
### Features
|
||||
- Added `pathFilters` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.2/manual/UsingCodeCoverage.html#using-code-coverage-in-batchmode)
|
||||
|
||||
## [0.2.0-preview] - 2019-11-13
|
||||
|
||||
### Fixes
|
||||
- Make sure recording coverage results are saved in the *Recording* folder, and starting a new recording session does not affect existing non-recording data
|
||||
|
||||
### Changes
|
||||
- Updated Report Generator to version 4.3.6
|
||||
- Split documentation into separate pages
|
||||
|
||||
### Improvements
|
||||
- Updated UX design of the Code Coverage window
|
||||
- Make sure settings and Record button are disabled when coverage is running
|
||||
- Make sure coverage window is disabled before unity is restarted when *Enabling Code Coverage* in Preferences
|
||||
- Only parse xml files with the correct filename format when generating the report
|
||||
- Implemented try/catch when deleting files/folders when selecting *Clear Data* or *Clear History*
|
||||
- Handle nested classes, nested generic classes and anonymous functions
|
||||
|
||||
### Features
|
||||
- Exposed `CodeCoverage.StartRecording()`, `CodeCoverage.StopRecording()`, `CodeCoverage.PauseRecording()` and `CodeCoverage.UnpauseRecording()` [API](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.2/api/UnityEditor.TestTools.CodeCoverage.CodeCoverage.html)
|
||||
|
||||
## [0.1.0-preview.3] - 2019-09-27
|
||||
|
||||
### Improvements
|
||||
- Passing `-coverageOptions generateHtmlReport` on the command line now creates a report if `-runTests` is not passed
|
||||
|
||||
## [0.1.0-preview.2] - 2019-09-23
|
||||
|
||||
### Changes
|
||||
- Updated Report Generator to version 4.2.20
|
||||
|
||||
### Improvements
|
||||
- Added support for correct naming of c# operators
|
||||
- Added support for correct naming of constructors
|
||||
- Added declaring type name as a prefix
|
||||
- Added support for return types in method names
|
||||
|
||||
### Features
|
||||
- Added [Coverage Recording](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@0.2/manual/CoverageRecording.html) feature
|
||||
|
||||
## [0.1.0-preview.0] - 2019-03-18
|
||||
|
||||
### This is the first release of *Code Coverage Package*
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6351153cf5e1af468cae5dbc72d1a04
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
# Code Coverage window
|
||||
|
||||

|
||||
|
||||
|**Toolbar**|**Description**|
|
||||
|:---|:---|
|
||||
||Select **Start Recording** to start recording code coverage data and **Stop Recording** to stop recording.|
|
||||
||Select **Pause Recording** to pause recording code coverage data and **Resume Recording** to resume recording. The buttons are disabled if not in a [Coverage Recording](CoverageRecording.md) session.|
|
||||
|Generate Report|Select **Generate Report** to generate a coverage report from the last set of tests that were run in the [Test Runner](CoverageTestRunner.md) or from the last [Coverage Recording](CoverageRecording.md) session. Note that **Generate Report** is disabled if no tests ran, there is no Coverage Recording data or all **HTML Report**, **Additional Reports** and **Summary Badges** checkboxes are unchecked.|
|
||||
|Clear Results|Select **Clear Results** to clear the coverage data from previous test runs or from previous [Coverage Recording](CoverageRecording.md) sessions. **Clear Results** is disabled if the coverage results are cleared, if no tests ran, or if there is no Coverage Recording data.|
|
||||
|Clear History|Select **Clear History** to clear the coverage report history. **Clear History** is disabled if the history is cleared or if no reports were generated.|
|
||||
||Select **Help** to open the Documentation Reference for Code Coverage in the web browser.|
|
||||
|**Settings**|**Description**|
|
||||
|Enable Code Coverage|Check this to enable Code Coverage. This is required in order to generate Coverage data and reports. Note that Code Coverage can affect the Editor performance.|
|
||||
|Results Location|Select the dropdown to open or specify the folder where the coverage results and report are saved to, and to reset to the default location. The default location is the Project's folder.|
|
||||
|Report History Location|Select the dropdown to open or specify the folder where the coverage report history is saved to, and to reset to the default location. The default location is the Project's folder.|
|
||||
|Included Assemblies|Specify assemblies to be included in the coverage results. This is a dropdown list containing the available assemblies. Click the dropdown to view, select or deselect the assemblies. Select **All** to select all the assemblies in the project. Select **Assets** to select only the assemblies under the `Assets` folder. Select **Packages** to select only the Packages' assemblies. Select **Deselect All** to deselect all the assemblies.</br></br>**Note:** If searching, the buttons will apply only to the assemblies visible in the list.|
|
||||
|Included Paths|Select **Add (+)** to specify individual folders and files to include in coverage results. You can use globbing to filter the paths. If the list is empty, Unity includes all files in the **Included Assemblies**. To remove an individual list entry, select the entry and then select **Remove (-)**.|
|
||||
|Excluded Paths|Select **Add (+)** to specify individual folders and files to exclude from coverage results. You can use globbing to filter the paths. To remove an individual list entry, select the entry and then select **Remove (-)**.|
|
||||
|Log Verbosity Level|Click the dropdown to set the verbosity level for the editor and console logs. The default level is `Info`.<br/><br/>**Levels:**<br/>`Verbose` All logs will be printed.<br/>`Info` Logs, Warnings and Errors will be printed.<br/>`Warning` Warnings and Errors will be printed.<br/>`Error` Only Errors will be printed.<br/>`Off` No logs will be printed.|
|
||||
|**Report Options**|**Description**|
|
||||
|HTML Report|Check this to generate an [HTML report](HowToInterpretResults.md).|
|
||||
|Additional Reports|Check this to generate [SonarQube](https://docs.sonarqube.org/latest/analysis/generic-test), [Cobertura](https://cobertura.github.io/cobertura) and [LCOV](https://github.com/linux-test-project/lcov) reports.|
|
||||
|Report History|Check this to generate and include the coverage history in the HTML report.|
|
||||
|Summary Badges|Check this to generate coverage summary badges in SVG and PNG format.|
|
||||
|Additional Metrics|Check this to generate and include additional metrics in the HTML report. These currently include Cyclomatic Complexity and Crap Score calculations for each method. See the [Risk Hotspots](HowToInterpretResults.md#risk-hotspots) section for more information.|
|
||||
|Test Runner References|Check this to include test references to the generated coverage results and enable the [Coverage by test methods](HowToInterpretResults.md#coverage-by-test-methods) section in the HTML report. This shows how each test contributes to the overall coverage.|
|
||||
|Auto Generate Report|Check this to generate the report automatically after the [Test Runner](CoverageTestRunner.md) finishes running or the [Coverage Recording](CoverageRecording.md) session is complete.|
|
||||
|Auto Open Report|Check this to open the coverage report automatically after it has been generated.|
|
||||
@@ -0,0 +1,97 @@
|
||||
# Using Code Coverage in batchmode
|
||||
|
||||
You can pass the following arguments in batchmode:
|
||||
|
||||
**-enableCodeCoverage**, to enable code coverage.
|
||||
**-coverageResultsPath** (optional), to set the location where the coverage results and report are saved to. The default location is the project's path.
|
||||
**-coverageHistoryPath** (optional), to set the location where the coverage report history is saved to. The default location is the project's path.
|
||||
**-coverageOptions** (optional), to pass extra options. Options are separated by semicolon. Some shells use semicolons to separate commands. Therefore, to ensure that coverage options are parsed correctly, enclose them in quotation marks.
|
||||
|
||||
|Coverage Option|Description|
|
||||
|:---|:---|
|
||||
|`generateHtmlReport`|Add this to generate a coverage [HTML report](HowToInterpretResults.md).|
|
||||
|`generateHtmlReportHistory`|Add this to generate and include the coverage history in the HTML report.|
|
||||
|`generateAdditionalReports`|Add this to generate [SonarQube](https://docs.sonarqube.org/latest/analysis/generic-test), [Cobertura](https://cobertura.github.io/cobertura) and [LCOV](https://github.com/linux-test-project/lcov) reports.|
|
||||
|`generateBadgeReport`|Add this to generate coverage summary badges in SVG and PNG format.|
|
||||
|`generateAdditionalMetrics`|Add this to generate and include additional metrics in the HTML report. These currently include Cyclomatic Complexity and Crap Score calculations for each method. See the [Risk Hotspots](HowToInterpretResults.md#risk-hotspots) section for more information.|
|
||||
|`generateTestReferences`|Add this to include test references to the generated coverage results and enable the [Coverage by test methods](HowToInterpretResults.md#coverage-by-test-methods) section in the HTML report. This shows how each test contributes to the overall coverage.|
|
||||
|`verbosity`|Add this to set the verbosity level for the editor and console logs. The default value is `info`.<br/>**Values:** `verbose`, `info`, `warning`, `error`, `off`|
|
||||
|`useProjectSettings`|Add this to use the settings specified in `ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json` instead. Any options passed in the command line will override this. This option can only be used in batchmode and it does not take effect when running the editor from the command line in non-batchmode.|
|
||||
|`dontClear`|Add this to allow coverage results to be accumulated after every code coverage session. If not passed the results are cleared before a new session. For more information see [Generate combined report from EditMode and PlayMode tests](#generate-combined-report-from-editmode-and-playmode-tests).|
|
||||
|`sourcePaths`|Add this to specify the source directories which contain the corresponding source code. The source directories are used by the report generator when the path information of classes cannot be determined. This is a comma separated string. Globbing is not supported.<br/><br/>**Example:** See [Generate combined report from separate projects](#generate-combined-report-from-separate-projects).|
|
||||
|`assemblyFilters`|Add this to specify the assemblies to include or exclude in the coverage calculation and/or report. This is a comma-separated string. Prefix assemblies with `+` to include them or with `-` to exclude them. Globbing can be used to filter the assemblies.<br/><br/>**Available aliases:**<br/><br/>`<all>` maps to all the assemblies in the project.<br/>`<assets>` maps to the assemblies under the `Assets` folder.<br/>`<packages>` maps to the Packages' assemblies in the project, including the built-in packages.<br/><br/>**By default, if there are no included assemblies specified, only the assemblies under the `Assets` folder will be included.**<br/><br/>**Examples:**<br/><br/>`assemblyFilters:+<all>` will include code from all the assemblies in the project.<br/>`assemblyFilters:+my.assembly` will only include code from the assembly called `my.assembly`.<br/>`assemblyFilters:+unity.*` will include code from any assembly whose name starts with `unity.`<br/>`assemblyFilters:-*unity*` will exclude code from all assemblies that contain the word `unity` in their names.<br/>`assemblyFilters:+my.assembly.*,-my.assembly.tests` will include code from any assembly whose name starts with `my.assembly.`, but will explicitly exclude code from the assembly called `my.assembly.tests`.<br/>`assemblyFilters:+my.locale.??` will only include code from assemblies whose names match this format, e.g. `my.locale.en`, `my.locale.99`, etc.<br/>`assemblyFilters:+my.assembly.[a-z][0-9]` will only include code from assemblies whose names match this format, e.g. `my.assembly.a1`, `my.assembly.q7`, etc.|
|
||||
|`pathFilters`|Add this to specify the paths that should be included or excluded in the coverage calculation and/or report. This is a comma-separated string. Prefix paths with `+` to include them and with `-` to exclude them. Globbing can be used to filter the paths.<br/><br/>Both absolute and relative paths are supported. Absolute paths can be shortened using globbing e.g. `**/Assets/Scripts/`. Relative paths require the `sourcePaths` option to be set. See [Using relative paths in path filters](#using-relative-paths-in-path-filters).<br/><br/>**Note:** If `pathFilters` are specified and there are no included assemblies specified in `assemblyFilters`, then all the assemblies in the project are included in order for `path filtering` to take precedence over `assembly filtering`.<br/><br/><br/>**Examples:**<br/><br/>`pathFilters:+C:/MyProject/Assets/MyClass.cs` will only include the `MyClass.cs` file.<br/>`pathFilters:+C:/MyProject/Assets/Scripts/*` will include all files in the `C:/MyProject/Assets/Scripts` folder. Files in subfolders will not be included.<br/>`pathFilters:-C:/MyProject/Assets/AutoGenerated/**` will exclude all files under the `C:/MyProject/Assets/AutoGenerated` folder and any of its subfolders.<br/>`pathFilters:+**/Assets/Editor/**` will include just the files that have `/Assets/Editor/` in their path.<br/>`pathFilters:+C:/MyProject/Assets/**/MyClass.cs` will include any file named `MyClass.cs` that is under the `C:/MyProject/Assets` folder and any of its subfolders.<br/>`pathFilters:+C:/MyProject/**,-**/Packages/**` will only include files under `C:/MyProject/` folder and exclude all files under any `Packages` folder.<br/>`pathFilters:+**/MyGeneratedClass_??.cs` will include only files with filenames that match this format, i.e. `MyGeneratedClass_01.cs`, `MyGeneratedClass_AB.cs`, etc.<br/>`pathFilters:+**/MyClass_[A-Z][0-9].cs` will include only files with filenames that match this format, i.e. `MyClass_A1.cs`, `MyClass_Q7.cs`, etc.|
|
||||
|`pathFiltersFromFile`|Add this to specify the file to read path filtering rules from. Instead of defining all path filtering rules directly in the command line, as you would with the `pathFilters` option, this allows you to store them in a separate file, making your commands clearer and easier to manage.<br/><br/>Like with the `pathFilters` option, `pathFiltersFromFile` also supports relative paths. See [Using relative paths in path filters](#using-relative-paths-in-path-filters).<br/><br/>**Examples:**<br/><br/>`pathFiltersFromFile:C:/MyProject/FilteringRules.txt` will read rules from a file located in `C:/MyProject/FilteringRules.txt`<br/>`pathFiltersFromFile:FilteringRules.txt` will read rules from `FilteringRules.txt` located in the root of your project.<br/><br/>Syntax of the rules is the same as with the `pathFilters` option, however, rules should be listed in separate lines in the file.<br/><br/>**File example:**<br/><br/>This will include all the files in the `Scripts` folder and exclude all the files in the `Scripts/Generated` folder<pre><code>+**/Scripts/**<br/>-**/Scripts/Generated/**</code></pre><br/>**Note:** The `pathFiltersFromFile` option will be deprecated in the next package major release. Please use the `filtersFromFile` option instead.|
|
||||
|`filtersFromFile`|Add this to specify the json file to read path and assembly filtering rules from. Instead of defining all filtering rules directly in the command line, as you would with `pathFilters` and `assemblyFilters` options, this allows you to store them in a separate file, making your commands clearer and easier to manage.<br/><br/>Like with the `pathFilters` option, `filtersFromFile` also supports relative paths. See [Using relative paths in path filters](#using-relative-paths-in-path-filters).<br/><br/>**Examples:**<br/><br/>`filtersFromfile:C:/MyProject/FilteringRules.json` will read rules from a file located in `C:/MyProject/FilteringRules.json`.<br/>`filtersFromFile:FilteringRules.json` will read rules from `FilteringRules.json` located in the root of your project.<br/><br/>**File example:**<br/><br/>This will include the `my.included.assembly`, exclude `my.excluded.assembly` and all assemblies with `unity` in their name. It will also include all files in the `Scripts` folder, and exclude all files in the `Scripts/Generated` folder<pre><code>{<br/> "assembliesInclude": [<br/> "my.included.assembly"<br/> ],<br/> "assembliesExclude": [<br/> "my.excluded.assembly",<br/> "*unity*"<br/> ],<br/> "pathsInclude": [<br/> "**/Scripts/**"<br/> ],<br/> "pathsExclude": [<br/> "**/Scripts/Generated/**"<br/> ]</br>}</pre></code><br/>**Note:** The `pathFiltersFromFile` option will be deprecated in the next package major release. Please use the `filtersFromFile` option instead.|
|
||||
|`pathReplacePatterns`|Add this to replace specific sections from the paths that are stored in the coverage results xml files. This is a comma separated string and requires elements to be passed in pairs i.e. `pathReplacePatterns:from,to,from,to`. Globbing is supported.<br/><br/>You can change the file paths in the coverage results xml to relative paths so that coverage data generated on different machines can be merged into a single report. Use the `pathReplacePatterns` option in conjunction with the `sourcePaths` option to specify the source directories which contain the corresponding source code. For more information see [Generate combined report from separate projects](#generate-combined-report-from-separate-projects).<br/><br/>**Note:** The [OpenCover](https://github.com/OpenCover/opencover) results xml format specifies file paths as absolute paths (`fullPath`). Changing these paths to relative paths will invalidate the OpenCover standard format. When the results xml files are fed into other tools, these may not work as expected if the paths are relative.<br/><br/>**Examples:**<br/><br/>`pathReplacePatterns:C:/MyProject,C:/MyOtherProject` will store the path as `C:/MyOtherProject/Assets/Scripts/MyScript.cs`, when the original path is `C:/MyProject/Assets/Scripts/MyScript.cs`<br/>`pathReplacePatterns:@*,,**/PackageCache/,Packages/` will store the path as `Packages/com.unity.my.package/Editor/MyScript.cs`, when the original path is `C:/Project/Library/PackageCache/com.unity.my.package@12345/Editor/MyScript.cs`<br/>`pathReplacePatterns:C:/MyProject/,` will store the path as `Assets/Scripts/MyScript.cs`, when the original path is `C:/MyProject/Assets/Scripts/MyScript.cs`<br/>`pathReplacePatterns:**Assets/,` will store the path as `Scripts/MyScript.cs`, when the original path is `C:/MyProject/Assets/Scripts/MyScript.cs`<br/>`pathReplacePatterns:C:/*/Assets/,` will store the path as `Scripts/MyScript.cs`, when the original path is `C:/MyProject/Assets/Scripts/MyScript.cs`<br/>`pathReplacePatterns:C:/MyProject??/,` will store the path as `Assets/Scripts/MyScript.cs`, when the original path is `C:/MyProject01/Assets/Scripts/MyScript.cs`<br/>`pathReplacePatterns:**/MyProject[A-Z][0-9]/,` will store the path as `Assets/Scripts/MyScript.cs`, when the original path is `C:/MyProjectA1/Assets/Scripts/MyScript.cs`|
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
Unity.exe -projectPath <path-to-project> -batchmode -testPlatform editmode -runTests -testResults
|
||||
<path-to-results-xml> -debugCodeOptimization
|
||||
-enableCodeCoverage
|
||||
-coverageResultsPath <path-to-coverage-results>
|
||||
-coverageHistoryPath <path-to-coverage-history>
|
||||
-coverageOptions "generateAdditionalMetrics;generateHtmlReport;generateHtmlReportHistory;generateBadgeReport;
|
||||
assemblyFilters:+my.assembly.*,+<packages>;
|
||||
pathFilters:-**/Tests/**,-**/BuiltInPackages/**"
|
||||
```
|
||||
The example above opens the project at `\<path-to-project\>`, runs the `EditMode` tests and produces an HTML coverage report and coverage summary badges in `\<path-to-coverage-results\>`. The report includes the coverage history, Cyclomatic Complexity and Crap Score calculations. The coverage history files are saved in `\<path-to-coverage-history\>`.
|
||||
|
||||
Additionally, the report includes code from any assembly whose name starts with `my.assembly.`, and includes code from all the Packages' assemblies. It excludes files that have `/Tests/` in their path (i.e. all the files under the Tests folder) and also excludes files that have `/BuiltInPackages/` in their path (i.e. all the built-in packages).
|
||||
|
||||
**Note:** `-debugCodeOptimization` is passed above to ensure Code optimization is set to Debug mode. See [Using Code Coverage with Code Optimization](UsingCodeCoverage.md#using-code-coverage-with-code-optimization).
|
||||
|
||||
## Generate combined report from EditMode and PlayMode tests
|
||||
|
||||
To get coverage information for both EditMode and PlayMode tests, run the editor three times as shown in the example below:
|
||||
```
|
||||
Unity.exe -projectPath <path-to-project> -batchmode -testPlatform editmode -runTests -debugCodeOptimization -enableCodeCoverage -coverageResultsPath <path-to-coverage-results>
|
||||
-coverageOptions "generateAdditionalMetrics;assemblyFilters:+my.assembly.*;dontClear"
|
||||
|
||||
Unity.exe -projectPath <path-to-project> -batchmode -testPlatform playmode -runTests -debugCodeOptimization -enableCodeCoverage -coverageResultsPath <path-to-coverage-results>
|
||||
-coverageOptions "generateAdditionalMetrics;assemblyFilters:+my.assembly.*;dontClear"
|
||||
|
||||
Unity.exe -projectPath <path-to-project> -batchmode -debugCodeOptimization -enableCodeCoverage -coverageResultsPath <path-to-coverage-results>
|
||||
-coverageOptions "generateHtmlReport;generateBadgeReport;assemblyFilters:+my.assembly.*" -quit
|
||||
```
|
||||
The first generates the coverage results for the EditMode tests, the second generates the coverage results for the PlayMode tests and the third generates the coverage report and summary badges based on both coverage results.<br/><br/>**Note:** In [Unity Test Framework 2.0](https://docs.unity3d.com/Packages/com.unity.test-framework@2.0) and above the coverage results from both the EditMode and PlayMode test runs are stored in the `Automated` folder. In this example, passing the `dontClear` coverage option ensures that the results from the EditMode test run are not cleared during the PlayMode test run.
|
||||
|
||||
## Generate combined report from separate projects
|
||||
|
||||
To get a coverage report for your shared code which is used on separate projects, run the tests for each project making sure the `-coverageResultsPath` points to a separate location inside a shared root folder as shown in the example below:
|
||||
```
|
||||
Unity.exe -projectPath C:/MyProject -batchmode -testPlatform playmode -runTests -debugCodeOptimization -enableCodeCoverage -coverageResultsPath C:/CoverageResults/MyProject
|
||||
-coverageOptions "generateAdditionalMetrics;assemblyFilters:+my.assembly.*;pathReplacePatterns:C:/MyProject/,"
|
||||
|
||||
Unity.exe -projectPath C:/MyOtherProject -batchmode -testPlatform playmode -runTests -debugCodeOptimization -enableCodeCoverage -coverageResultsPath C:/CoverageResults/MyOtherProject
|
||||
-coverageOptions "generateAdditionalMetrics;assemblyFilters:+my.assembly.*;pathReplacePatterns:C:/MyOtherProject/,"
|
||||
|
||||
Unity.exe -projectPath C:/MyProject -batchmode -debugCodeOptimization -enableCodeCoverage -coverageResultsPath C:/CoverageResults
|
||||
-coverageOptions "generateHtmlReport;generateBadgeReport;assemblyFilters:+my.assembly.*;sourcePaths:C:/MyProject" -quit
|
||||
```
|
||||
The first run generates the coverage results for the PlayMode tests for `MyProject` and stores these in `C:/CoverageResults/MyProject`. The second run generates the coverage results for the PlayMode tests for `MyOtherProject` and stores these in `C:/CoverageResults/MyOtherProject`. The third run generates the coverage report and summary badges based on the results found under the common `C:/CoverageResults` folder.
|
||||
|
||||
## Using relative paths in path filters ##
|
||||
|
||||
When the `sourcePaths` option is specified, the path filtering rules set by the `pathFilters`, `pathFiltersFromFile` and `filtersFromFile` options can be defined as relative paths.
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
Unity.exe -projectPath C:/MyProject -batchmode -testPlatform playmode -runTests -debugCodeOptimization -enableCodeCoverage -coverageResultsPath C:/CoverageResults/MyProject
|
||||
-coverageOptions "generateHtmlReport;generateAdditionalMetrics;assemblyFilters:+<all>;pathFiltersFromFile:FilteringRules.txt;sourcePaths:C:/MyProject/Assets"
|
||||
```
|
||||
|
||||
`FilteringRules.txt`
|
||||
```
|
||||
+Scripts/Animation/**
|
||||
-**/Generated/**
|
||||
+C:/MyPackages/com.my.company.mypackage/**
|
||||
```
|
||||
|
||||
This example contains three rules:
|
||||
* `+Scripts/Animation/**` - because the `sourcePaths` option was set and this is a relative path, this rule will include all the scripts in the `C:/MyProject/Assets/Scripts/Animation` folder and its subfolders.
|
||||
* `-**/Generated/**` - excludes all the files that have `/Generated/` in their path. This is not a relative path so the `sourcePaths` option has no effect.
|
||||
* `+C:/MyPackages/com.my.company.mypackage/**` - includes all the scripts located in the package outside of the project. This is an absolute path so the `sourcePaths` option has no effect.
|
||||
@@ -0,0 +1,34 @@
|
||||
# On-demand coverage recording
|
||||
|
||||
With Coverage Recording you can capture coverage data on demand and generate an [HTML report](HowToInterpretResults.md) which shows which lines of your code run while recording. It supports capturing in EditMode as well as in PlayMode, and you can switch between the two.
|
||||
|
||||
To start recording coverage data, select **Start Recording**. While recording, use the Editor as usual, for example to enter PlayMode. To stop recording coverage data, select **Stop Recording**. If **Auto Generate Report** is checked, then an [HTML report](HowToInterpretResults.md) is generated and a file viewer window opens (if **Auto Open Report** is checked too). It contains the coverage results and the report. Otherwise, select **Generate Report** to generate the report. The results are based on the assemblies specified in **Included Assemblies**.
|
||||
|
||||
You can also control Coverage Recording via the [CodeCoverage ScriptingAPI](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@latest/index.html?subfolder=/api/UnityEditor.TestTools.CodeCoverage.CodeCoverage.html).
|
||||
|
||||
## Steps
|
||||
|
||||
1. Open the [Code Coverage window](CodeCoverageWindow.md) (go to **Window** > **Analysis** > **Code Coverage**).<br/><br/>
|
||||

|
||||
|
||||
2. Select **Enable Code Coverage** if not already selected, to be able to generate Coverage data and reports.<br/>
|
||||
<br/>**Note:** Enabling Code Coverage adds some overhead to the Editor and can affect the performance.
|
||||
|
||||
3. Select the [Assembly Definitions](https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html) you would like to see the coverage for. In this example we selected `Assembly-CSharp` and `Assembly-CSharp-Editor`. By default, Unity compiles almost all project scripts into the `Assembly-CSharp.dll` managed assembly and all Editor scripts into the `Assembly-CSharp-Editor.dll` managed assembly.<br/><br/>
|
||||

|
||||
|
||||
4. Select **Start Recording**.<br/>
|
||||

|
||||
|
||||
5. Continue using the Editor as normal, for example enter PlayMode to test your application or run some manual testing. You can also select **Pause Recording** to pause recording and **Resume Recording** to resume recording.
|
||||
|
||||
6. When you have finished your testing and have collected enough coverage data, select **Stop Recording**.<br/>
|
||||

|
||||
|
||||
7. If **Auto Open Report** is checked a file viewer window opens containing the coverage report. Alternatively, select the **Results Location** dropdown to open it in the file viewer.<br/><br/>**Note:** To generate the report automatically after you stop recording, select **Auto Generate Report** in the [Code Coverage window](CodeCoverageWindow.md). Alternatively, you can select **Generate Report**.<br/>
|
||||
|
||||
8. Select `index.htm`.<br/><br/>
|
||||

|
||||
|
||||
9. This opens the [HTML coverage report](HowToInterpretResults.md).<br/><br/>
|
||||

|
||||
@@ -0,0 +1,55 @@
|
||||
# Using Code Coverage with Test Runner
|
||||
|
||||
When running your tests in the [Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html?subfolder=/manual/workflow-run-test.html) you can generate an [HTML report](HowToInterpretResults.md) which shows which lines of your code the tests cover. This includes both `EditMode` and `PlayMode` tests.
|
||||
|
||||
If **Auto Generate Report** is checked, then an [HTML report](HowToInterpretResults.md) is generated and a file viewer window opens (if **Auto Open Report** is checked too). It contains the coverage results and the report. Otherwise, select **Generate Report** to generate the report. The results are based on the assemblies specified in **Included Assemblies**.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Open the [Code Coverage window](CodeCoverageWindow.md) (go to **Window** > **Analysis** > **Code Coverage**).<br/><br/>
|
||||

|
||||
|
||||
2. Select **Enable Code Coverage** if not already selected, to be able to generate Coverage data and reports.<br/>
|
||||
<br/>**Note:** Enabling Code Coverage adds some overhead to the Editor and can affect the performance.
|
||||
|
||||
3. Select the [Assembly Definitions](https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html) you would like to see the coverage for. In this example we selected `Assembly-CSharp` and `Assembly-CSharp-Editor`. By default, Unity compiles almost all project scripts into the `Assembly-CSharp.dll` managed assembly and all Editor scripts into the `Assembly-CSharp-Editor.dll` managed assembly.<br/><br/>
|
||||

|
||||
|
||||
4. Switch to the [Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html?subfolder=/manual/workflow-run-test.html) and run your `EditMode` and/or `PlayMode` test(s).<br/><br/>
|
||||

|
||||
|
||||
Example test:
|
||||
```
|
||||
using NUnit.Framework;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
public class EditorTests
|
||||
{
|
||||
[Test]
|
||||
public void MyPublicClass_PublicFunctionCanBeCalled()
|
||||
{
|
||||
MyPublicClass myPublicClass = new MyPublicClass();
|
||||
Assert.IsTrue(myPublicClass.MyPublicFunction());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
5. When the test(s) finish running, a file viewer window opens containing the coverage report. Alternatively, select the **Results Location** dropdown to open it in the file viewer.<br/><br/>**Note:** To generate the report automatically after the Test Runner has finished running the tests, select **Auto Generate Report** in the [Code Coverage window](CodeCoverageWindow.md). Alternatively, you can select **Generate Report**.<br/>
|
||||
|
||||
6. Select `index.htm`.<br/><br/>
|
||||

|
||||
<br/><br/>
|
||||
This opens the [HTML coverage report](HowToInterpretResults.md).<br/><br/>
|
||||

|
||||
<br/>
|
||||
|
||||
## Get results for EditMode and PlayMode tests
|
||||
|
||||
Coverage data are generated from the last set of tests that were run in the [Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html?subfolder=/manual/workflow-run-test.html).<br/><br/>
|
||||
**Note:** Currently the [Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html?subfolder=/manual/workflow-run-test.html) does not support `EditMode` and `PlayMode` tests running at the same time. In [version 2.0](https://docs.unity3d.com/Packages/com.unity.test-framework@2.0/manual/whats-new.html#added) of the Test Framework this will be possible. In the meantime, to include coverage for both `EditMode` and `PlayMode` tests, you must run these separately. In this case, the last Coverage Report generated will include the combined coverage of `EditMode` and `PlayMode` tests.
|
||||
|
||||
If a fresh start is required, select **Clear Results** to clear the Coverage data from all previous test runs for both `EditMode` and `PlayMode` tests.
|
||||
|
||||
## Get coverage by test methods
|
||||
|
||||
To see how each test contributes to the overall coverage check **Test Runner References**. For more details see [Coverage by test methods](HowToInterpretResults.md#coverage-by-test-methods).
|
||||
@@ -0,0 +1,21 @@
|
||||
# Document revision history - Archive
|
||||
|
||||
|Date|Reason|
|
||||
|:---|:---|
|
||||
|Feb 26, 2021|<li>Added information about the *Enable Code Coverage* setting in the Code Coverage window<li>Updated *Installing Code Coverage* section<li>Added *verbosity* section in *-coverageOptions*<li>Added *Generate combined report from separate projects* section<li>Matches package version *1.0.0-pre.4*|
|
||||
|Jan 13, 2021|<li>Added information about *assemblyFilters* aliases and note about how *path filtering* can take precedence over *assembly filtering* in *Using Code Coverage in batchmode* section<li>Matches package version *1.0.0-pre.2*|
|
||||
|Nov 12, 2020|<li>Matches package version *1.0.0-pre.1*|
|
||||
|Nov 11, 2020|<li>Added information about *Included Paths* and *Excluded Paths* settings in the Code Coverage window<li>Updated information about *Included Assemblies* setting in the Code Coverage window<li>Matches package version *0.4.0-preview*|
|
||||
|Aug 3, 2020|<li>Matches package version *0.3.1-preview*|
|
||||
|May 20, 2020|<li>Added information about the *History Location* and *Generate History* settings in the Code Coverage window and *coverageHistoryPath* and *generateHtmlReportHistory* in *-coverageOptions*<li>Added information about the *Generate Additional Metrics* setting in the Code Coverage window and *generateAdditionalMetrics* in *-coverageOptions*<li>Added information about *Coverage History* and *Crap Score* in *How to interpret the results* page<li>Updated *Installing Code Coverage* section<li>Matches package version *0.3.0-preview*|
|
||||
|Feb 18, 2020|<li>Added *Generate combined report from EditMode and PlayMode tests* section<li>Matches package version *0.2.3-preview*|
|
||||
|Dec 11, 2019|<li>Matches package version *0.2.2-preview*|
|
||||
|Dec 3, 2019|<li>Added *pathFilters* section<li>Added examples for *assemblyFilters* and *pathFilters*<li>Added a reference to the *Coverage Recording ScriptingAPI*<li>Matches package version *0.2.1-preview*|
|
||||
|Nov 10, 2019|<li>Split documentation into separate pages<li>Matches package version *0.2.0-preview*|
|
||||
|Nov 5, 2019|<li>Updated UX design|
|
||||
|Sep 27, 2019|<li>Added *Using Code Coverage with Burst compiler* section<li>Added *Using Code Coverage with Code Optimization* section<li>Matches package version *0.1.0-preview.3*|
|
||||
|Sep 23, 2019|<li>Added *Coverage Recording* section<li>Matches package version *0.1.0-preview.2*|
|
||||
|Aug 16, 2019|<li>Added *How to interpret the results* section<li>Added *How it works* section|
|
||||
|Aug 7, 2019|<li>Added *Clear Coverage Data* setting to *Settings* table<li>Added *Note* in *Using Code Coverage* section about combined coverage of EditMode and PlayMode tests|
|
||||
|Aug 5, 2019|<li>Updated *About Code Coverage* section and *Settings* table|
|
||||
|May 15, 2019|<li>Document created. Matches package version *0.1.0-preview.0*|
|
||||
@@ -0,0 +1,13 @@
|
||||
# Document revision history
|
||||
|
||||
|Date|Reason|
|
||||
|:---|:---|
|
||||
|Dec 20, 2023|<li>Matches package version *1.2.5*.|
|
||||
|Jun 02, 2023|<li>Corrected *Settings.json* path in **useProjectSettings** section in *-coverageOptions*.<li>Matches package version *1.2.4*.|
|
||||
|Apr 14, 2023|<li>Added **filtersFromFile** section in *-coverageOptions*.<li>Updated **Using Code Coverage with Burst compiler** section with the correct number of dashes for *--burst-disable-compilation*.<li>Matches package version *1.2.3*.|
|
||||
|Nov 18, 2022|<li>Added **Uncoverable lines** definition in **How to interpret the results** page.<li>Matches package version *1.2.2*.|
|
||||
|Oct 27, 2022|<li>Matches package version *1.2.1*.|
|
||||
|Aug 01, 2022|<li>Updated **What's new** and **Upgrade guide** pages.<li>Added information about the buttons in the **toolbar** in the Code Coverage window.<li>Added information about the **Log Verbosity Level** setting in the Code Coverage window.<li>Added information about the **Additional Reports**, **Test Runner References** and **Auto Open Report** options in the Code Coverage window.<li>Introduced new selection buttons under the **Included Assemblies** dropdown in the Code Coverage window.<li>Added **generateTestReferences**, **generateAdditionalReports**, **pathFiltersFromFile** and **dontClear** sections in *-coverageOptions*.<li>Added **pathReplacePatterns** section in *-coverageOptions*.<li>Removed **pathStrippingPatterns** section from *-coverageOptions* (replaced with **pathReplacePatterns**).<li>Renamed the aliases in the **assemblyFilters** command line option.<li>Updated the examples in the **pathFilters** command line option to follow the standard globbing paradigm.<li>Added **Using relative paths in path filters** section.<li>Added **Coverage by test methods** section.<li>Updated the **Quickstart - Code Coverage Tutorial** page.<li>Matches package version *1.2.0*.|
|
||||
|Dec 17, 2021|<li>Added **What's new** and **Upgrade guide** pages.<li>Matches package version *1.1.1*.|
|
||||
|Jun 09, 2021|<li>Added **Subscribing to Code Coverage session events** section.<li>Added **Ignoring tests for Code Coverage** section.<li>Added **useProjectSettings**, **pathStrippingPatterns** and **sourcePaths** sections in *-coverageOptions*.<li>Updated the **Generate combined report from separate projects** section.<li>Matches package version *1.1.0*.|
|
||||
|Mar 09, 2021|<li>Added **Quickstart** guide.<li>Matches package version *1.0.0*.|
|
||||
@@ -0,0 +1,64 @@
|
||||
# How to interpret the results
|
||||
|
||||
This section assumes that you checked **HTML Report** in the [Code Coverage window](CodeCoverageWindow.md) or passed the `generateHtmlReport` option in `-coverageOptions` on the [command line](CoverageBatchmode.md). If you're running the tests in the Editor, a file viewer window opens up containing the coverage report once the test run has been finished. If you're running the tests from the command line, navigate to the `-coverageResultsPath` location with your file viewer. Open the `Report` folder then open `index.htm` in a web browser. This shows a summary of the coverage results from the tests.<br/>
|
||||
|
||||

|
||||
|
||||
## Summary view
|
||||
|
||||
The summary view is divided into several sections: Summary, Coverage History, Risk Hotspots and Coverage.
|
||||
|
||||
### Summary
|
||||
|
||||
This section shows a brief summary of the coverage results including the number of assemblies, classes, files and lines that were processed. The most important value is the **Line Coverage** which shows the current coverage percentage of all coverable lines. Coverable lines only include the lines that can be executed and are colored either green or red in the [File(s)](#files) section depending on whether the line was covered or not. Uncoverable lines are the lines that cannot be executed and are not colored in the [File(s)](#files) section; these include lines containing:
|
||||
- Assemblies, Classes, Constructors, Methods and Structs that are marked to be [excluded from coverage](UsingCodeCoverage.md#excluding-code-from-code-coverage)
|
||||
- Directives
|
||||
- Attributes
|
||||
- Method signatures
|
||||
- Class definitions
|
||||
- Unassigned variable declarations
|
||||
- Constant variable declarations
|
||||
- else/case/default keywords
|
||||
- Lines from other classes, when multiple classes are included in the same file
|
||||
- Blank lines
|
||||
|
||||
### Coverage History
|
||||
|
||||
This section only appears if you checked **Report History** in the [Code Coverage window](CodeCoverageWindow.md) or passed the `generateHtmlReportHistory` option in `-coverageOptions` on the [command line](CoverageBatchmode.md). The Coverage History displays a graph showing the total percentage coverage for every test run for this project. Aim to keep this percentage as high as possible. If it is decreasing, consider writing more tests to improve your coverage.
|
||||
|
||||
### Risk Hotspots
|
||||
|
||||
This section only appears if you checked **Additional Metrics** in the [Code Coverage window](CodeCoverageWindow.md) or passed the `generateAdditionalMetrics` option in `-coverageOptions` on the [command line](CoverageBatchmode.md).
|
||||
|
||||
The Risk Hotspots display information about any methods that have a Cyclomatic Complexity score that is greater than 15. The Cyclomatic Complexity score is a value that is based on the number of paths that can be taken through a method. The score will tend to be higher if a method has a large number of `if` or `switch` statements. For more detailed information see the [Wikipedia entry on Cyclomatic Complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity). You will also see information about any methods with a high Crap Score. CRAP stands for Change Risk Anti-Patterns. For more detailed information see this [article](https://testing.googleblog.com/2011/02/this-code-is-crap.html).
|
||||
|
||||
If there are any methods with a very high Cyclomatic Complexity or Crap Score, consider refactoring the method to reduce its complexity.
|
||||
|
||||
**Note:** NPath Complexity calculation and Branch Coverage are not implemented at present so will always appear as zero.
|
||||
|
||||
### Coverage
|
||||
By default, this shows a list of the assemblies that have been covered together with some stats showing how well covered they are. Select **Expand (+)** next to the assembly name to see a list of the classes or structs within the assembly and their associated coverage data. To see more detailed information for a particular class, select its name in the list.
|
||||
|
||||
## Class/Struct view
|
||||
|
||||
### Summary
|
||||
|
||||
Similar to the Summary section of the previous page, this section shows some brief statistics for the selected class. The most important value is the Line Coverage percentage. Select **Back (<)** in the top left hand corner to return to the previous screen.
|
||||
|
||||
### Coverage History
|
||||
|
||||
This section only appears if you checked **Report History** in the [Code Coverage window](CodeCoverageWindow.md) or passed the `generateHtmlReportHistory` option in `-coverageOptions` on the [command line](CoverageBatchmode.md). It shows a graph of the coverage percentage of the class/struct over time. Try to keep this value as high as you can. Make sure that as you add new code the coverage percentage is maintained by adding more tests.
|
||||
|
||||
### Metrics
|
||||
|
||||
The metrics section displays a list of the methods and properties of the class, along with each method's Cyclomatic Complexity, Crap Score and Sequence Coverage scores. Currently, the NPath Complexity and Branch Coverage aren't calculated, so will always appear as zero.
|
||||
|
||||
### File(s)
|
||||
|
||||
The File(s) section shows the C# source code for the selected class. Each line is colored either green or red depending on whether the line was covered or not. The number in the left column indicates the number of times that the line was executed during a Test Runner or Coverage Recording session.
|
||||
|
||||
### Coverage by test methods
|
||||
|
||||
This section only appears if you checked **Test Runner References** in the [Code Coverage window](CodeCoverageWindow.md) or passed the `generateTestReferences` option in `-coverageOptions` on the [command line](CoverageBatchmode.md).
|
||||
|
||||
It shows a list of test methods allowing you to see how each test contributes to the overall coverage. Select a test method to view the relevant code or hover over the code to see which test method executed it.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Installing Code Coverage
|
||||
|
||||
Before you install the package, make sure you have no errors in the [Console](https://docs.unity3d.com/Manual/Console.html) window (in red text).
|
||||
|
||||
## From the Unity Package Manager
|
||||
|
||||
Use the [Unity Package Manager](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest) to find and install the Code Coverage package.
|
||||
|
||||

|
||||
|
||||
Alternatively, use the **Add (+)** dropdown and select **Add package from git URL...** or **Add package by name...** and type `com.unity.testtools.codecoverage`.
|
||||
|
||||

|
||||
|
||||
To verify that Code Coverage has been installed correctly, open the Code Coverage window (go to **Window** > **Analysis** > **Code Coverage**). If you don't see the **Code Coverage** menu item, then Code Coverage did not install correctly.
|
||||
|
||||
## Manually from the Package Manifest
|
||||
|
||||
You can also install the Code Coverage package manually. To do this, add a reference to Code Coverage in your project's `Packages/manifest.json` file. There are two ways you can reference a specific version of the Code Coverage package, depending on how you use it.
|
||||
|
||||
### Using a production version of the package
|
||||
|
||||
You can point the Package Manager at a publicly available version. To do this manually, add it to `manifest.json`:
|
||||
|
||||
```json
|
||||
"dependencies": {
|
||||
//...
|
||||
"com.unity.testtools.codecoverage":"<full version number>"
|
||||
}
|
||||
```
|
||||
|
||||
### Using a local clone of the package
|
||||
|
||||
If you want to use a cloned version of the package, you can point the Package Manager at a local folder as the package location:
|
||||
|
||||
```json
|
||||
"dependencies": {
|
||||
//...
|
||||
"com.unity.testtools.codecoverage":"file:path/to/package/root"
|
||||
}
|
||||
```
|
||||
|
||||
To verify that Code Coverage has been installed correctly, open the Code Coverage window (go to **Window** > **Analysis** > **Code Coverage**). If you don't see the **Code Coverage** menu item, then Code Coverage did not install correctly.
|
||||
@@ -0,0 +1,201 @@
|
||||
# Quickstart - Code Coverage tutorial
|
||||
|
||||
The Quickstart guide will give you an insight into what Code Coverage is and how you can identify areas of your code that need more testing, even if you haven't written any automated tests. It takes about 30 minutes to complete.
|
||||
|
||||

|
||||
|
||||
## Tasks
|
||||
|
||||
1. [What is Code Coverage](#1-what-is-code-coverage-sub2-minsub) (2 min)
|
||||
2. [Install the Code Coverage package](#2-install-the-code-coverage-package-sub2-minsub) (2 min)
|
||||
3. [Install the Asteroids sample project](#3-install-the-asteroids-sample-project-sub1-minsub) (1 min)
|
||||
4. [Enable Code Coverage](#4-enable-code-coverage-sub1-minsub) (1 min)
|
||||
5. [Understanding the game code: Shoot() function](#5-understanding-the-game-code-shoot-function-sub4-minsub) (4 min)
|
||||
6. [Generate a Coverage report from PlayMode tests](#6-generate-a-coverage-report-from-playmode-tests-sub3-minsub) (3 min)
|
||||
7. [Add Weapon tests to improve coverage](#7-add-weapon-tests-to-improve-coverage-sub3-minsub) (3 min)
|
||||
8. [Add a test for the LaserController](#8-add-a-test-for-the-lasercontroller-sub4-minsub) (4 min)
|
||||
9. [Clear the coverage data](#9-clear-the-coverage-data-sub1-minsub) (1 min)
|
||||
10. [Generate a Coverage report using Coverage Recording](#10-generate-a-coverage-report-using-coverage-recording-sub4-minsub) (4 min)
|
||||
|
||||
**Note:** Estimated times are shown for each task to give you a better understanding of the time required. These times are rough guidelines - it is fine to take as much or as little time as needed.
|
||||
|
||||
## 1. What is Code Coverage <sub>(2 min)</sub>
|
||||
|
||||
[Code Coverage](https://en.wikipedia.org/wiki/Code_coverage) is a measure of how much of your code has been executed. It is normally associated with automated tests, but you can gather coverage data in Unity at any time when the Editor is running.
|
||||
|
||||
It is typically presented as a [report](HowToInterpretResults.md) that shows the percentage of the code that has been executed. For automated testing the report does not measure the quality of tests, only whether your code is executed by PlayMode and EditMode tests. It is especially useful to check that critical or high risk areas of your code are covered, because they should receive the most rigorous testing.
|
||||
|
||||
It is much easier to accidentally introduce bugs into code that is not covered by tests, because those bugs are not detected straight away by the tests and can instead cause problems later — such as after you have published your game or app.
|
||||
|
||||
Additionally, the Code Coverage package offers a [Coverage Recording](CoverageRecording.md) feature which allows capturing coverage data on demand, in case you do not have tests in your project or doing manual testing.
|
||||
|
||||
## 2. Install the Code Coverage package <sub>(2 min)</sub>
|
||||
**Note:** Skip this task if the package is already installed.
|
||||
|
||||
Use the [Unity Package Manager](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest) to find and install the **Code Coverage** package.
|
||||
|
||||

|
||||
|
||||
Alternatively, use the **Add (+)** dropdown and select **Add package from git URL...** or **Add package by name...** and type `com.unity.testtools.codecoverage`.
|
||||
|
||||

|
||||
|
||||
To verify that Code Coverage has been installed correctly, open the Code Coverage window (go to **Window** > **Analysis** > **Code Coverage**). If you don't see the **Code Coverage** menu item, then Code Coverage did not install correctly.
|
||||
|
||||
## 3. Install the Asteroids sample project <sub>(1 min)</sub>
|
||||
|
||||
1. In the [Unity Package Manager](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest) (**Window** > **Package Manager**) select the **Code Coverage** package, if not already selected.
|
||||
2. Find the **Samples** section in the package details (right hand side) and select **Import** next to **Code Coverage Tutorial**.<br/><br/>
|
||||

|
||||
|
||||
## 4. Enable Code Coverage <sub>(1 min)</sub>
|
||||
|
||||
To enable Code Coverage open the [Code Coverage window](CodeCoverageWindow.md) (go to **Window** > **Analysis** > **Code Coverage**) and select **Enable Code Coverage** if not already selected, to be able to generate Coverage data and reports.
|
||||
|
||||

|
||||
|
||||
**Note:** Enabling Code Coverage adds some overhead to the editor and can affect the performance.
|
||||
|
||||
## 5. Understanding the game code: Shoot() function <sub>(4 min)</sub>
|
||||
|
||||
1. Go to `Asteroids/Scenes` in Project View and open the **Asteroids** scene.<br/>
|
||||
This is located in `Assets/Samples/Code Coverage/<version>/Code Coverage Tutorial`.
|
||||
|
||||
2. Hit **Play** and play the game for a minute or two.<br/>
|
||||

|
||||
Use the arrow keys to move and the spacebar to shoot.
|
||||
|
||||
3. Exit PlayMode.
|
||||
|
||||
4. Open the `Scripts/Controllers/SpaceshipController.cs` script.
|
||||
|
||||
5. Study the **Shoot** function.
|
||||
```
|
||||
If Weapon is Basic, the Prefabs/Weapons/Projectile prefab is instantiated
|
||||
If Weapon is Laser, the Prefabs/Weapons/Laser prefab is instantiated
|
||||
```
|
||||
|
||||
## 6. Generate a Coverage report from PlayMode tests <sub>(3 min)</sub>
|
||||
|
||||
1. Open the [Code Coverage window](CodeCoverageWindow.md) (go to **Window** > **Analysis** > **Code Coverage**).<br/><br/>
|
||||

|
||||
|
||||
2. If you see this warning select **Switch to debug mode**.<br/>
|
||||

|
||||
[Code Optimization](https://docs.unity3d.com/2020.1/Documentation/Manual/ManagedCodeDebugging.html#CodeOptimizationMode) was introduced in Unity 2020.1; in _Release mode_ the code is optimized and therefore not directly represented by the original code. Therefore, _Debug mode_ is required in order to obtain accurate code coverage information.
|
||||
|
||||
3. Click the **Included Assemblies** dropdown to make sure only<br/>
|
||||
`Unity.TestTools.CodeCoverage.Sample.Asteroids` and<br/>
|
||||
`Unity.TestTools.CodeCoverage.Sample.Asteroids.Tests` are selected.<br/><br/>
|
||||

|
||||
|
||||
4. Make sure **HTML Report**, **Report History**, **Auto Generate Report** and **Auto Open Report** are all checked.
|
||||

|
||||
|
||||
5. Switch to the [Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html?subfolder=/manual/workflow-run-test.html) window, select the **PlayMode** tab and hit **Run All** tests.<br/><br/>
|
||||

|
||||
|
||||
6. When the tests finish running, a file viewer window will open up containing the coverage report. Select `index.htm`.
|
||||
|
||||
7. Look for the classes with low coverage, especially **LaserController**, **BaseProjectile** and **ProjectileController**.
|
||||
|
||||
You can sort the results by _Line coverage_.
|
||||
|
||||

|
||||
|
||||
See also [How to interpret the results](HowToInterpretResults.md).
|
||||
|
||||
## 7. Add Weapon tests to improve coverage <sub>(3 min)</sub>
|
||||
|
||||
1. Open the `Tests/WeaponTests.cs` script.
|
||||
|
||||
2. Uncomment all the tests (from _line 35_ down to _line 237_).
|
||||
|
||||
3. Back in the **Test Runner**, hit **Run All** tests again.
|
||||
|
||||
4. When the tests finish running, a file viewer window will open up containing the coverage report. Select `index.htm`.
|
||||
|
||||
5. Notice that now **BaseProjectile** and **ProjectileController** coverage is considerably higher, but **LaserController** has not improved much.
|
||||
|
||||

|
||||
|
||||
## 8. Add a test for the LaserController <sub>(4 min)</sub>
|
||||
|
||||
1. Open the `Tests/WeaponTests.cs` script.
|
||||
|
||||
2. Go to the **\_18\_LaserFiresSuccessfully** test in line 225.
|
||||
|
||||
3. Uncomment and study the code.
|
||||
|
||||
4. Back in the **Test Runner**, hit **Run All** tests again.
|
||||
|
||||
5. When the tests finish running, a file viewer window will open up containing the coverage report. Select `index.htm`.
|
||||
|
||||
6. Notice how the coverage for **LaserController** has improved.<br/>
|
||||

|
||||
|
||||
7. Select the **LaserController** class to enter the class view and notice that about 2/3 (65%) of the code is now covered (green).
|
||||
|
||||

|
||||
|
||||
Complete the [Bonus Task](#11-bonus-task-sub5-8-minsub) at the end of the tutorial to get 100% coverage!
|
||||
|
||||
## 9. Clear the coverage data <sub>(1 min)</sub>
|
||||
|
||||
1. Open the [Code Coverage window](CodeCoverageWindow.md) (go to **Window** > **Analysis** > **Code Coverage**).
|
||||
|
||||
2. Select **Clear Results** and confirm.
|
||||
|
||||
3. Select **Clear History** and confirm.
|
||||
|
||||
## 10. Generate a Coverage report using Coverage Recording <sub>(4 min)</sub>
|
||||
|
||||
1. Go to `Asteroids/Scenes` in Project View and open the **Asteroids** scene, if not opened already.
|
||||
|
||||
2. Open the [Code Coverage window](CodeCoverageWindow.md). Make sure **HTML Report**, **Report History**, **Auto Generate Report** and **Auto Open Report** all are checked.<br/>
|
||||

|
||||
|
||||
3. Select **Start Recording**.<br/>
|
||||

|
||||
|
||||
4. Hit **Play** to play the game and **exit** PlayMode before you get **8000** points.
|
||||

|
||||
|
||||
5. Select **Stop Recording**.<br/>
|
||||

|
||||
|
||||
6. A file viewer window will open up containing the coverage report. Select `index.htm`.
|
||||
|
||||
7. Notice that **LaserController** has 0% coverage.<br/>
|
||||

|
||||
|
||||
8. Go back to the **Code Coverage window**.
|
||||
|
||||
9. Select **Start Recording**.
|
||||
|
||||
10. Now hit **Play** to play the game again but this time **exit** PlayMode when you get **8000** points.
|
||||
|
||||
11. Select **Stop Recording**.
|
||||
|
||||
12. Notice that **LaserController** coverage is now 100%.<br/>
|
||||

|
||||
|
||||
See also [How to interpret the results](HowToInterpretResults.md).
|
||||
<br/><br/>
|
||||
|
||||
## 11. Bonus task <sub>(5-8 min)</sub>
|
||||
|
||||
Write a new test that checks that the laser gets destroyed after 2 seconds, which will also cover the rest of the code in **LaserController**.
|
||||
|
||||
**Suggested name:** _19_LaserFiresAndIsDestroyedAfterTwoSeconds.
|
||||
**Hint:** You can use `yield return new WaitForSeconds(2f);` to wait for 2 seconds.
|
||||
|
||||
<br/>
|
||||
|
||||
---
|
||||
|
||||
<br/>
|
||||
|
||||
### Well done for finishing the Code Coverage tutorial!
|
||||
|
||||
For questions and feedback please visit the [Testing & Automation](https://forum.unity.com/forums/testing-automation.211/) forum section to browse current conversations or start a new thread. Please use the **code coverage** tag.
|
||||
@@ -0,0 +1,41 @@
|
||||
* [About Code Coverage](index)
|
||||
* [What's new](whats-new.md)
|
||||
* [Upgrade guide](upgrade-guide.md)
|
||||
* [Code Coverage package](index#code-coverage-package)
|
||||
* [Coverage HTML Report](index#coverage-html-report)
|
||||
* [Other Reports](index#other-reports)
|
||||
* [Coverage Summary Badges](index#coverage-summary-badges)
|
||||
* [Quickstart](Quickstart)
|
||||
* [What is Code Coverage](Quickstart#1-what-is-code-coverage-sub2-minsub)
|
||||
* [Install the Code Coverage package](Quickstart#2-install-the-code-coverage-package-sub2-minsub)
|
||||
* [Install the Asteroids sample project](Quickstart#3-install-the-asteroids-sample-project-sub1-minsub)
|
||||
* [Enable Code Coverage](Quickstart#4-enable-code-coverage-sub1-minsub)
|
||||
* [Understanding the game code: Shoot() function](Quickstart.html#5-understanding-the-game-code-shoot-function-sub4-minsub)
|
||||
* [Generate a Coverage report from PlayMode tests](Quickstart#6-generate-a-coverage-report-from-playmode-tests-sub3-minsub)
|
||||
* [Add Weapon tests to improve coverage](Quickstart#7-add-weapon-tests-to-improve-coverage-sub3-minsub)
|
||||
* [Add a test for the LaserController](Quickstart#8-add-a-test-for-the-lasercontroller-sub4-minsub)
|
||||
* [Clear the coverage data](Quickstart#9-clear-the-coverage-data-sub1-minsub)
|
||||
* [Generate a Coverage report using Coverage Recording](Quickstart#10-generate-a-coverage-report-using-coverage-recording-sub4-minsub)
|
||||
* [Installing Code Coverage](InstallingCodeCoverage)
|
||||
* [From the Unity Package Manager](InstallingCodeCoverage#from-the-unity-package-manager)
|
||||
* [Manually from the Package Manifest](InstallingCodeCoverage#manually-from-the-package-manifest)
|
||||
* [Using Code Coverage](UsingCodeCoverage)
|
||||
* [Code Coverage window](CodeCoverageWindow)
|
||||
* [Using Code Coverage with Test Runner](CoverageTestRunner)
|
||||
* [On demand coverage recording](CoverageRecording)
|
||||
* [Using Code Coverage in batchmode](CoverageBatchmode)
|
||||
* [Using Code Coverage with Burst compiler](UsingCodeCoverage#using-code-coverage-with-burst-compiler)
|
||||
* [Using Code Coverage with Code Optimization](UsingCodeCoverage#using-code-coverage-with-code-optimization)
|
||||
* [Excluding code from Code Coverage](UsingCodeCoverage#excluding-code-from-code-coverage)
|
||||
* [Ignoring tests for Code Coverage](UsingCodeCoverage#ignoring-tests-for-code-coverage)
|
||||
* [Subscribing to Code Coverage session events](UsingCodeCoverage#subscribing-to-code-coverage-session-events)
|
||||
* [How to interpret the results](HowToInterpretResults)
|
||||
* [Summary View](HowToInterpretResults#summary-view)
|
||||
* [Class/Struct View](HowToInterpretResults#classstruct-view)
|
||||
* [Technical details](TechnicalDetails)
|
||||
* [How it works](TechnicalDetails#how-it-works)
|
||||
* [Requirements](TechnicalDetails#requirements)
|
||||
* [3rd party libraries used](TechnicalDetails#3rd-party-libraries-used)
|
||||
* [Known limitations](TechnicalDetails#known-limitations)
|
||||
* [Document revision history](DocumentRevisionHistory)
|
||||
* [Archive](DocumentArchive)
|
||||
@@ -0,0 +1,23 @@
|
||||
# Technical details
|
||||
|
||||
## How it works
|
||||
|
||||
The package is a client of the coverage API. For more information, see the [coverage API's documentation](https://docs.unity3d.com/ScriptReference/TestTools.Coverage.html). The package uses a combination of this API and C# reflection to output the test coverage data in the OpenCover format. Optionally, a third-party report generator will then parse the OpenCover data and generate a report (HTML, SonarQube, Cobertura, LCOV).
|
||||
|
||||
## Requirements
|
||||
|
||||
This version of the Code Coverage package is compatible with the following versions of the Unity Editor:
|
||||
|
||||
* 2019.3 and later
|
||||
|
||||
## Third-party libraries used
|
||||
|
||||
* [ReportGenerator](https://github.com/danielpalme/ReportGenerator) - v5.0.4
|
||||
|
||||
## Known limitations
|
||||
|
||||
Code Coverage includes the following known limitations:
|
||||
|
||||
* Code Coverage currently only supports the [OpenCover](https://github.com/OpenCover/opencover) format.
|
||||
* Code Coverage currently only supports code run in the Editor and not in Standalone/Player.
|
||||
* NPath Complexity calculation and Branch Coverage are not implemented at present so they will always appear as zero in the coverage report.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Using Code Coverage
|
||||
|
||||
## Using Code Coverage with Burst compiler
|
||||
|
||||
If you use the [Burst package](https://docs.unity3d.com/Packages/com.unity.burst@latest) and have jobs compiled with Burst, you will need to disable Burst compilation in order to get full coverage. To disable Burst compilation you can do **one** of the following:
|
||||
|
||||
- Uncheck **Enable Compilation** under **Jobs** > **Burst** > **Enable Compilation**.
|
||||
- Pass `--burst-disable-compilation` to the command line.
|
||||
|
||||
## Using Code Coverage with Code Optimization
|
||||
|
||||
Code Optimization was introduced in 2020.1. Code Optimization mode defines whether Unity Editor compiles scripts in Debug or Release mode. Debug mode enables C# debugging and it is required in order to obtain accurate code coverage. To ensure Code optimization is set to Debug mode you can do **one** of the following:
|
||||
|
||||
- Switch to Debug mode in the Editor (bottom right corner, select the **Bug icon** > **Switch to debug mode**).
|
||||
- Using the CompilationPipeline api, set `CompilationPipeline.codeOptimization = CodeOptimization.Debug`.
|
||||
- Pass `-debugCodeOptimization` to the command line.
|
||||
|
||||
## Excluding code from Code Coverage
|
||||
|
||||
Any code that should not be contributing to the Code Coverage calculation can be excluded by adding the [`ExcludeFromCoverage`](https://docs.unity3d.com/ScriptReference/TestTools.ExcludeFromCoverageAttribute.html) attribute. This attribute can be added to Assemblies, Classes, Constructors, Methods and Structs. Note that you can also use the .NET [`ExcludeFromCodeCoverage`](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.excludefromcodecoverageattribute?view=netcore-2.0) attribute.
|
||||
|
||||
## Ignoring tests for Code Coverage
|
||||
|
||||
To ignore tests when running with Code Coverage, use the [ConditionalIgnore](https://docs.unity3d.com/Packages/com.unity.test-framework@latest/index.html?subfolder=/manual/reference-attribute-conditionalignore.html) attribute, passing the `"IgnoreForCoverage"` ID.
|
||||
|
||||
#### Example
|
||||
```
|
||||
public class MyTestClass
|
||||
{
|
||||
[Test, ConditionalIgnore("IgnoreForCoverage", "This test is disabled when ran with code coverage")]
|
||||
public void TestNeverRunningWithCodeCoverage()
|
||||
{
|
||||
Assert.Pass();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Subscribing to Code Coverage session events
|
||||
|
||||
Use the [Events API](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@latest/index.html?subfolder=/api/UnityEditor.TestTools.CodeCoverage.Events.html) to subscribe to events invoked during a Code Coverage session.
|
||||
@@ -0,0 +1,37 @@
|
||||
apiRules:
|
||||
- exclude:
|
||||
# inherited Object methods
|
||||
uidRegex: ^System\.Object\..*$
|
||||
type: Method
|
||||
- exclude:
|
||||
# mentioning types from System.* namespace
|
||||
uidRegex: ^System\..*$
|
||||
type: Type
|
||||
- exclude:
|
||||
hasAttribute:
|
||||
uid: System.ObsoleteAttribute
|
||||
type: Member
|
||||
- exclude:
|
||||
hasAttribute:
|
||||
uid: System.ObsoleteAttribute
|
||||
type: Type
|
||||
- exclude:
|
||||
hasAttribute:
|
||||
uid: System.ComponentModel.EditorBrowsableAttribute
|
||||
ctorArguments:
|
||||
- System.ComponentModel.EditorBrowsableState.Never
|
||||
- exclude:
|
||||
uidRegex: ^OpenCover\.Framework\.Model
|
||||
type: namespace
|
||||
- exclude:
|
||||
uidRegex: ^Mono\.Reflection
|
||||
type: namespace
|
||||
- exclude:
|
||||
uidRegex: Unity.TestTools.CodeCoverage.Editor.Test*
|
||||
type: namespace
|
||||
- exclude:
|
||||
uidRegex: UnityEditor.TestTools.CodeCoverage.Tests
|
||||
type: namespace
|
||||
- exclude:
|
||||
uidRegex: ^Global Namespace*
|
||||
type: namespace
|
||||
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 145 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 946 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 139 KiB |
@@ -0,0 +1,39 @@
|
||||
# About Code Coverage
|
||||
|
||||
[Code Coverage](https://en.wikipedia.org/wiki/Code_coverage) is a measure of how much of your code has been executed. It is normally associated with automated tests, but you can gather coverage data in Unity at any time when the Editor is running.
|
||||
|
||||
It is typically presented as a [report](HowToInterpretResults.md) that shows the percentage of the code that has been executed. For automated testing the report does not measure the quality of tests, only whether your code is executed by `PlayMode` and `EditMode` tests. It is especially useful to check that critical or high risk areas of your code are covered, because they should receive the most rigorous testing.
|
||||
|
||||
## Code Coverage package
|
||||
|
||||
Use the Code Coverage package with the [Test Runner](CoverageTestRunner.md) to gather and present test coverage information. When you run your tests with code coverage enabled you can see exactly which lines of your code are executed when the tests run in addition to whether the tests passed or failed. See [Using Code Coverage with Test Runner](CoverageTestRunner.md).
|
||||
|
||||
Once a test run has completed, the Code Coverage package will generate an [HTML coverage report](HowToInterpretResults.md) showing which lines of your code are covered by tests. Code Coverage currently supports **PlayMode** and **EditMode** tests. It also allows you to track the code coverage changes through time.
|
||||
|
||||
Additionally, the Code Coverage package offers a [Coverage Recording](CoverageRecording.md) feature which allows capturing coverage data on demand, in case you do not have tests in your project or doing manual testing.
|
||||
|
||||
The [Quickstart](Quickstart.md) guide will give you an insight into the package.
|
||||
|
||||
## Coverage HTML report
|
||||
|
||||
Shown below is an example of the top level page of an HTML report generated by the package.
|
||||
|
||||

|
||||
|
||||
### Class view
|
||||
|
||||
This view shows some brief statistics for the selected class as well as the C# source code. Each line will be colored either green or red depending on whether the line was covered or not.
|
||||
|
||||

|
||||
|
||||
For more information see [How to interpret the results](HowToInterpretResults.md).
|
||||
|
||||
## Other reports
|
||||
|
||||
The package can produce [SonarQube](https://docs.sonarqube.org/latest/analysis/generic-test), [Cobertura](https://cobertura.github.io/cobertura) and [LCOV](https://github.com/linux-test-project/lcov) reports.
|
||||
|
||||
## Coverage summary badges
|
||||
|
||||
Additionally, the package can produce simple badges in SVG and PNG format, showing the current percentage of code that is covered.
|
||||
|
||||

|
||||
@@ -0,0 +1,22 @@
|
||||
# Upgrading to Code Coverage package version 1.2
|
||||
|
||||
To upgrade to Code Coverage package version 1.2, you need to do the following:
|
||||
- [Update assembly filtering aliases in batchmode](upgrade-guide.md#update-assembly-filtering-aliases-in-batchmode)
|
||||
- [Rename `pathStrippingPatterns` to `pathReplacePatterns` in batchmode](upgrade-guide.md#rename-pathstrippingpatterns-to-pathreplacepatterns-in-batchmode)
|
||||
|
||||
**Note**: If you're upgrading from a version older than 1.1, follow the upgrade guide for version 1.1 first.
|
||||
|
||||
## Update assembly filtering aliases in batchmode
|
||||
- Rename assembly filtering aliases when running in [batchmode](CoverageBatchmode.md). `<user>` alias was renamed to `<assets>` and `<project>` was renamed to `<all>`.
|
||||
|
||||
## Rename `pathStrippingPatterns` to `pathReplacePatterns` in batchmode
|
||||
- Rename `pathStrippingPatterns` to `pathReplacePatterns` in [batchmode](CoverageBatchmode.md).<br/><br/>**Example:**<br/><br/>Change `pathStrippingPatterns:C:/MyProject/` to `pathReplacePatterns:C:/MyProject/,`.<br/>This is equivalent to stripping `C:/MyProject/` by replacing `C:/MyProject/` with an empty string.
|
||||
|
||||
# Upgrading to Code Coverage package version 1.1
|
||||
To upgrade to Code Coverage package version 1.1, you need to do the following:
|
||||
- [Update path filtering globbing rules](upgrade-guide.md#update-path-filtering-globbing-rules)
|
||||
|
||||
## Update path filtering globbing rules
|
||||
- Update the path filtering globbing rules in your batchmode commands and code coverage window. To keep the current behavior when using [globbing](https://en.wikipedia.org/wiki/Glob_%28programming%29) to match any number of folders, the `*` character should be replaced with `**`. A single `*` character can be used to specify a single folder layer.<br/><br/>**Examples:**<br/><br/>`pathFilters:+C:/MyProject/Assets/Scripts/*` will include all files in the `C:/MyProject/Assets/Scripts` folder. Files in subfolders will not be included.<br/>`pathFilters:+C:/MyProject/Assets/Scripts/**` will include all files under the `C:/MyProject/Assets/Scripts` folder and any of its subfolders.
|
||||
|
||||
For a full list of changes and updates in this version, see the [Code Coverage package changelog](../changelog/CHANGELOG.html).
|
||||
@@ -0,0 +1,31 @@
|
||||
# What's new in version 1.2
|
||||
|
||||
Summary of changes in Code Coverage package version 1.2
|
||||
|
||||
The main updates in this release include:
|
||||
|
||||
## Added
|
||||
|
||||
- Added `Pause Recording` and `Resume Recording` buttons in the toolbar in the [Code Coverage window](CodeCoverageWindow.md).
|
||||
- Added `Test Runner References` coverage report option in the [Code Coverage window](CodeCoverageWindow.md). When you check this option, the generated coverage results include references to the triggering tests enabling the [Coverage by test methods](HowToInterpretResults.md#coverage-by-test-methods) section in the HTML report. This section allows you to see how each test contributes to the overall coverage. In [batchmode](CoverageBatchmode.md), you can generate test references by adding the `generateTestReferences` option in *-coverageOptions*.
|
||||
- Added `Log Verbosity Level` setting in the [Code Coverage window](CodeCoverageWindow.md) which allows setting the verbosity level for the editor and console logs.
|
||||
- Added `Additional Reports` option in the [Code Coverage window](CodeCoverageWindow.md) which if checked [SonarQube](https://docs.sonarqube.org/latest/analysis/generic-test), [Cobertura](https://cobertura.github.io/cobertura) and [LCOV](https://github.com/linux-test-project/lcov) reports will be generated. Added `generateAdditionalReports` in *-coverageOptions* for [batchmode](CoverageBatchmode.md).
|
||||
- Added `filtersFromFile` in *-coverageOptions* for [batchmode](CoverageBatchmode.md). This allows you to specify an external Json file which contains path and assembly filtering rules.
|
||||
- Added `dontClear` in *-coverageOptions* for [batchmode](https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.2/manual/CoverageBatchmode.html) which allows coverage results to be accumulated after every code coverage session. If not passed the results are cleared before a new session.
|
||||
|
||||
## Updated
|
||||
|
||||
- Updated the UI of the [Code Coverage window](CodeCoverageWindow.md) moving the action buttons into a toolbar at the top.
|
||||

|
||||
- Introduced new selection buttons under the *Included Assemblies* dropdown in the [Code Coverage window](CodeCoverageWindow.md).
|
||||
- Renamed *assemblyFilters* aliases in [batchmode](CoverageBatchmode.md); `<user>` was renamed to `<assets>` and `<project>` was renamed to `<all>`.
|
||||
- Replaced `pathStrippingPatterns` with `pathReplacePatterns` in [batchmode](CoverageBatchmode.md). The `pathReplacePatterns` option allows stripping and replacing specific sections from the paths that are stored in the coverage results xml files.
|
||||
- The size of the coverage result files and the Code Coverage session duration have been optimized.
|
||||
- Improved the editor and console logs.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Ensure assemblies are removed from the Included Assemblies field if they no longer exist (case [1318668](https://issuetracker.unity3d.com/issues/code-coverage-the-included-assemblies-field-shows-assemblies-that-no-longer-exist)).
|
||||
- Ensure hidden sequence points are ignored (case [1372305](https://issuetracker.unity3d.com/issues/class-which-derives-from-methodbase-causes-incorrect-sequence-points-to-be-generated-by-coverage-api)).
|
||||
|
||||
For a full list of changes and updates in this version, see the [Code Coverage package changelog](../changelog/CHANGELOG.html).
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f60cdb876f3cce043b7f2d9d08583e92
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b5c29f7e37f22e4c8d285687af72aa3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,228 @@
|
||||
// #define COVERAGE_ANALYTICS_LOGGING
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.TestTools.CodeCoverage.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Analytics;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage.Analytics
|
||||
{
|
||||
[Serializable]
|
||||
internal class Timer
|
||||
{
|
||||
public void Start()
|
||||
{
|
||||
startTime = DateTime.Now;
|
||||
}
|
||||
|
||||
public long elapsedTimeMs => (long)(DateTime.Now - startTime).TotalMilliseconds;
|
||||
|
||||
[SerializeField]
|
||||
private DateTime startTime = DateTime.Now;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class CoverageAnalytics : ScriptableSingleton<CoverageAnalytics>
|
||||
{
|
||||
[SerializeField]
|
||||
private bool s_Registered;
|
||||
[SerializeField]
|
||||
private List<int> s_ResultsIdsList;
|
||||
|
||||
public CoverageAnalyticsEvent CurrentCoverageEvent;
|
||||
public Timer CoverageTimer;
|
||||
|
||||
protected CoverageAnalytics() : base()
|
||||
{
|
||||
ResetEvents();
|
||||
}
|
||||
|
||||
public void ResetEvents()
|
||||
{
|
||||
CurrentCoverageEvent = new CoverageAnalyticsEvent();
|
||||
CoverageTimer = new Timer();
|
||||
s_ResultsIdsList = new List<int>();
|
||||
|
||||
CurrentCoverageEvent.actionID = ActionID.Other;
|
||||
CurrentCoverageEvent.coverageModeId = CoverageModeID.None;
|
||||
CurrentCoverageEvent.numOfIncludedPaths = 0;
|
||||
CurrentCoverageEvent.numOfExcludedPaths = 0;
|
||||
}
|
||||
|
||||
public void StartTimer()
|
||||
{
|
||||
CoverageTimer.Start();
|
||||
}
|
||||
|
||||
// See ResultsLogger.cs for details
|
||||
public void AddResult(ResultID resultId)
|
||||
{
|
||||
s_ResultsIdsList.Add((int)resultId);
|
||||
}
|
||||
|
||||
public void SendCoverageEvent(bool success)
|
||||
{
|
||||
CurrentCoverageEvent.success = success;
|
||||
CurrentCoverageEvent.duration = CoverageTimer.elapsedTimeMs;
|
||||
CurrentCoverageEvent.resultIds = s_ResultsIdsList.ToArray();
|
||||
|
||||
bool runFromCommandLine = CommandLineManager.instance.runFromCommandLine;
|
||||
bool batchmode = CommandLineManager.instance.batchmode;
|
||||
bool useProjectSettings = CommandLineManager.instance.useProjectSettings;
|
||||
|
||||
CurrentCoverageEvent.runFromCommandLine = runFromCommandLine;
|
||||
CurrentCoverageEvent.batchmode = batchmode;
|
||||
CurrentCoverageEvent.useProjectSettings = useProjectSettings;
|
||||
|
||||
if (batchmode && !useProjectSettings)
|
||||
{
|
||||
CurrentCoverageEvent.autogenerate = CommandLineManager.instance.generateBadgeReport || CommandLineManager.instance.generateHTMLReport || CommandLineManager.instance.generateAdditionalReports;
|
||||
CurrentCoverageEvent.createBadges = CommandLineManager.instance.generateBadgeReport;
|
||||
CurrentCoverageEvent.generateHistory = CommandLineManager.instance.generateHTMLReportHistory;
|
||||
CurrentCoverageEvent.generateHTMLReport = CommandLineManager.instance.generateHTMLReport;
|
||||
CurrentCoverageEvent.generateMetrics = CommandLineManager.instance.generateAdditionalMetrics;
|
||||
CurrentCoverageEvent.generateTestReferences = CommandLineManager.instance.generateTestReferences;
|
||||
CurrentCoverageEvent.generateAdditionalReports = CommandLineManager.instance.generateAdditionalReports;
|
||||
CurrentCoverageEvent.dontClear = CommandLineManager.instance.dontClear;
|
||||
CurrentCoverageEvent.useDefaultAssemblyFilters = !CommandLineManager.instance.assemblyFiltersSpecified;
|
||||
CurrentCoverageEvent.useDefaultPathFilters = !CommandLineManager.instance.pathFiltersSpecified;
|
||||
CurrentCoverageEvent.useDefaultResultsLoc = CommandLineManager.instance.coverageResultsPath.Length == 0;
|
||||
CurrentCoverageEvent.useDefaultHistoryLoc = CommandLineManager.instance.coverageHistoryPath.Length == 0;
|
||||
CurrentCoverageEvent.usePathReplacePatterns = CommandLineManager.instance.pathReplacingSpecified;
|
||||
CurrentCoverageEvent.useSourcePaths = CommandLineManager.instance.sourcePathsSpecified;
|
||||
CurrentCoverageEvent.usePathFiltersFromFile = CommandLineManager.instance.pathFiltersFromFileSpecified;
|
||||
CurrentCoverageEvent.useAssemblyFiltersFromFile = CommandLineManager.instance.assemblyFiltersFromFileSpecified;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentCoverageEvent.autogenerate = CommandLineManager.instance.generateBadgeReport || CommandLineManager.instance.generateHTMLReport || CommandLineManager.instance.generateAdditionalReports || CoveragePreferences.instance.GetBool("AutoGenerateReport", true);
|
||||
CurrentCoverageEvent.autoOpenReport = CoveragePreferences.instance.GetBool("OpenReportWhenGenerated", true);
|
||||
CurrentCoverageEvent.createBadges = CommandLineManager.instance.generateBadgeReport || CoveragePreferences.instance.GetBool("GenerateBadge", true);
|
||||
CurrentCoverageEvent.generateHistory = CommandLineManager.instance.generateHTMLReportHistory || CoveragePreferences.instance.GetBool("IncludeHistoryInReport", true);
|
||||
CurrentCoverageEvent.generateHTMLReport = CommandLineManager.instance.generateHTMLReport || CoveragePreferences.instance.GetBool("GenerateHTMLReport", true);
|
||||
CurrentCoverageEvent.generateMetrics = CommandLineManager.instance.generateAdditionalMetrics || CoveragePreferences.instance.GetBool("GenerateAdditionalMetrics", false);
|
||||
CurrentCoverageEvent.generateTestReferences = CommandLineManager.instance.generateTestReferences || CoveragePreferences.instance.GetBool("GenerateTestReferences", false);
|
||||
CurrentCoverageEvent.generateAdditionalReports = CommandLineManager.instance.generateAdditionalReports || CoveragePreferences.instance.GetBool("GenerateAdditionalReports", false);
|
||||
CurrentCoverageEvent.dontClear = CommandLineManager.instance.dontClear;
|
||||
CurrentCoverageEvent.usePathReplacePatterns = CommandLineManager.instance.pathReplacingSpecified;
|
||||
CurrentCoverageEvent.useSourcePaths = CommandLineManager.instance.sourcePathsSpecified;
|
||||
CurrentCoverageEvent.usePathFiltersFromFile = CommandLineManager.instance.pathFiltersFromFileSpecified;
|
||||
CurrentCoverageEvent.useAssemblyFiltersFromFile = CommandLineManager.instance.assemblyFiltersFromFileSpecified;
|
||||
|
||||
|
||||
CurrentCoverageEvent.useDefaultAssemblyFilters = !CommandLineManager.instance.assemblyFiltersSpecified;
|
||||
if (!CommandLineManager.instance.assemblyFiltersSpecified)
|
||||
CurrentCoverageEvent.useDefaultAssemblyFilters = string.Equals(CoveragePreferences.instance.GetString("IncludeAssemblies", AssemblyFiltering.GetUserOnlyAssembliesString()), AssemblyFiltering.GetUserOnlyAssembliesString(), StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
CurrentCoverageEvent.useDefaultPathFilters = !CommandLineManager.instance.pathFiltersSpecified;
|
||||
if (!CommandLineManager.instance.pathFiltersSpecified)
|
||||
CurrentCoverageEvent.useDefaultPathFilters = string.Equals(CoveragePreferences.instance.GetString("PathsToInclude", string.Empty), string.Empty) && string.Equals(CoveragePreferences.instance.GetString("PathsToExclude", string.Empty), string.Empty);
|
||||
|
||||
CurrentCoverageEvent.useDefaultResultsLoc = CommandLineManager.instance.coverageResultsPath.Length == 0;
|
||||
if (CommandLineManager.instance.coverageResultsPath.Length == 0)
|
||||
CurrentCoverageEvent.useDefaultResultsLoc = string.Equals(CoveragePreferences.instance.GetStringForPaths("Path", string.Empty), CoverageUtils.GetProjectPath(), StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
CurrentCoverageEvent.useDefaultHistoryLoc = CommandLineManager.instance.coverageHistoryPath.Length == 0;
|
||||
if (CommandLineManager.instance.coverageHistoryPath.Length == 0)
|
||||
CurrentCoverageEvent.useDefaultHistoryLoc = string.Equals(CoveragePreferences.instance.GetStringForPaths("HistoryPath", string.Empty), CoverageUtils.GetProjectPath(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
CurrentCoverageEvent.inDebugMode = Compilation.CompilationPipeline.codeOptimization == Compilation.CodeOptimization.Debug;
|
||||
#else
|
||||
CurrentCoverageEvent.inDebugMode = true;
|
||||
#endif
|
||||
if (!runFromCommandLine || (runFromCommandLine && !batchmode && !CommandLineManager.instance.assemblyFiltersSpecified))
|
||||
{
|
||||
if (CurrentCoverageEvent.actionID == ActionID.ReportOnly)
|
||||
{
|
||||
string includeAssemblies = CoveragePreferences.instance.GetString("IncludeAssemblies", AssemblyFiltering.GetUserOnlyAssembliesString());
|
||||
string[] includeAssembliesArray = includeAssemblies.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
CurrentCoverageEvent.includedAssemblies = includeAssembliesArray;
|
||||
}
|
||||
}
|
||||
|
||||
Send(EventName.codeCoverage, CurrentCoverageEvent);
|
||||
|
||||
ResetEvents();
|
||||
}
|
||||
|
||||
public bool RegisterEvents()
|
||||
{
|
||||
if (!EditorAnalytics.enabled)
|
||||
{
|
||||
ResultsLogger.LogSessionItem("Editor analytics are disabled", LogVerbosityLevel.Info);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s_Registered)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var allNames = Enum.GetNames(typeof(EventName));
|
||||
if (allNames.Any(eventName => !RegisterEvent(eventName)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
s_Registered = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool RegisterEvent(string eventName)
|
||||
{
|
||||
const string vendorKey = "unity.testtools.codecoverage";
|
||||
var result = EditorAnalytics.RegisterEventWithLimit(eventName, 100, 1000, vendorKey);
|
||||
switch (result)
|
||||
{
|
||||
case AnalyticsResult.Ok:
|
||||
{
|
||||
#if COVERAGE_ANALYTICS_LOGGING
|
||||
ResultsLogger.LogSessionItem($"Registered analytics event: {eventName}", LogVerbosityLevel.Info);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
case AnalyticsResult.TooManyRequests:
|
||||
// this is fine - event registration survives domain reload (native)
|
||||
return true;
|
||||
default:
|
||||
{
|
||||
ResultsLogger.LogSessionItem($"Failed to register analytics event {eventName}. Result: {result}", LogVerbosityLevel.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Send(EventName eventName, object eventData)
|
||||
{
|
||||
if (!RegisterEvents())
|
||||
{
|
||||
#if COVERAGE_ANALYTICS_LOGGING
|
||||
Console.WriteLine($"[{CoverageSettings.PackageName}] Analytics disabled: event='{eventName}', time='{DateTime.Now:HH:mm:ss}', payload={EditorJsonUtility.ToJson(eventData, true)}");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var result = EditorAnalytics.SendEventWithLimit(eventName.ToString(), eventData);
|
||||
if (result == AnalyticsResult.Ok)
|
||||
{
|
||||
#if COVERAGE_ANALYTICS_LOGGING
|
||||
ResultsLogger.LogSessionItem($"Event={eventName}, time={DateTime.Now:HH:mm:ss}, payload={EditorJsonUtility.ToJson(eventData, true)}", LogVerbosityLevel.Info);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ResultsLogger.LogSessionItem($"Failed to send analytics event {eventName}. Result: {result}", LogVerbosityLevel.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 712896fdadbc6744585b09d9e159c025
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace UnityEditor.TestTools.CodeCoverage.Analytics
|
||||
{
|
||||
internal enum EventName
|
||||
{
|
||||
codeCoverage
|
||||
}
|
||||
|
||||
internal enum ActionID
|
||||
{
|
||||
Other = 0,
|
||||
DataOnly = 1,
|
||||
ReportOnly = 2,
|
||||
DataReport = 3
|
||||
}
|
||||
|
||||
internal enum CoverageModeID
|
||||
{
|
||||
None = 0,
|
||||
TestRunner = 1,
|
||||
Recording = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9bb904d2fa36b040bfc7c599e54c407
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage.Analytics
|
||||
{
|
||||
[Serializable]
|
||||
internal class CoverageAnalyticsEvent
|
||||
{
|
||||
// The action performed on the event (batchmode compatible)
|
||||
public ActionID actionID;
|
||||
// Array of resultsIds (batchmode compatible)
|
||||
public int[] resultIds;
|
||||
// The coverage mode that was performed on successful action (batchmode compatible)
|
||||
public CoverageModeID coverageModeId;
|
||||
// Duration (in ms) for which the Coverage session lasted (batchmode compatible)
|
||||
public long duration;
|
||||
// Was the coverage session result a success (batchmode compatible)
|
||||
public bool success;
|
||||
// Did the user run the editor from the command line
|
||||
public bool runFromCommandLine;
|
||||
// Did the user run the editor in batch mode
|
||||
public bool batchmode;
|
||||
// Did the user pass the useProjectSettings option in batch mode (batchmode only)
|
||||
public bool useProjectSettings;
|
||||
// Did the user have Generate HTML Report selected (batchmode compatible)
|
||||
public bool generateHTMLReport;
|
||||
// Did the user have Generate History selected (batchmode compatible)
|
||||
public bool generateHistory;
|
||||
// Did the user have Generate Badges selected (batchmode compatible)
|
||||
public bool createBadges;
|
||||
// Did the user have Generate Additional Metrics selected (batchmode compatible)
|
||||
public bool generateMetrics;
|
||||
// Did the user have Generate Test Runner References selected (batchmode compatible)
|
||||
public bool generateTestReferences;
|
||||
// Did the user have Generate Additional reports selected (batchmode compatible)
|
||||
public bool generateAdditionalReports;
|
||||
// Did the user have passed the dontClear coverage option (batchmode compatible)
|
||||
public bool dontClear;
|
||||
// Did the user have Auto Generate Report selected (batchmode compatible)
|
||||
public bool autogenerate;
|
||||
// Did the user have Auto Open Report selected
|
||||
public bool autoOpenReport;
|
||||
// Did the user select the Clear Data button
|
||||
public bool clearData;
|
||||
// Did the user select the Clear History button
|
||||
public bool clearHistory;
|
||||
// Did the user select the Generate From Last button
|
||||
public bool generateFromLast;
|
||||
// Did the user switch to Debug mode (Code Optimization) in the Coverage window
|
||||
public bool switchToDebugMode;
|
||||
// Is the editor in Code Optimization: Debug mode (batchmode compatible)
|
||||
public bool inDebugMode;
|
||||
// Did the user disable Burst Compilation in the Coverage window
|
||||
public bool switchBurstOff;
|
||||
// Did the user select a new Results location or uses the default one (batchmode compatible)
|
||||
public bool useDefaultResultsLoc;
|
||||
// Did the user select a new History location or uses the default one (batchmode compatible)
|
||||
public bool useDefaultHistoryLoc;
|
||||
// Did the user specify different assemblies from the default ones (batchmode compatible)
|
||||
public bool useDefaultAssemblyFilters;
|
||||
// Did the user specify different paths filtering from the default one (batchmode compatible)
|
||||
public bool useDefaultPathFilters;
|
||||
// Did the user enter the Selected Assemblies dialog/dropdown
|
||||
public bool enterAssembliesDialog;
|
||||
// Did the user update any assemblies via the Selected Assemblies dialog/dropdown
|
||||
public bool updateAssembliesDialog;
|
||||
// Did the user update Included Paths
|
||||
public bool updateIncludedPaths;
|
||||
// Did the user select Add Folder for Included Paths
|
||||
public bool selectAddFolder_IncludedPaths;
|
||||
// Did the user select Add File for Included Paths
|
||||
public bool selectAddFile_IncludedPaths;
|
||||
// How many paths are included (batchmode compatible)
|
||||
public int numOfIncludedPaths;
|
||||
// Did the user update Excluded Paths
|
||||
public bool updateExcludedPaths;
|
||||
// Did the user select Add Folder for Excluded Paths
|
||||
public bool selectAddFolder_ExcludedPaths;
|
||||
// Did the user select Add File for Excluded Paths
|
||||
public bool selectAddFile_ExcludedPaths;
|
||||
// How many paths are excluded (batchmode compatible)
|
||||
public int numOfExcludedPaths;
|
||||
// Did the user use the Coverage API to StartRecording (batchmode compatible)
|
||||
public bool useAPI_StartRec;
|
||||
// Did the user use the Coverage API to StopRecording (batchmode compatible)
|
||||
public bool useAPI_StopRec;
|
||||
// Did the user use the Coverage API to PauseRecording (batchmode compatible)
|
||||
public bool useAPI_PauseRec;
|
||||
// Did the user use the Coverage API to UnpauseRecording (batchmode compatible)
|
||||
public bool useAPI_UnpauseRec;
|
||||
// Array of individual included assembly names (batchmode compatible)
|
||||
public string[] includedAssemblies;
|
||||
// Array of individual excluded assembly names (batchmode only)
|
||||
public string[] excludedAssemblies;
|
||||
// Did the user use the onCoverageSessionStarted event (batchmode compatible)
|
||||
public bool useEvent_onCoverageSessionStarted;
|
||||
// Did the user use the onCoverageSessionFinished event (batchmode compatible)
|
||||
public bool useEvent_onCoverageSessionFinished;
|
||||
// Did the user use the onCoverageSessionPaused event (batchmode compatible)
|
||||
public bool useEvent_onCoverageSessionPaused;
|
||||
// Did the user use the onCoverageSessionUnpaused event (batchmode compatible)
|
||||
public bool useEvent_onCoverageSessionUnpaused;
|
||||
// Did the user specify path replace patterns (command line only)
|
||||
public bool usePathReplacePatterns;
|
||||
// Did the user specify source paths (command line only)
|
||||
public bool useSourcePaths;
|
||||
// Did the user specify path filters from file option (command line only)
|
||||
public bool usePathFiltersFromFile;
|
||||
// Did the user specify assembly filters from file option (command line only)
|
||||
public bool useAssemblyFiltersFromFile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ab5c92c8c1059a4e92378da3696821e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Unity.TestTools.CodeCoverage.Editor.Tests")]
|
||||
[assembly: InternalsVisibleTo("Unity.TestTools.CodeCoverage.Editor.Tests.Performance")]
|
||||
[assembly: InternalsVisibleTo("Unity.TestTools.CodeCoverage.Editor.CoverageStatsSerializer")]
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5f6a9c343f474407aa9c6096dea2d0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "Unity.TestTools.CodeCoverage.Editor",
|
||||
"rootNamespace": "UnityEditor.TestTools.CodeCoverage",
|
||||
"references": [
|
||||
"GUID:27619889b8ba8c24980f49ee34dbb44a",
|
||||
"GUID:0acc523941302664db1f4e527237feb3",
|
||||
"GUID:19c3df1967929405fba735480b3da9a7",
|
||||
"GUID:eecdf9bdfcb2949619db458f3e24c5e2",
|
||||
"GUID:49818357e697641afb75d2f8acaf1861"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll",
|
||||
"ReportGeneratorMerged.dll"
|
||||
],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"UNITY_2019_2_OR_NEWER"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.test-framework",
|
||||
"expression": "1.0.16",
|
||||
"define": "CONDITIONAL_IGNORE_SUPPORTED"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.burst",
|
||||
"expression": "1.1.1",
|
||||
"define": "BURST_INSTALLED"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.test-framework",
|
||||
"expression": "1.1.18",
|
||||
"define": "TEST_FRAMEWORK_1_1_18_OR_NEWER"
|
||||
},
|
||||
{
|
||||
"name": "Unity",
|
||||
"expression": "2021.1.0b10",
|
||||
"define": "NO_COV_EDITORPREF"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.test-framework",
|
||||
"expression": "1.3.0",
|
||||
"define": "TEST_FRAMEWORK_1_3_OR_NEWER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.test-framework",
|
||||
"expression": "2.0.0",
|
||||
"define": "TEST_FRAMEWORK_2_0_OR_NEWER"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37180d43aa4b85c4b9076e2ef48a3b2a
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,196 @@
|
||||
using UnityEditor.TestTools.CodeCoverage.Analytics;
|
||||
using UnityEditor.TestTools.CodeCoverage.Utils;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class for the CodeCoverage API.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// The following example loads a scene, starts coverage recording, initializes a number of instances of a prefab, then pauses the recording to load another scene, unpauses the recording, initializes a number of instances of a different prefab and finally stops the recording.
|
||||
/// It also sets the verbosity level to Verbose, so all logs are printed to the editor log.
|
||||
/// <code>
|
||||
/// using UnityEngine;
|
||||
/// using UnityEditor;
|
||||
/// using UnityEditor.TestTools.CodeCoverage;
|
||||
/// using UnityEditor.SceneManagement;
|
||||
///
|
||||
/// public class CoverageApiTest : MonoBehaviour
|
||||
/// {
|
||||
/// [MenuItem("CodeCoverage/Run Recording")]
|
||||
/// static void RunRecording()
|
||||
/// {
|
||||
/// CodeCoverage.VerbosityLevel = LogVerbosityLevel.Verbose;
|
||||
///
|
||||
/// int i;
|
||||
///
|
||||
/// EditorSceneManager.OpenScene("Assets/Scenes/Scene1.unity");
|
||||
///
|
||||
/// CodeCoverage.StartRecording();
|
||||
///
|
||||
/// for (i = 0; i < 1000; ++i)
|
||||
/// {
|
||||
/// Instantiate(Resources.Load("ComplexPrefab1"));
|
||||
/// }
|
||||
///
|
||||
/// CodeCoverage.PauseRecording();
|
||||
///
|
||||
/// EditorSceneManager.OpenScene("Assets/Scenes/Scene2.unity");
|
||||
///
|
||||
/// CodeCoverage.UnpauseRecording();
|
||||
///
|
||||
/// for (i = 0; i < 1000; ++i)
|
||||
/// {
|
||||
/// Instantiate(Resources.Load("ComplexPrefab2"));
|
||||
/// }
|
||||
///
|
||||
/// CodeCoverage.StopRecording();
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static class CodeCoverage
|
||||
{
|
||||
private static CoverageReporterManager s_CoverageReporterManager;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the verbosity level used in editor and console logs. The default level is <see cref="LogVerbosityLevel.Info"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The verbosity level used in editor and console logs.
|
||||
/// </value>
|
||||
public static LogVerbosityLevel VerbosityLevel
|
||||
{
|
||||
set
|
||||
{
|
||||
ResultsLogger.VerbosityLevel = value;
|
||||
}
|
||||
|
||||
get
|
||||
{
|
||||
return ResultsLogger.VerbosityLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to start a new coverage recording session.
|
||||
/// </summary>
|
||||
public static void StartRecording()
|
||||
{
|
||||
CoverageAnalytics.instance.CurrentCoverageEvent.useAPI_StartRec = true;
|
||||
|
||||
StartRecordingInternal();
|
||||
}
|
||||
|
||||
internal static void StartRecordingInternal()
|
||||
{
|
||||
bool isRunning = CoverageRunData.instance.isRunning;
|
||||
|
||||
if (!isRunning)
|
||||
{
|
||||
Coverage.ResetAll();
|
||||
|
||||
CoverageRunData.instance.StartRecording();
|
||||
|
||||
if (s_CoverageReporterManager == null)
|
||||
s_CoverageReporterManager = CoverageReporterStarter.CoverageReporterManager;
|
||||
s_CoverageReporterManager.CreateCoverageReporter();
|
||||
|
||||
ICoverageReporter coverageReporter = s_CoverageReporterManager.CoverageReporter;
|
||||
if (coverageReporter != null)
|
||||
coverageReporter.OnRunStarted(null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to pause the recording on the current coverage recording session.
|
||||
/// </summary>
|
||||
public static void PauseRecording()
|
||||
{
|
||||
CoverageAnalytics.instance.CurrentCoverageEvent.useAPI_PauseRec = true;
|
||||
|
||||
PauseRecordingInternal();
|
||||
}
|
||||
|
||||
internal static void PauseRecordingInternal()
|
||||
{
|
||||
bool isRunning = CoverageRunData.instance.isRunning;
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
if (CoverageRunData.instance.isRecording && !CoverageRunData.instance.isRecordingPaused)
|
||||
{
|
||||
if (s_CoverageReporterManager == null)
|
||||
s_CoverageReporterManager = CoverageReporterStarter.CoverageReporterManager;
|
||||
|
||||
ICoverageReporter coverageReporter = s_CoverageReporterManager.CoverageReporter;
|
||||
if (coverageReporter != null)
|
||||
coverageReporter.OnCoverageRecordingPaused();
|
||||
|
||||
CoverageRunData.instance.PauseRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to continue recording on the current coverage recording session, after having paused the recording.
|
||||
/// </summary>
|
||||
public static void UnpauseRecording()
|
||||
{
|
||||
CoverageAnalytics.instance.CurrentCoverageEvent.useAPI_UnpauseRec = true;
|
||||
|
||||
UnpauseRecordingInternal();
|
||||
}
|
||||
|
||||
internal static void UnpauseRecordingInternal()
|
||||
{
|
||||
bool isRunning = CoverageRunData.instance.isRunning;
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
if (CoverageRunData.instance.isRecording && CoverageRunData.instance.isRecordingPaused)
|
||||
{
|
||||
Coverage.ResetAll();
|
||||
|
||||
CoverageRunData.instance.UnpauseRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to end the current coverage recording session.
|
||||
/// </summary>
|
||||
public static void StopRecording()
|
||||
{
|
||||
CoverageAnalytics.instance.CurrentCoverageEvent.useAPI_StopRec = true;
|
||||
|
||||
StopRecordingInternal();
|
||||
}
|
||||
|
||||
internal static void StopRecordingInternal()
|
||||
{
|
||||
bool isRunning = CoverageRunData.instance.isRunning;
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
if (CoverageRunData.instance.isRecording)
|
||||
{
|
||||
if (CoverageRunData.instance.isRecordingPaused)
|
||||
Coverage.ResetAll();
|
||||
|
||||
if (s_CoverageReporterManager == null)
|
||||
s_CoverageReporterManager = CoverageReporterStarter.CoverageReporterManager;
|
||||
|
||||
ICoverageReporter coverageReporter = s_CoverageReporterManager.CoverageReporter;
|
||||
if (coverageReporter != null)
|
||||
coverageReporter.OnRunFinished(null);
|
||||
|
||||
CoverageRunData.instance.StopRecording();
|
||||
|
||||
s_CoverageReporterManager.GenerateReport();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: baf0187acde1d4a4d8183adbd25f4941
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,679 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor.TestTools.CodeCoverage.CommandLineParser;
|
||||
using UnityEditor.TestTools.CodeCoverage.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage
|
||||
{
|
||||
internal class CommandLineManager : CommandLineManagerImplementation
|
||||
{
|
||||
private static CommandLineManager s_Instance = null;
|
||||
|
||||
public static CommandLineManager instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Instance == null)
|
||||
s_Instance = new CommandLineManager();
|
||||
|
||||
return s_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
protected CommandLineManager() : base(Environment.GetCommandLineArgs())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class CommandLineManagerImplementation
|
||||
{
|
||||
public bool runFromCommandLine
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string coverageResultsPath
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string coverageHistoryPath
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateAdditionalMetrics
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateTestReferences
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateHTMLReportHistory
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateHTMLReport
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateBadgeReport
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateAdditionalReports
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool useProjectSettings
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool generateRootEmptyReport
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool dontClear
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool verbosityLevelSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool assemblyFiltersSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool assemblyFiltersFromFileSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool pathFiltersSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool pathFiltersFromFileSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool pathReplacingSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string sourcePaths
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool sourcePathsSpecified
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public AssemblyFiltering assemblyFiltering
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public PathFiltering pathFiltering
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public PathReplacing pathReplacing
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool runTests
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool batchmode
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool burstDisabled
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private string m_CoverageOptionsArg;
|
||||
private string m_IncludeAssemblies;
|
||||
private string m_ExcludeAssemblies;
|
||||
private string m_IncludePaths;
|
||||
private string m_ExcludePaths;
|
||||
private string m_PathReplacePatterns;
|
||||
|
||||
public CommandLineManagerImplementation(string[] commandLineArgs)
|
||||
{
|
||||
runFromCommandLine = false;
|
||||
coverageResultsPath = string.Empty;
|
||||
coverageHistoryPath = string.Empty;
|
||||
sourcePaths = string.Empty;
|
||||
generateAdditionalMetrics = false;
|
||||
generateTestReferences = false;
|
||||
generateHTMLReportHistory = false;
|
||||
generateHTMLReport = false;
|
||||
generateBadgeReport = false;
|
||||
generateAdditionalReports = false;
|
||||
useProjectSettings = false;
|
||||
generateRootEmptyReport = false;
|
||||
dontClear = false;
|
||||
verbosityLevelSpecified = false;
|
||||
assemblyFiltersSpecified = false;
|
||||
pathFiltersSpecified = false;
|
||||
pathReplacingSpecified = false;
|
||||
sourcePathsSpecified = false;
|
||||
pathFiltersFromFileSpecified = false;
|
||||
assemblyFiltering = new AssemblyFiltering();
|
||||
pathFiltering = new PathFiltering();
|
||||
pathReplacing = new PathReplacing();
|
||||
runTests = false;
|
||||
batchmode = false;
|
||||
burstDisabled = false;
|
||||
|
||||
m_CoverageOptionsArg = string.Empty;
|
||||
m_IncludeAssemblies = string.Empty;
|
||||
m_ExcludeAssemblies = string.Empty;
|
||||
m_IncludePaths = string.Empty;
|
||||
m_ExcludePaths = string.Empty;
|
||||
m_PathReplacePatterns = string.Empty;
|
||||
|
||||
CommandLineOptionSet optionSet = new CommandLineOptionSet(
|
||||
new CommandLineOption("enableCodeCoverage", () => { runFromCommandLine = true; }),
|
||||
new CommandLineOption("coverageResultsPath", filePathArg => { SetCoverageResultsPath(filePathArg); }),
|
||||
new CommandLineOption("coverageHistoryPath", filePathArg => { SetCoverageHistoryPath(filePathArg); }),
|
||||
new CommandLineOption("coverageOptions", optionsArg => { AddCoverageOptions(optionsArg); }),
|
||||
new CommandLineOption("runTests", () => { runTests = true; }),
|
||||
new CommandLineOption("batchmode", () => { batchmode = true; }),
|
||||
new CommandLineOption("-burst-disable-compilation", () => { burstDisabled = true; })
|
||||
);
|
||||
optionSet.Parse(commandLineArgs);
|
||||
|
||||
ValidateCoverageResultsPath();
|
||||
ValidateCoverageHistoryPath();
|
||||
|
||||
if (runFromCommandLine)
|
||||
ParseCoverageOptions();
|
||||
}
|
||||
|
||||
private void SetCoverageResultsPath(string filePathArg)
|
||||
{
|
||||
if (coverageResultsPath != string.Empty)
|
||||
{
|
||||
ResultsLogger.Log(ResultID.Warning_MultipleResultsPaths, coverageResultsPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filePathArg != null)
|
||||
{
|
||||
coverageResultsPath = CoverageUtils.NormaliseFolderSeparators(filePathArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateCoverageResultsPath()
|
||||
{
|
||||
if (!CoverageUtils.EnsureFolderExists(coverageResultsPath))
|
||||
coverageResultsPath = string.Empty;
|
||||
}
|
||||
|
||||
private void SetCoverageHistoryPath(string filePathArg)
|
||||
{
|
||||
if (coverageHistoryPath != string.Empty)
|
||||
{
|
||||
ResultsLogger.Log(ResultID.Warning_MultipleHistoryPaths, coverageHistoryPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filePathArg != null)
|
||||
{
|
||||
coverageHistoryPath = CoverageUtils.NormaliseFolderSeparators(filePathArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateCoverageHistoryPath()
|
||||
{
|
||||
if (!CoverageUtils.EnsureFolderExists(coverageHistoryPath))
|
||||
coverageHistoryPath = string.Empty;
|
||||
}
|
||||
|
||||
private void AddCoverageOptions(string coverageOptionsArg)
|
||||
{
|
||||
if (coverageOptionsArg != null)
|
||||
{
|
||||
coverageOptionsArg = coverageOptionsArg.Trim('\'');
|
||||
|
||||
if (coverageOptionsArg != string.Empty)
|
||||
{
|
||||
if (m_CoverageOptionsArg == string.Empty)
|
||||
{
|
||||
m_CoverageOptionsArg = coverageOptionsArg;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CoverageOptionsArg += ";";
|
||||
m_CoverageOptionsArg += coverageOptionsArg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseCoverageOptions()
|
||||
{
|
||||
// Make sure there is no trailing quotes at the end of the options
|
||||
m_CoverageOptionsArg = m_CoverageOptionsArg.TrimEnd('"');
|
||||
|
||||
// 'sourcePaths' option is moved at the beginning to ensure it is handled first,
|
||||
// since it may be needed for other options
|
||||
var options = m_CoverageOptionsArg.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
if (options.Count > 1)
|
||||
{
|
||||
var sourcePath = options.FirstOrDefault(option => option.StartsWith("SOURCEPATHS:", StringComparison.InvariantCultureIgnoreCase));
|
||||
if (sourcePath != null)
|
||||
{
|
||||
var sourcePathIndex = options.IndexOf(sourcePath);
|
||||
var firstElement = options[0];
|
||||
options[sourcePathIndex] = firstElement;
|
||||
options[0] = sourcePath;
|
||||
}
|
||||
}
|
||||
|
||||
string[] coverageOptions = options.ToArray();
|
||||
|
||||
foreach (string optionArgsStr in coverageOptions)
|
||||
{
|
||||
if (optionArgsStr.Length == 0)
|
||||
continue;
|
||||
|
||||
string optionName = optionArgsStr;
|
||||
string optionArgs = string.Empty;
|
||||
|
||||
int indexOfColon = optionArgsStr.IndexOf(':');
|
||||
if (indexOfColon > 0)
|
||||
{
|
||||
optionName = optionArgsStr.Substring(0, indexOfColon);
|
||||
optionArgs = optionArgsStr.Substring(indexOfColon+1);
|
||||
}
|
||||
|
||||
switch (optionName.ToUpperInvariant())
|
||||
{
|
||||
case "GENERATEADDITIONALMETRICS":
|
||||
generateAdditionalMetrics = true;
|
||||
break;
|
||||
|
||||
case "GENERATEHTMLREPORTHISTORY":
|
||||
generateHTMLReportHistory = true;
|
||||
break;
|
||||
|
||||
case "GENERATEHTMLREPORT":
|
||||
generateHTMLReport = true;
|
||||
break;
|
||||
|
||||
case "GENERATEBADGEREPORT":
|
||||
generateBadgeReport = true;
|
||||
break;
|
||||
|
||||
case "GENERATEADDITIONALREPORTS":
|
||||
generateAdditionalReports = true;
|
||||
break;
|
||||
|
||||
case "GENERATEROOTEMPTYREPORT":
|
||||
generateRootEmptyReport = true;
|
||||
break;
|
||||
|
||||
case "DONTCLEAR":
|
||||
dontClear = true;
|
||||
break;
|
||||
|
||||
case "GENERATETESTREFERENCES":
|
||||
generateTestReferences = true;
|
||||
break;
|
||||
|
||||
case "USEPROJECTSETTINGS":
|
||||
if (batchmode)
|
||||
useProjectSettings = true;
|
||||
else
|
||||
ResultsLogger.Log(ResultID.Warning_UseProjectSettingsNonBatchmode);
|
||||
break;
|
||||
|
||||
case "VERBOSITY":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
verbosityLevelSpecified = true;
|
||||
|
||||
switch (optionArgs.ToUpperInvariant())
|
||||
{
|
||||
case "VERBOSE":
|
||||
ResultsLogger.VerbosityLevel = LogVerbosityLevel.Verbose;
|
||||
break;
|
||||
case "INFO":
|
||||
ResultsLogger.VerbosityLevel = LogVerbosityLevel.Info;
|
||||
break;
|
||||
case "WARNING":
|
||||
ResultsLogger.VerbosityLevel = LogVerbosityLevel.Warning;
|
||||
break;
|
||||
case "ERROR":
|
||||
ResultsLogger.VerbosityLevel = LogVerbosityLevel.Error;
|
||||
break;
|
||||
case "OFF":
|
||||
ResultsLogger.VerbosityLevel = LogVerbosityLevel.Off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "ASSEMBLYFILTERS":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
assemblyFiltersSpecified = true;
|
||||
|
||||
string[] assemblyFilters = optionArgs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
ParseAssemblyFilters(assemblyFilters);
|
||||
}
|
||||
break;
|
||||
|
||||
case "PATHFILTERSFROMFILE":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
pathFiltersFromFileSpecified = true;
|
||||
ResultsLogger.Log(ResultID.Warning_PathFiltersFromFileDeprecation);
|
||||
|
||||
if (File.Exists(optionArgs))
|
||||
{
|
||||
try
|
||||
{
|
||||
ParsePathFilters( GetPathFiltersFromFile(optionArgs) );
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ResultsLogger.Log(ResultID.Warning_FailedToExtractPathFiltersFromFile, e.Message, optionArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "PATHFILTERS":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
string[] pathFilters = optionArgs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
ParsePathFilters(pathFilters);
|
||||
}
|
||||
break;
|
||||
|
||||
case "FILTERSFROMFILE":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonFile jsonFile = GetFiltersFromFile(optionArgs);
|
||||
if (jsonFile != null)
|
||||
{
|
||||
string[] pathFilters = ConvertToFilterArray(jsonFile.pathsInclude, jsonFile.pathsExclude);
|
||||
if (pathFilters != null && pathFilters.Length > 0)
|
||||
{
|
||||
pathFiltersFromFileSpecified = true;
|
||||
ParsePathFilters(pathFilters);
|
||||
}
|
||||
|
||||
string[] assemblyFilters = ConvertToFilterArray(jsonFile.assembliesInclude, jsonFile.assembliesExclude);
|
||||
if (assemblyFilters != null && assemblyFilters.Length > 0)
|
||||
{
|
||||
assemblyFiltersFromFileSpecified = true;
|
||||
ParseAssemblyFilters(assemblyFilters);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ResultsLogger.Log(ResultID.Warning_FailedToExtractFiltersFromFile, e.Message, optionArgs);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case "PATHREPLACEPATTERNS":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
pathReplacingSpecified = true;
|
||||
m_PathReplacePatterns = optionArgs;
|
||||
}
|
||||
break;
|
||||
|
||||
case "SOURCEPATHS":
|
||||
if (optionArgs.Length > 0)
|
||||
{
|
||||
string[] rawSourcePaths = optionArgs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int i = 0; i < rawSourcePaths.Length; ++i)
|
||||
{
|
||||
if (sourcePaths.Length > 0)
|
||||
sourcePaths += ",";
|
||||
sourcePaths += CoverageUtils.NormaliseFolderSeparators(rawSourcePaths[i]);
|
||||
}
|
||||
|
||||
if (sourcePaths.Length > 0)
|
||||
sourcePathsSpecified = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ResultsLogger.Log(ResultID.Warning_UnknownCoverageOptionProvided, optionArgsStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_IncludeAssemblies.Length == 0)
|
||||
{
|
||||
// If there are no inlcudedAssemblies specified but there are includedPaths specified
|
||||
// then include all project assemblies so path filtering can take precedence over assembly filtering,
|
||||
// othewise if there are no includedPaths specified neither then inlcude just the user assemblies (found under the Assets folder)
|
||||
|
||||
if (m_IncludePaths.Length > 0)
|
||||
m_IncludeAssemblies = AssemblyFiltering.GetAllProjectAssembliesString();
|
||||
else
|
||||
m_IncludeAssemblies = AssemblyFiltering.GetUserOnlyAssembliesString();
|
||||
}
|
||||
|
||||
assemblyFiltering.Parse(m_IncludeAssemblies, m_ExcludeAssemblies);
|
||||
pathFiltering.Parse(m_IncludePaths, m_ExcludePaths);
|
||||
pathReplacing.Parse(m_PathReplacePatterns);
|
||||
}
|
||||
|
||||
private void ParseAssemblyFilters(string[] assemblyFilters)
|
||||
{
|
||||
for (int i = 0; i < assemblyFilters.Length; ++i)
|
||||
{
|
||||
string filter = assemblyFilters[i];
|
||||
string filterBody = filter.Length > 1 ? filter.Substring(1) : string.Empty;
|
||||
|
||||
if (filter.StartsWith("+", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (m_IncludeAssemblies.Length > 0)
|
||||
m_IncludeAssemblies += ",";
|
||||
|
||||
if (filterBody.StartsWith("<", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.Equals(filterBody, AssemblyFiltering.kAssetsAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_IncludeAssemblies += AssemblyFiltering.GetUserOnlyAssembliesString();
|
||||
else if (string.Equals(filterBody, AssemblyFiltering.kAllAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_IncludeAssemblies += AssemblyFiltering.GetAllProjectAssembliesString();
|
||||
else if (string.Equals(filterBody, AssemblyFiltering.kPackagesAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_IncludeAssemblies += AssemblyFiltering.GetPackagesOnlyAssembliesString();
|
||||
else if (string.Equals(filterBody, AssemblyFiltering.kCoreAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_IncludeAssemblies += AssemblyFiltering.kCoreAssemblies;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IncludeAssemblies += filterBody;
|
||||
}
|
||||
}
|
||||
else if (filter.StartsWith("-", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (m_ExcludeAssemblies.Length > 0)
|
||||
m_ExcludeAssemblies += ",";
|
||||
|
||||
if (filterBody.StartsWith("<", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.Equals(filterBody, AssemblyFiltering.kAssetsAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_ExcludeAssemblies += AssemblyFiltering.GetUserOnlyAssembliesString();
|
||||
else if (string.Equals(filterBody, AssemblyFiltering.kAllAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_ExcludeAssemblies += AssemblyFiltering.GetAllProjectAssembliesString();
|
||||
else if (string.Equals(filterBody, AssemblyFiltering.kPackagesAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_ExcludeAssemblies += AssemblyFiltering.GetPackagesOnlyAssembliesString();
|
||||
else if (string.Equals(filterBody, AssemblyFiltering.kCoreAlias, StringComparison.OrdinalIgnoreCase))
|
||||
m_ExcludeAssemblies += AssemblyFiltering.kCoreAssemblies;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ExcludeAssemblies += filterBody;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ResultsLogger.Log(ResultID.Warning_AssemblyFiltersNotPrefixed, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParsePathFilters(string[] pathFilters)
|
||||
{
|
||||
var sources = new string[0];
|
||||
if (sourcePathsSpecified)
|
||||
sources = sourcePaths.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
for (int i = 0; i < pathFilters.Length; ++i)
|
||||
{
|
||||
string filter = pathFilters[i];
|
||||
string filterBody = filter.Length > 1 ? filter.Substring(1) : string.Empty;
|
||||
|
||||
var isRelative = !filterBody.StartsWith("*") && !filterBody.StartsWith("?") && string.IsNullOrEmpty(Path.GetPathRoot(filterBody));
|
||||
//If current path is relative - expand it to an absolute path using specified source paths
|
||||
if (isRelative && sourcePathsSpecified)
|
||||
{
|
||||
string expandedPaths = string.Empty;
|
||||
foreach (var source in sources)
|
||||
{
|
||||
if (expandedPaths.Length > 0)
|
||||
expandedPaths += ",";
|
||||
expandedPaths += CoverageUtils.NormaliseFolderSeparators(Path.Combine(source, filterBody));
|
||||
}
|
||||
filterBody = expandedPaths;
|
||||
}
|
||||
|
||||
if (filter.StartsWith("+", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (m_IncludePaths.Length > 0)
|
||||
m_IncludePaths += ",";
|
||||
m_IncludePaths += filterBody;
|
||||
}
|
||||
else if (filter.StartsWith("-", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (m_ExcludePaths.Length > 0)
|
||||
m_ExcludePaths += ",";
|
||||
m_ExcludePaths += filterBody;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResultsLogger.Log(ResultID.Warning_PathFiltersNotPrefixed, filter);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_IncludePaths.Length > 0 || m_ExcludePaths.Length > 0)
|
||||
pathFiltersSpecified = true;
|
||||
}
|
||||
|
||||
internal string[] GetPathFiltersFromFile(string path)
|
||||
{
|
||||
var paths = new List<string>();
|
||||
|
||||
foreach (var line in File.ReadAllLines(path))
|
||||
{
|
||||
var entry = line.Trim();
|
||||
paths.Add(CoverageUtils.NormaliseFolderSeparators(entry));
|
||||
}
|
||||
|
||||
return paths.ToArray();
|
||||
}
|
||||
|
||||
internal JsonFile GetFiltersFromFile(string path)
|
||||
{
|
||||
string jsonString = JsonUtils.CleanJsonString(File.ReadAllText(path));
|
||||
JsonUtils.ValidateJsonKeys(jsonString);
|
||||
JsonFile jsonFile = JsonUtility.FromJson<JsonFile>(jsonString);
|
||||
return jsonFile;
|
||||
}
|
||||
|
||||
internal string[] ConvertToFilterArray(string[] include, string[] exclude)
|
||||
{
|
||||
var filtersList = new List<string>();
|
||||
|
||||
if (include != null && include.Length > 0)
|
||||
{
|
||||
foreach (var filter in include)
|
||||
{
|
||||
filtersList.Add($"+{filter}");
|
||||
}
|
||||
}
|
||||
if (exclude != null && exclude.Length > 0)
|
||||
{
|
||||
foreach (var filter in exclude)
|
||||
{
|
||||
filtersList.Add($"-{filter}");
|
||||
}
|
||||
}
|
||||
return filtersList.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d1e5d1da297ded489d27da1867372cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4d2c6ec2b0608f4d915bdae931a5561
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage.CommandLineParser
|
||||
{
|
||||
internal class CommandLineOption : ICommandLineOption
|
||||
{
|
||||
readonly Action<string> m_ArgAction;
|
||||
|
||||
public CommandLineOption(string argName, Action action)
|
||||
{
|
||||
ArgName = argName;
|
||||
m_ArgAction = s => action();
|
||||
}
|
||||
|
||||
public CommandLineOption(string argName, Action<string> action)
|
||||
{
|
||||
ArgName = argName;
|
||||
m_ArgAction = action;
|
||||
}
|
||||
|
||||
public CommandLineOption(string argName, Action<string[]> action)
|
||||
{
|
||||
ArgName = argName;
|
||||
m_ArgAction = s => action(SplitStringToArray(s));
|
||||
}
|
||||
|
||||
public string ArgName { get; private set; }
|
||||
|
||||
public void ApplyValue(string value)
|
||||
{
|
||||
m_ArgAction(value);
|
||||
}
|
||||
|
||||
static string[] SplitStringToArray(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return new string[] { };
|
||||
}
|
||||
|
||||
return value.Split(';').ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b33e1d48774f68f479218e97f4ca4a8e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage.CommandLineParser
|
||||
{
|
||||
internal class CommandLineOptionSet
|
||||
{
|
||||
readonly ICommandLineOption[] m_Options;
|
||||
|
||||
public CommandLineOptionSet(params ICommandLineOption[] options)
|
||||
{
|
||||
m_Options = options;
|
||||
}
|
||||
|
||||
public void Parse(string[] args)
|
||||
{
|
||||
var i = 0;
|
||||
while (i < args.Length)
|
||||
{
|
||||
var arg = args[i];
|
||||
if (!arg.StartsWith("-"))
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = null;
|
||||
if (i + 1 < args.Length && !args[i + 1].StartsWith("-"))
|
||||
{
|
||||
value = args[i + 1];
|
||||
i++;
|
||||
}
|
||||
|
||||
ApplyValueToMatchingOptions(arg, value);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyValueToMatchingOptions(string argName, string value)
|
||||
{
|
||||
foreach (var option in m_Options)
|
||||
{
|
||||
if ("-" + option.ArgName == argName)
|
||||
{
|
||||
option.ApplyValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99c7f651b61814e4fbfa07eaa1457453
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace UnityEditor.TestTools.CodeCoverage.CommandLineParser
|
||||
{
|
||||
interface ICommandLineOption
|
||||
{
|
||||
string ArgName { get; }
|
||||
void ApplyValue(string value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e6a21b19469f7743953f66cd419decc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8760551a767291a4f9d72703986de775
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Unity.TestTools.CodeCoverage.Editor.Compatibility",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"!UNITY_2019_2_OR_NEWER"
|
||||
],
|
||||
"versionDefines": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5518f4bf96c8e9849ab65cbaaf1191e1
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
internal class CompatibilityInitializer
|
||||
{
|
||||
static CompatibilityInitializer()
|
||||
{
|
||||
Debug.LogError("[Code Coverage] The Code Coverage package is not compatible with versions of Unity earlier than 2019.2.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae5c3e58418ef514eba4fc6ade0ec75b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8502d38e600753d44a2a65242d06f132
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace UnityEditor.TestTools.CodeCoverage
|
||||
{
|
||||
internal enum CoverageFormat
|
||||
{
|
||||
OpenCover = 0,
|
||||
DotCover = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8419585fc64d77e4d8e18b7311df59a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 401e5b541d6e30e489f5751eec729fab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Mono.Reflection;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage.OpenCover
|
||||
{
|
||||
internal static class CyclomaticComplexity
|
||||
{
|
||||
private static List<Instruction> targets = new List<Instruction>();
|
||||
|
||||
public static int CalculateCyclomaticComplexity(this MethodBase method)
|
||||
{
|
||||
if (method == null || method.GetMethodBody() == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool hasSwitch = false;
|
||||
foreach (Instruction ins in method.GetInstructions())
|
||||
{
|
||||
if (ins.OpCode.OperandType == OperandType.InlineSwitch)
|
||||
{
|
||||
hasSwitch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSwitch)
|
||||
{
|
||||
return GetSwitchCyclomaticComplexity(method);
|
||||
}
|
||||
return GetFastCyclomaticComplexity(method);
|
||||
}
|
||||
|
||||
private static int GetFastCyclomaticComplexity(MethodBase method)
|
||||
{
|
||||
int cc = 1;
|
||||
foreach (Instruction ins in method.GetInstructions())
|
||||
{
|
||||
switch (ins.OpCode.FlowControl)
|
||||
{
|
||||
case FlowControl.Branch:
|
||||
// detect ternary pattern
|
||||
Instruction previous = ins.Previous;
|
||||
if (previous != null && previous.OpCode.Name.StartsWith("ld"))
|
||||
{
|
||||
++cc;
|
||||
}
|
||||
break;
|
||||
|
||||
case FlowControl.Cond_Branch:
|
||||
++cc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
private static int GetSwitchCyclomaticComplexity(MethodBase method)
|
||||
{
|
||||
Instruction previous = null;
|
||||
Instruction branch = null;
|
||||
int cc = 1;
|
||||
|
||||
foreach (Instruction ins in method.GetInstructions())
|
||||
{
|
||||
switch (ins.OpCode.FlowControl)
|
||||
{
|
||||
case FlowControl.Branch:
|
||||
if (previous == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// detect ternary pattern
|
||||
previous = ins.Previous;
|
||||
if (previous.OpCode.Name.StartsWith("ld"))
|
||||
{
|
||||
cc++;
|
||||
}
|
||||
|
||||
// or 'default' (xmcs)
|
||||
if (previous.OpCode.FlowControl == FlowControl.Cond_Branch)
|
||||
{
|
||||
branch = (previous.Operand as Instruction);
|
||||
// branch can be null (e.g. switch -> Instruction[])
|
||||
if ((branch != null) && targets.Contains(branch) && !targets.Contains(ins))
|
||||
{
|
||||
targets.Add(ins);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FlowControl.Cond_Branch:
|
||||
// note: a single switch (C#) with sparse values can be broken into several swicth (IL)
|
||||
// that will use the same 'targets' and must be counted only once
|
||||
if (ins.OpCode.OperandType == OperandType.InlineSwitch)
|
||||
{
|
||||
AccumulateSwitchTargets(ins);
|
||||
}
|
||||
else
|
||||
{
|
||||
// some conditional branch can be related to the sparse switch
|
||||
branch = (ins.Operand as Instruction);
|
||||
previous = branch.Previous;
|
||||
if ((previous != null) && previous.Previous.OpCode.OperandType != OperandType.InlineSwitch)
|
||||
{
|
||||
if (!targets.Contains(branch))
|
||||
{
|
||||
cc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// count all unique targets (and default if more than one C# switch is used)
|
||||
cc += targets.Count;
|
||||
targets.Clear();
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
private static void AccumulateSwitchTargets(Instruction ins)
|
||||
{
|
||||
Instruction[] cases = (Instruction[])ins.Operand;
|
||||
foreach (Instruction target in cases)
|
||||
{
|
||||
// ignore targets that are the next instructions (xmcs)
|
||||
if (target != ins.Next && !targets.Contains(target))
|
||||
targets.Add(target);
|
||||
}
|
||||
// add 'default' branch (if one exists)
|
||||
Instruction next = ins.Next;
|
||||
if (next.OpCode.FlowControl == FlowControl.Branch)
|
||||
{
|
||||
Instruction unc = FindFirstUnconditionalBranchTarget(cases[0]);
|
||||
if (unc != next.Operand && !targets.Contains(next.Operand as Instruction))
|
||||
targets.Add(next.Operand as Instruction);
|
||||
}
|
||||
}
|
||||
|
||||
private static Instruction FindFirstUnconditionalBranchTarget(Instruction ins)
|
||||
{
|
||||
while (ins != null)
|
||||
{
|
||||
if (FlowControl.Branch == ins.OpCode.FlowControl)
|
||||
return ((Instruction)ins.Operand);
|
||||
|
||||
ins = ins.Next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74449815e747b4b1ba000bf66f12e01a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c2ede2081f2f4c45a6f7f4c92e3a735
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// a branch point
|
||||
/// </summary>
|
||||
public class BranchPoint : InstrumentationPoint, IDocumentReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Line of the branching instruction
|
||||
/// </summary>
|
||||
[XmlAttribute("sl")]
|
||||
public int StartLine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A path that can be taken
|
||||
/// </summary>
|
||||
[XmlAttribute("path")]
|
||||
public int Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of OffsetPoints between Offset and EndOffset (exclusive)
|
||||
/// </summary>
|
||||
[XmlAttribute("offsetchain")]
|
||||
public System.Collections.Generic.List<int> OffsetPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should offset points be serialized
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ShouldSerializeOffsetPoints()
|
||||
{
|
||||
return OffsetPoints.Maybe(_ => _.Any());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Last Offset == EndOffset.
|
||||
/// Can be same as Offset
|
||||
/// </summary>
|
||||
[XmlAttribute("offsetend")]
|
||||
public int EndOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file associated with the supplied startline
|
||||
/// </summary>
|
||||
[XmlAttribute("fileid")]
|
||||
public uint FileId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The url to the document if an entry was not mapped to an id
|
||||
/// </summary>
|
||||
[XmlAttribute("url")]
|
||||
public string Document { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88cac9839726d46718b126833c76c5e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// An entity that contains methods
|
||||
/// </summary>
|
||||
public class Class : SummarySkippedEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// instantiate
|
||||
/// </summary>
|
||||
public Class()
|
||||
{
|
||||
Methods = new Method[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The full name of the class
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
internal File[] Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of methods that make up the class
|
||||
/// </summary>
|
||||
public Method[] Methods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a class was skipped by instrumentation, supply the reason why
|
||||
/// </summary>
|
||||
/// <param name="reason"></param>
|
||||
public override void MarkAsSkipped(SkippedMethod reason)
|
||||
{
|
||||
SkippedDueTo = reason;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0d40fe321f9746dcbccb27824986511
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A coverage session
|
||||
/// </summary>
|
||||
public class CoverageSession
|
||||
{
|
||||
private string _version;
|
||||
|
||||
/// <summary>
|
||||
/// initialise a coverage session
|
||||
/// </summary>
|
||||
public CoverageSession()
|
||||
{
|
||||
Modules = new Module[0];
|
||||
Summary = new Summary();
|
||||
_version = GetType().Assembly.GetName().Version.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// A unique session identifier
|
||||
/// </summary>
|
||||
public string SessionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A Summary of results for the session
|
||||
/// </summary>
|
||||
public Summary Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of modules that have been profiled under the session
|
||||
/// </summary>
|
||||
public Module[] Modules { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current version
|
||||
/// </summary>
|
||||
[XmlAttribute("Version")]
|
||||
public string Version {
|
||||
get { return _version; }
|
||||
// ReSharper disable once ValueParameterNotUsed
|
||||
set { /* intentionally left blank */} }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 561dcfbc5a4094415b3d8348f1a6b738
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A file reference within the coverage session and is used to point to an existing File entity
|
||||
/// </summary>
|
||||
public class FileRef
|
||||
{
|
||||
/// <summary>
|
||||
/// The uniqueid of a file in a coverage session
|
||||
/// </summary>
|
||||
[XmlAttribute("uid")]
|
||||
public UInt32 UniqueId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File details of a source file
|
||||
/// </summary>
|
||||
public class File : FileRef
|
||||
{
|
||||
private static int _uId;
|
||||
|
||||
static readonly List<File> Files = new List<File>();
|
||||
|
||||
internal static void ResetAfterLoading()
|
||||
{
|
||||
_uId = (int)Files.Max(x => x.UniqueId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A standard constructor
|
||||
/// </summary>
|
||||
public File()
|
||||
{
|
||||
UniqueId = (UInt32)Interlocked.Increment(ref _uId);
|
||||
Files.Add(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The path to file
|
||||
/// </summary>
|
||||
[XmlAttribute("fullPath")]
|
||||
public string FullPath { get; set; }
|
||||
}
|
||||
|
||||
internal class FileEqualityComparer : IEqualityComparer<File>
|
||||
{
|
||||
public bool Equals(File x, File y)
|
||||
{
|
||||
return x.FullPath == y.FullPath;
|
||||
}
|
||||
|
||||
public int GetHashCode(File obj)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ea0122a5084b4beca6bbb008fea821e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace OpenCover.Framework
|
||||
{
|
||||
internal static class HelperExtensions
|
||||
{
|
||||
public static TRet Maybe<T, TRet>(this T value, Func<T, TRet> action, TRet defValue = default(TRet))
|
||||
where T : class
|
||||
{
|
||||
return (value != null) ? action(value) : defValue;
|
||||
}
|
||||
|
||||
public static T Do<T>(this T value, Action<T> action)
|
||||
where T : class
|
||||
{
|
||||
if (value != null)
|
||||
action(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static T Try<T>(this T value, Action<T> action)
|
||||
where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
if (value != null)
|
||||
action(value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore error
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a74e938125304007a53cf9733cd1208
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A point may have a document reference
|
||||
/// </summary>
|
||||
public interface IDocumentReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The document url
|
||||
/// </summary>
|
||||
string Document { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The document id after lookup
|
||||
/// </summary>
|
||||
uint FileId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebffa2e2071ad4f79a3641b47e74b25e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// An instrumentable point
|
||||
/// </summary>
|
||||
public class InstrumentationPoint
|
||||
{
|
||||
private static int _instrumentPoint;
|
||||
private static readonly object LockObject = new object();
|
||||
private static readonly List<InstrumentationPoint> InstrumentPoints;
|
||||
|
||||
static InstrumentationPoint()
|
||||
{
|
||||
_instrumentPoint = 0;
|
||||
InstrumentPoints = new List<InstrumentationPoint>(8192) {null};
|
||||
}
|
||||
|
||||
internal static void Clear()
|
||||
{
|
||||
InstrumentPoints.Clear();
|
||||
InstrumentPoints.Add(null);
|
||||
_instrumentPoint = 0;
|
||||
}
|
||||
|
||||
internal static void ResetAfterLoading()
|
||||
{
|
||||
var points = InstrumentPoints
|
||||
.Where(x => x != null)
|
||||
.GroupBy(x => x.UniqueSequencePoint)
|
||||
.Select(g => g.OrderBy(x => x.OrigSequencePoint).First())
|
||||
.ToList();
|
||||
|
||||
var max = (int)points.Max(x => x.UniqueSequencePoint);
|
||||
|
||||
InstrumentPoints.Clear();
|
||||
InstrumentPoints.Add(null);
|
||||
|
||||
for (var i = 1; i <= max; i++)
|
||||
{
|
||||
var point = new SequencePoint();
|
||||
InstrumentPoints[i] = point;
|
||||
point.UniqueSequencePoint = (uint)i;
|
||||
}
|
||||
|
||||
foreach (var instrumentationPoint in points)
|
||||
{
|
||||
InstrumentPoints[(int)instrumentationPoint.UniqueSequencePoint] = instrumentationPoint;
|
||||
}
|
||||
|
||||
_instrumentPoint = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of visit points
|
||||
/// </summary>
|
||||
public static int Count {
|
||||
get { return InstrumentPoints.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of recorded visit points for this identifier
|
||||
/// </summary>
|
||||
/// <param name="spid">the sequence point identifier - NOTE 0 is not used</param>
|
||||
public static int GetVisitCount(uint spid)
|
||||
{
|
||||
return InstrumentPoints[(int) spid].VisitCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a number of recorded visit ppints against this identifier
|
||||
/// </summary>
|
||||
/// <param name="spid">the sequence point identifier - NOTE 0 is not used</param>
|
||||
/// <param name="trackedMethodId">the id of a tracked method - Note 0 means no method currently tracking</param>
|
||||
/// <param name="amount">the number of visit points to add</param>
|
||||
public static bool AddVisitCount(uint spid, uint trackedMethodId, int amount)
|
||||
{
|
||||
if (spid != 0 && spid < InstrumentPoints.Count)
|
||||
{
|
||||
var point = InstrumentPoints[(int) spid];
|
||||
point.VisitCount += amount;
|
||||
if (point.VisitCount < 0)
|
||||
{
|
||||
point.VisitCount = int.MaxValue;
|
||||
}
|
||||
if (trackedMethodId != 0)
|
||||
{
|
||||
AddOrUpdateTrackingPoint(trackedMethodId, amount, point);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void AddOrUpdateTrackingPoint(uint trackedMethodId, int amount, InstrumentationPoint point)
|
||||
{
|
||||
point._tracked = point._tracked ?? new List<TrackedMethodRef>();
|
||||
var tracked = point._tracked.Find(x => x.UniqueId == trackedMethodId);
|
||||
if (tracked == null)
|
||||
{
|
||||
tracked = new TrackedMethodRef {UniqueId = trackedMethodId, VisitCount = amount};
|
||||
point._tracked.Add(tracked);
|
||||
}
|
||||
else
|
||||
{
|
||||
tracked.VisitCount += amount;
|
||||
if (tracked.VisitCount < 0)
|
||||
tracked.VisitCount = int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
private List<TrackedMethodRef> _tracked;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise
|
||||
/// </summary>
|
||||
public InstrumentationPoint()
|
||||
{
|
||||
lock (LockObject)
|
||||
{
|
||||
UniqueSequencePoint = (uint)++_instrumentPoint;
|
||||
InstrumentPoints.Add(this);
|
||||
OrigSequencePoint = UniqueSequencePoint;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store the number of visits
|
||||
/// </summary>
|
||||
[XmlAttribute("vc")]
|
||||
public int VisitCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A unique number
|
||||
/// </summary>
|
||||
[XmlAttribute("uspid")]
|
||||
public UInt32 UniqueSequencePoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An order of the point within the method
|
||||
/// </summary>
|
||||
[XmlAttribute("ordinal")]
|
||||
public UInt32 Ordinal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IL offset of the point
|
||||
/// </summary>
|
||||
[XmlAttribute("offset")]
|
||||
public int Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to hide an instrumentation point
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public bool IsSkipped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of tracked methods
|
||||
/// </summary>
|
||||
public TrackedMethodRef[] TrackedMethodRefs
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_tracked != null)
|
||||
{
|
||||
return _tracked.ToArray();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
_tracked = null;
|
||||
if (value == null)
|
||||
return;
|
||||
_tracked = new List<TrackedMethodRef>(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public UInt32 OrigSequencePoint { get; set; }
|
||||
}
|
||||
}
|
||||