1"use strict";(self.webpackChunkstryker_mutator_github_io=self.webpackChunkstryker_mutator_github_io||[]).push([["7515"],{94275:function(t,e,n){n.r(e),n.d(e,{metadata:function(){return s},default:function(){return u},frontMatter:function(){return o},contentTitle:function(){return a},toc:function(){return d},assets:function(){return l}});var s=JSON.parse('{"id":"mutation-testing-elements/mutant-states-and-metrics","title":"Mutant states and metrics","description":"This page should shed some light on the different outcomes a mutant can have and the different metrics you\'ll find in any given mutation testing report.","source":"@site/docs/mutation-testing-elements/mutant-states-and-metrics.md","sourceDirName":"mutation-testing-elements","slug":"/mutation-testing-elements/mutant-states-and-metrics","permalink":"/docs/mutation-testing-elements/mutant-states-and-metrics","draft":false,"unlisted":false,"editUrl":"https://github.com/stryker-mutator/mutation-testing-elements/edit/master/docs/mutant-states-and-metrics.md","tags":[],"version":"current","frontMatter":{"title":"Mutant states and metrics","custom_edit_url":"https://github.com/stryker-mutator/mutation-testing-elements/edit/master/docs/mutant-states-and-metrics.md"},"sidebar":"docs","previous":{"title":"Implementing real-time reporting","permalink":"/docs/mutation-testing-elements/implementing-real-time-reporting"},"next":{"title":"SonarQube integration","permalink":"/docs/mutation-testing-elements/sonarqube-integration"}}'),i=n(94686),r=n(23191);let o={title:"Mutant states and metrics",custom_edit_url:"https://github.com/stryker-mutator/mutation-testing-elements/edit/master/docs/mutant-states-and-metrics.md"},a,l={},d=[{value:"Mutant states",id:"mutant-states",level:2},{value:"Metrics",id:"metrics",level:2},{value:"Test states and metrics",id:"test-states-and-metrics",level:2}];function c(t){let e={a:"a",br:"br",code:"code",em:"em",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.p,{children:"This page should shed some light on the different outcomes a mutant can have and the different metrics you'll find in any given mutation testing report."}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsxs)(e.em,{children:["Are you new to mutation testing, see ",(0,i.jsx)(e.a,{href:"https://stryker-mutator.io/docs/",children:"what is mutation testing?"})]}),"."]}),"\n",(0,i.jsx)(e.h2,{id:"mutant-states",children:"Mutant states"}),"\n",(0,i.jsx)(e.p,{children:"A mutant can have one of the following states:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Pending"}),"\nThe mutant has been generated, but not run yet. This is a temporary state and will be changed once the mutant has been tested."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Killed"}),"\nWhen at least one test failed while this mutant was active, the mutant is killed. This is what you want, good job!"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Survived"}),"\nWhen all tests passed while this mutant was active, the mutant survived. You're missing a test for it."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"No coverage"}),"\nThe mutant isn't covered by one of your tests and survived as a result."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Timeout"}),'\nThe running of tests with this mutant active resulted in a timeout.\nFor example, the mutant resulted in an infinite loop in your code.\nDon\'t spend too much attention to this mutant.\nIt is counted as "detected". The logic here is that if this mutant were to be injected in your code,\nyour CI build would detect it because the tests will never complete.']}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Runtime error"}),"\nThe running of the tests resulted in an error (rather than a failed test).\nThis can happen when the test runner fails. For example, when a test runner throws an ",(0,i.jsx)(e.code,{children:"OutOfMemoryError"})," or for dynamic languages where the mutant resulted in unparsable code.\nDon't spend too much attention looking at this mutant. It is not represented in your mutation score."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Compile error"}),"\nThe mutant caused a compile error.\nThis can happen in compiled languages.\nDon't spend too much attention looking at this mutant.\nIt is not represented in your mutation score."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Ignored"}),"\nThe mutant wasn't tested because it is ignored. Either by user action, or for another reason.\nThis will not count against your mutation score but will show up in reports."]}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"metrics",children:"Metrics"}),"\n",(0,i.jsx)(e.p,{children:"Based on these states, we can calculate the following metrics:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Detected"})," ",(0,i.jsx)(e.code,{children:"killed + timeout"}),(0,i.jsx)(e.br,{}),"\n","The number of mutants detected by your tests."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Undetected"})," ",(0,i.jsx)(e.code,{children:"survived + no coverage"}),(0,i.jsx)(e.br,{}),"\n","The number of mutants that are not detected by your tests."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Covered"})," ",(0,i.jsx)(e.code,{children:"detected + survived"}),(0,i.jsx)(e.br,{}
1),"\n","The number of mutants that your tests produce code coverage for."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Valid"})," ",(0,i.jsx)(e.code,{children:"detected + undetected"}),(0,i.jsx)(e.br,{}),"\n","The number of valid mutants. They didn't result in a compile error or runtime error."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Invalid"})," ",(0,i.jsx)(e.code,{children:"runtime errors + compile errors"}),(0,i.jsx)(e.br,{}),"\n","The number of invalid mutants. They couldn't be tested because they produce either a compile error or a runtime error."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Total mutants"})," ",(0,i.jsx)(e.code,{children:"valid + invalid + ignored + pending"}),(0,i.jsx)(e.br,{}),"\n","All mutants."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Mutation score"})," ",(0,i.jsx)(e.code,{children:"detected / valid * 100"}),(0,i.jsx)(e.br,{}),"\n","The total percentage of mutants that were detected. The higher, the better!"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Mutation score based on covered code"})," ",(0,i.jsx)(e.code,{children:"detected / covered * 100"}),(0,i.jsx)(e.br,{}),"\n","The total percentage of mutants that were detected based on the code coverage results."]}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"test-states-and-metrics",children:"Test states and metrics"}),"\n",(0,i.jsxs)(e.p,{children:["A ",(0,i.jsx)(e.em,{children:"test"})," can also have state with regards to mutation testing."]}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Killing"}),"\nThe test is killing at least one mutant. This is what you want."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Covering"}),"\nThe test is covering mutants, but not killing any of them. The coverage information should be available per test to provide this test state."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Not covering"}),"\nThe test is not even covering any mutants (and thus not killing any of them)."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"Total"})," ",(0,i.jsx)(e.code,{children:"not covering + covering + killing"}),"\nTotal number of tests."]}),"\n"]})]})}function u(t={}){let{wrapper:e}={...(0,r.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(c,{...t})}):c(t)}},23191:function(t,e,n){n.d(e,{R:function(){return o},x:function(){return a}});var s=n(92990);let i={},r=s.createContext(i);function o(t){let e=s.useContext(r);return s.useMemo(function(){return"function"==typeof t?t(e):{...e,...t}},[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(i):t.components||i:o(t.components),s.createElement(r.Provider,{value:e},t.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.