mutation-testing-metrics
Advanced tools
Comparing version 1.5.2 to 1.6.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [1.6.0](https://github.com/stryker-mutator/mutation-testing-elements/compare/v1.5.2...v1.6.0) (2021-02-22) | ||
### Features | ||
* **metrics:** add test metrics ([#871](https://github.com/stryker-mutator/mutation-testing-elements/issues/871)) ([4758f39](https://github.com/stryker-mutator/mutation-testing-elements/commit/4758f39a3b08a9fd5828d6491d4d559ac38308d6)) | ||
## [1.5.1](https://github.com/stryker-mutator/mutation-testing-elements/compare/v1.5.0...v1.5.1) (2020-12-23) | ||
@@ -8,0 +19,0 @@ |
@@ -1,9 +0,15 @@ | ||
import { FileResultDictionary } from 'mutation-testing-report-schema'; | ||
import { MetricsResult } from './api/MetricsResult'; | ||
import { FileResult, MutationTestResult } from 'mutation-testing-report-schema'; | ||
import { FileUnderTestModel, Metrics, MetricsResult, MutationTestMetricsResult } from './model'; | ||
/** | ||
* Calculates the metrics inside of a mutation testing report | ||
* Calculates the files-under-test metrics inside of a mutation testing report | ||
* @param files The files inside the mutation testing report | ||
* @returns A MetricsResult containing the metrics for the entire report. See `childResults` | ||
*/ | ||
export declare function calculateMetrics(files: FileResultDictionary): MetricsResult; | ||
export declare function calculateMetrics(files: Record<string, FileResult>): MetricsResult<FileUnderTestModel, Metrics>; | ||
/** | ||
* Calculates the full mutation test metrics from both the files-under-test as well as (optionally) the test files. | ||
* @param result The full mutation test result | ||
* @returns A MutationTestMetricsResult that contains both the `systemUnderTestMetrics` as well as the `testMetrics` | ||
*/ | ||
export declare function calculateMutationTestMetrics(result: MutationTestResult): MutationTestMetricsResult; | ||
//# sourceMappingURL=calculateMetrics.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.calculateMetrics = void 0; | ||
exports.calculateMutationTestMetrics = exports.calculateMetrics = void 0; | ||
const helpers_1 = require("./helpers"); | ||
const mutation_testing_report_schema_1 = require("mutation-testing-report-schema"); | ||
const helpers_2 = require("./helpers"); | ||
const model_1 = require("./model"); | ||
const DEFAULT_SCORE = NaN; | ||
const ROOT_NAME = 'All files'; | ||
const ROOT_NAME_TESTS = 'All tests'; | ||
/** | ||
* Calculates the metrics inside of a mutation testing report | ||
* Calculates the files-under-test metrics inside of a mutation testing report | ||
* @param files The files inside the mutation testing report | ||
@@ -15,10 +17,32 @@ * @returns A MetricsResult containing the metrics for the entire report. See `childResults` | ||
function calculateMetrics(files) { | ||
const normalizedFiles = helpers_1.normalizeFileNames(files); | ||
return calculateDirectoryMetrics(normalizedFiles, ROOT_NAME); | ||
const normalizedFiles = helpers_1.normalize(files, (input) => new model_1.FileUnderTestModel(input)); | ||
return calculateDirectoryMetrics(ROOT_NAME, normalizedFiles, countFileMetrics); | ||
} | ||
exports.calculateMetrics = calculateMetrics; | ||
function calculateDirectoryMetrics(files, name) { | ||
const metrics = countMetrics(helpers_1.flatMap(Object.values(files), (file) => file.mutants)); | ||
const childResults = toChildModels(files); | ||
/** | ||
* Calculates the full mutation test metrics from both the files-under-test as well as (optionally) the test files. | ||
* @param result The full mutation test result | ||
* @returns A MutationTestMetricsResult that contains both the `systemUnderTestMetrics` as well as the `testMetrics` | ||
*/ | ||
function calculateMutationTestMetrics(result) { | ||
const { files, testFiles } = result; | ||
const fileModelsUnderTest = helpers_1.normalize(files, (input) => new model_1.FileUnderTestModel(input)); | ||
if (testFiles) { | ||
const testFileModels = helpers_1.normalize(testFiles, (input) => new model_1.TestFileModel(input)); | ||
relate(Object.values(fileModelsUnderTest).flatMap((file) => file.mutants), Object.values(testFileModels).flatMap((file) => file.tests)); | ||
return { | ||
systemUnderTestMetrics: calculateDirectoryMetrics(ROOT_NAME, fileModelsUnderTest, countFileMetrics), | ||
testMetrics: calculateDirectoryMetrics(ROOT_NAME_TESTS, testFileModels, countTestFileMetrics), | ||
}; | ||
} | ||
return { | ||
systemUnderTestMetrics: calculateDirectoryMetrics(ROOT_NAME, fileModelsUnderTest, countFileMetrics), | ||
testMetrics: undefined, | ||
}; | ||
} | ||
exports.calculateMutationTestMetrics = calculateMutationTestMetrics; | ||
function calculateDirectoryMetrics(name, files, calculateMetrics) { | ||
const metrics = calculateMetrics(Object.values(files)); | ||
const childResults = toChildModels(files, calculateMetrics); | ||
return { | ||
name, | ||
@@ -29,3 +53,3 @@ childResults, | ||
} | ||
function calculateFileMetrics(fileName, file) { | ||
function calculateFileMetrics(fileName, file, calculateMetrics) { | ||
return { | ||
@@ -35,6 +59,6 @@ file, | ||
childResults: [], | ||
metrics: countMetrics(file.mutants), | ||
metrics: calculateMetrics([file]), | ||
}; | ||
} | ||
function toChildModels(files) { | ||
function toChildModels(files, calculateMetrics) { | ||
const filesByDirectory = helpers_2.groupBy(Object.entries(files), (namedFile) => namedFile[0].split('/')[0]); | ||
@@ -46,8 +70,7 @@ return Object.keys(filesByDirectory) | ||
filesByDirectory[directoryName].forEach((file) => (directoryFiles[file[0].substr(directoryName.length + 1)] = file[1])); | ||
return calculateDirectoryMetrics(directoryFiles, directoryName); | ||
return calculateDirectoryMetrics(directoryName, directoryFiles, calculateMetrics); | ||
} | ||
else { | ||
const fileName = filesByDirectory[directoryName][0][0]; | ||
const file = filesByDirectory[directoryName][0][1]; | ||
return calculateFileMetrics(fileName, file); | ||
const [fileName, file] = filesByDirectory[directoryName][0]; | ||
return calculateFileMetrics(fileName, file, calculateMetrics); | ||
} | ||
@@ -57,3 +80,30 @@ }) | ||
} | ||
function countMetrics(mutants) { | ||
function relate(mutants, tests) { | ||
var _a, _b; | ||
for (const mutant of mutants) { | ||
if (mutant.coveredBy || mutant.killedBy) { | ||
for (const test of tests) { | ||
if ((_a = mutant.coveredBy) === null || _a === void 0 ? void 0 : _a.includes(test.id)) { | ||
mutant.addCoveredBy(test); | ||
test.addCovered(mutant); | ||
} | ||
if ((_b = mutant.killedBy) === null || _b === void 0 ? void 0 : _b.includes(test.id)) { | ||
mutant.addKilledBy(test); | ||
test.addKilled(mutant); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
function countTestFileMetrics(testFile) { | ||
const tests = testFile.flatMap((_) => _.tests); | ||
return { | ||
total: tests.length, | ||
killing: tests.reduce((acc, test) => { var _a; return (((_a = test.killedMutants) === null || _a === void 0 ? void 0 : _a.length) ? ++acc : acc); }, 0), | ||
notKilling: tests.reduce((acc, test) => { var _a; return (!((_a = test.killedMutants) === null || _a === void 0 ? void 0 : _a.length) ? ++acc : acc); }, 0), | ||
notCovering: tests.reduce((acc, test) => { var _a; return (!((_a = test.coveredMutants) === null || _a === void 0 ? void 0 : _a.length) ? ++acc : acc); }, 0), | ||
}; | ||
} | ||
function countFileMetrics(fileResult) { | ||
const mutants = fileResult.flatMap((_) => _.mutants); | ||
const count = (status) => mutants.filter((_) => _.status === status).length; | ||
@@ -60,0 +110,0 @@ const killed = count(mutation_testing_report_schema_1.MutantStatus.Killed); |
@@ -1,8 +0,6 @@ | ||
import { MetricsResult } from './api/MetricsResult'; | ||
import { FileResultDictionary } from 'mutation-testing-report-schema'; | ||
export declare function flatMap<T, R>(source: T[], fn: (input: T) => R[]): R[]; | ||
import { MetricsResult } from './model/metrics-result'; | ||
export declare function groupBy<T>(arr: T[], criteria: (element: T) => string): Record<string, T[]>; | ||
export declare function pathJoin(...parts: string[]): string; | ||
export declare function normalizeFileNames(input: FileResultDictionary): FileResultDictionary; | ||
export declare function compareNames(a: MetricsResult, b: MetricsResult): number; | ||
export declare function normalizeFileNames<TIn>(input: Record<string, TIn>): Record<string, TIn>; | ||
export declare function normalize<TIn, TOut>(input: Record<string, TIn>, factory: (input: TIn) => TOut): Record<string, TOut>; | ||
export declare function compareNames(a: MetricsResult<any, any>, b: MetricsResult<any, any>): number; | ||
//# sourceMappingURL=helpers.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.compareNames = exports.normalizeFileNames = exports.pathJoin = exports.groupBy = exports.flatMap = void 0; | ||
exports.compareNames = exports.normalize = exports.normalizeFileNames = exports.groupBy = void 0; | ||
const SEPARATOR = '/'; | ||
function flatMap(source, fn) { | ||
const result = []; | ||
source.map(fn).forEach((items) => result.push(...items)); | ||
return result; | ||
} | ||
exports.flatMap = flatMap; | ||
function groupBy(arr, criteria) { | ||
@@ -22,21 +16,18 @@ return arr.reduce((acc, item) => { | ||
exports.groupBy = groupBy; | ||
function pathJoin(...parts) { | ||
return parts.reduce((prev, current) => (prev.length ? (current ? `${prev}/${current}` : prev) : current), ''); | ||
function normalizeFileNames(input) { | ||
return normalize(input, (input) => input); | ||
} | ||
exports.pathJoin = pathJoin; | ||
function normalizeFileNames(input) { | ||
exports.normalizeFileNames = normalizeFileNames; | ||
function normalize(input, factory) { | ||
const fileNames = Object.keys(input); | ||
const commonBasePath = determineCommonBasePath(fileNames); | ||
const output = {}; | ||
const output = Object.create(null); | ||
fileNames.forEach((fileName) => { | ||
output[normalize(fileName.substr(commonBasePath.length))] = input[fileName]; | ||
output[normalizeName(fileName.substr(commonBasePath.length))] = factory(input[fileName]); | ||
}); | ||
return output; | ||
} | ||
exports.normalizeFileNames = normalizeFileNames; | ||
function normalize(fileName) { | ||
return fileName | ||
.split(/\/|\\/) | ||
.filter((pathPart) => pathPart) | ||
.join('/'); | ||
exports.normalize = normalize; | ||
function normalizeName(fileName) { | ||
return fileName.split(/\/|\\/).filter(Boolean).join('/'); | ||
} | ||
@@ -43,0 +34,0 @@ function determineCommonBasePath(fileNames) { |
@@ -1,6 +0,4 @@ | ||
import { MetricsResult } from './api/MetricsResult'; | ||
import { Metrics } from './api/Metrics'; | ||
import { calculateMetrics } from './calculateMetrics'; | ||
import { normalizeFileNames } from './helpers'; | ||
export { MetricsResult, Metrics, calculateMetrics, normalizeFileNames }; | ||
export { calculateMetrics, calculateMutationTestMetrics } from './calculateMetrics'; | ||
export { normalizeFileNames } from './helpers'; | ||
export { MetricsResult, Metrics, TestMetrics, TestModel, FileUnderTestModel, TestFileModel, MutantModel } from './model'; | ||
//# sourceMappingURL=index.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.normalizeFileNames = exports.calculateMetrics = void 0; | ||
const calculateMetrics_1 = require("./calculateMetrics"); | ||
exports.MutantModel = exports.TestFileModel = exports.FileUnderTestModel = exports.TestModel = exports.normalizeFileNames = exports.calculateMutationTestMetrics = exports.calculateMetrics = void 0; | ||
var calculateMetrics_1 = require("./calculateMetrics"); | ||
Object.defineProperty(exports, "calculateMetrics", { enumerable: true, get: function () { return calculateMetrics_1.calculateMetrics; } }); | ||
const helpers_1 = require("./helpers"); | ||
Object.defineProperty(exports, "calculateMutationTestMetrics", { enumerable: true, get: function () { return calculateMetrics_1.calculateMutationTestMetrics; } }); | ||
var helpers_1 = require("./helpers"); | ||
Object.defineProperty(exports, "normalizeFileNames", { enumerable: true, get: function () { return helpers_1.normalizeFileNames; } }); | ||
var model_1 = require("./model"); | ||
Object.defineProperty(exports, "TestModel", { enumerable: true, get: function () { return model_1.TestModel; } }); | ||
Object.defineProperty(exports, "FileUnderTestModel", { enumerable: true, get: function () { return model_1.FileUnderTestModel; } }); | ||
Object.defineProperty(exports, "TestFileModel", { enumerable: true, get: function () { return model_1.TestFileModel; } }); | ||
Object.defineProperty(exports, "MutantModel", { enumerable: true, get: function () { return model_1.MutantModel; } }); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "mutation-testing-metrics", | ||
"version": "1.5.2", | ||
"version": "1.6.0", | ||
"description": "Utility functions to calculate mutation testing metrics.", | ||
@@ -21,5 +21,5 @@ "main": "dist/src/index.js", | ||
"dependencies": { | ||
"mutation-testing-report-schema": "^1.5.2" | ||
"mutation-testing-report-schema": "^1.6.0" | ||
}, | ||
"gitHead": "7995f03f14c8e9e80f090abdf44978b6ba47cf4e" | ||
"gitHead": "242a4e31adc6131c10106b4846b0b66c9254e16c" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41756
28
532
1