mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 22:56:42 +02:00
✅ test: implement comprehensive automated testing system with daily CI/CD
Implement rock-solid automated testing infrastructure for mana-core-auth with daily execution, notifications, and comprehensive monitoring. Test Suite Improvements: - Fix all 36 failing BetterAuthService tests (missing service mocks) - Add 21 JwtAuthGuard tests achieving 100% statement coverage - Create silentError helper to suppress intentional error logs - Fix Todo backend TaskService test structure - Add jose mock for JWT testing - Configure jest collectCoverageFrom for mana-core-auth GitHub Actions Workflow: - Daily automated test execution (2 AM UTC + manual trigger) - Matrix parallelization across 6 backend services - PostgreSQL and Redis service containers - Coverage enforcement (80% threshold) - Multi-channel notifications (Discord, Slack, GitHub Issues) - Support for success notifications (opt-in) Test Infrastructure: - Coverage aggregation across multiple services - Flaky test detection with 30-run history tracking - Performance metrics tracking with regression detection - Test data seeding and cleanup scripts - Comprehensive test reporting with formatted metrics Documentation: - TESTING_GUIDE.md (4000+ words) - Complete testing documentation - AUTOMATED_TESTING_SYSTEM.md - System architecture and workflows - DISCORD_NOTIFICATIONS_SETUP.md - Discord webhook setup guide - TESTING_DEPLOYMENT_CHECKLIST.md - Pre-deployment verification - TESTING_QUICK_REFERENCE.md - Quick command reference Final Result: - 180/180 tests passing (100% pass rate) - Zero console errors in test output - Automated daily testing with rich notifications - Production-ready test infrastructure
This commit is contained in:
parent
9dbd6e6c09
commit
304897261d
24 changed files with 5017 additions and 16 deletions
130
scripts/test-reporting/generate-summary.js
Normal file
130
scripts/test-reporting/generate-summary.js
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#!/usr/bin/env node
|
||||
/* eslint-disable @typescript-eslint/no-require-imports, no-console */
|
||||
/**
|
||||
* Generate Test Summary
|
||||
*
|
||||
* Creates a GitHub Actions summary with test results, coverage, and trends.
|
||||
*
|
||||
* Usage:
|
||||
* node generate-summary.js <test-results-dir>
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function findTestResults(dir) {
|
||||
const results = {
|
||||
coverage: [],
|
||||
testResults: [],
|
||||
};
|
||||
|
||||
function walk(currentDir) {
|
||||
if (!fs.existsSync(currentDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(currentDir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
walk(fullPath);
|
||||
} else if (entry.name === 'coverage-summary.json') {
|
||||
results.coverage.push(fullPath);
|
||||
} else if (entry.name.includes('test-results.json')) {
|
||||
results.testResults.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(dir);
|
||||
return results;
|
||||
}
|
||||
|
||||
function generateSummary(resultsDir) {
|
||||
const { coverage } = findTestResults(resultsDir);
|
||||
|
||||
let summary = '# 🧪 Daily Test Suite Results\n\n';
|
||||
summary += `**Date:** ${new Date().toISOString().split('T')[0]}\n\n`;
|
||||
|
||||
if (coverage.length === 0) {
|
||||
summary += '⚠️ No coverage reports found.\n';
|
||||
return summary;
|
||||
}
|
||||
|
||||
// Aggregate coverage stats
|
||||
const suites = [];
|
||||
let totalPassed = 0;
|
||||
let totalFailed = 0;
|
||||
|
||||
coverage.forEach((file) => {
|
||||
const content = JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
const suiteName = path.basename(path.dirname(path.dirname(file)));
|
||||
|
||||
if (content.total) {
|
||||
suites.push({
|
||||
name: suiteName,
|
||||
lines: content.total.lines.pct,
|
||||
statements: content.total.statements.pct,
|
||||
functions: content.total.functions.pct,
|
||||
branches: content.total.branches.pct,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Coverage table
|
||||
summary += '## Coverage by Suite\n\n';
|
||||
summary += '| Suite | Lines | Statements | Functions | Branches | Status |\n';
|
||||
summary += '|-------|-------|------------|-----------|----------|--------|\n';
|
||||
|
||||
suites.forEach((suite) => {
|
||||
const avgCoverage = (suite.lines + suite.statements + suite.functions + suite.branches) / 4;
|
||||
const status = avgCoverage >= 80 ? '✅ Pass' : avgCoverage >= 60 ? '⚠️ Warning' : '❌ Fail';
|
||||
|
||||
summary += `| ${suite.name} | ${suite.lines.toFixed(1)}% | ${suite.statements.toFixed(1)}% | ${suite.functions.toFixed(1)}% | ${suite.branches.toFixed(1)}% | ${status} |\n`;
|
||||
|
||||
if (avgCoverage >= 80) {
|
||||
totalPassed++;
|
||||
} else {
|
||||
totalFailed++;
|
||||
}
|
||||
});
|
||||
|
||||
// Overall stats
|
||||
summary += '\n## Overall Statistics\n\n';
|
||||
summary += `- **Total Test Suites:** ${suites.length}\n`;
|
||||
summary += `- **Passed:** ${totalPassed} ✅\n`;
|
||||
summary += `- **Failed:** ${totalFailed} ❌\n`;
|
||||
|
||||
const successRate = ((totalPassed / suites.length) * 100).toFixed(1);
|
||||
summary += `- **Success Rate:** ${successRate}%\n`;
|
||||
|
||||
// Recommendations
|
||||
if (totalFailed > 0) {
|
||||
summary += '\n## ⚠️ Recommendations\n\n';
|
||||
summary += 'The following test suites need attention:\n\n';
|
||||
|
||||
suites
|
||||
.filter((s) => (s.lines + s.statements + s.functions + s.branches) / 4 < 80)
|
||||
.forEach((suite) => {
|
||||
summary += `- **${suite.name}**: Improve coverage (currently ${((suite.lines + suite.statements + suite.functions + suite.branches) / 4).toFixed(1)}%)\n`;
|
||||
});
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const resultsDir = process.argv[2];
|
||||
|
||||
if (!resultsDir) {
|
||||
console.error('Usage: node generate-summary.js <test-results-dir>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const summary = generateSummary(resultsDir);
|
||||
console.log(summary);
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue