Files
bitvid/scripts/static-test-analysis.mjs
T
google-labs-jules[bot]andPR0M3TH3AN 661a51084e feat(test-audit): Add daily test integrity and coverage audit workflow
- Adds `scripts/run-test-audit.sh` to automate unit test execution with coverage.
- Adds `scripts/analyze-flakiness.mjs` to detect test flakiness.
- Adds `scripts/static-test-analysis.mjs` to find suspicious test patterns.
- Adds `scripts/coverage-gap-analysis.mjs` to identify critical coverage gaps.
- Adds `scripts/generate-audit-report.mjs` to produce markdown reports.
- Generates initial audit report `test-audit-report-2025-02-18.md` and `issues/ISSUE_test_audit_findings.md`.
- Documents findings in `decisions/DECISIONS_2025-02-18.md`.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-18 20:17:01 +00:00

79 lines
2.2 KiB
JavaScript

import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const rootDir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const testsDir = path.join(rootDir, 'tests');
const outputFile = path.join(rootDir, 'test-audit', 'suspicious-tests.json');
const checks = {
zeroAssertions: {
pattern: /(expect\(|assert\.|t\.is|chai\.expect|should\.)/g,
inverse: true,
message: 'No assertions found'
},
focusedOrSkipped: {
pattern: /\.(only|skip)\(/g,
message: 'Focused or skipped test'
},
timeDependence: {
pattern: /(setTimeout|setInterval|sleep|delay)\(/g,
message: 'Time dependence (sleep/timeout)'
},
networkDependence: {
pattern: /(fetch|axios\.|new WebSocket|WebSocket\()/g,
message: 'Network dependence (fetch/WebSocket)'
},
consoleUsage: {
pattern: /console\.(log|warn|error)/g,
message: 'Console usage'
}
};
async function scanFile(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const fileIssues = [];
for (const [key, check] of Object.entries(checks)) {
const matches = content.match(check.pattern);
if (check.inverse) {
if (!matches) {
fileIssues.push(check.message);
}
} else {
if (matches) {
fileIssues.push(`${check.message} (${matches.length} occurrences)`);
}
}
}
return fileIssues;
}
async function walk(dir) {
let results = {};
const list = fs.readdirSync(dir);
for (const file of list) {
if (file === 'node_modules' || file === 'visual' || file === 'e2e') continue;
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat && stat.isDirectory()) {
Object.assign(results, await walk(filePath));
} else if (file.endsWith('.test.mjs') || file.endsWith('.test.js')) {
const issues = await scanFile(filePath);
if (issues.length > 0) {
results[path.relative(rootDir, filePath)] = issues;
}
}
}
return results;
}
async function main() {
console.log('Scanning tests for suspicious patterns...');
const suspiciousTests = await walk(testsDir);
fs.writeFileSync(outputFile, JSON.stringify(suspiciousTests, null, 2));
console.log(`Wrote suspicious tests to ${outputFile}`);
}
main();