Skip to main content
Glama
test-assessment-generation.js19.2 kB
/** * Assessment Generation System Tests * @description Comprehensive test suite for assessment generation components * @version 5.0.0-alpha */ import { AssessmentEngine, FlashcardGenerator, QuizGenerator, AnswerRandomizer, ComplexityAdapter, QualityValidator, createAssessmentEngine, generateComprehensiveAssessment } from '../../src/content-generation/index.js'; // Test data const mockTopicAnalysis = { subject: 'física', gradeLevel: 'medio', complexity: 'medium', keywords: ['força', 'movimento', 'energia', 'velocidade'], concepts: ['dinâmica', 'cinemática', 'energia cinética', 'leis de Newton'], learningObjectives: [ 'Compreender as leis de Newton', 'Aplicar conceitos de força e movimento', 'Resolver problemas de dinâmica' ] }; const mockContent = { metadata: { topic: 'Leis de Newton e Dinâmica', subject: 'física', gradeLevel: 'medio', complexity: 'medium' }, components: { introduction: { type: 'introduction', title: 'Introdução à Dinâmica', content: 'A dinâmica é o ramo da física que estuda as causas do movimento dos corpos.' }, explanation: { type: 'explanation', title: 'Leis de Newton', content: 'Sir Isaac Newton formulou três leis fundamentais que descrevem a relação entre as forças que atuam sobre um corpo e seu movimento. A primeira lei estabelece o conceito de inércia, a segunda relaciona força com aceleração, e a terceira trata da ação e reação.' }, examples: { type: 'examples', title: 'Exemplos Práticos', examples: [ 'Um carro freando demonstra a primeira lei de Newton', 'Empurrar um objeto aplica a segunda lei de Newton', 'Caminhar ilustra a terceira lei de Newton' ] }, summary: { type: 'summary', title: 'Resumo', content: 'As leis de Newton são fundamentais para compreender o movimento e as forças na física clássica.' } } }; // Test suite export async function runAssessmentGenerationTests() { console.log('\n🧪 Starting Assessment Generation System Tests'); console.log('='.repeat(60)); const results = { total: 0, passed: 0, failed: 0, errors: [] }; const tests = [ // Core component tests { name: 'FlashcardGenerator - Basic Generation', test: testFlashcardGeneratorBasic }, { name: 'FlashcardGenerator - Type Variety', test: testFlashcardGeneratorTypeVariety }, { name: 'FlashcardGenerator - Content Quality', test: testFlashcardGeneratorQuality }, { name: 'QuizGenerator - Basic Generation', test: testQuizGeneratorBasic }, { name: 'QuizGenerator - Question Types', test: testQuizGeneratorTypes }, { name: 'QuizGenerator - Difficulty Balance', test: testQuizGeneratorDifficulty }, { name: 'AnswerRandomizer - Multiple Choice', test: testAnswerRandomizerMC }, { name: 'AnswerRandomizer - Position Distribution', test: testAnswerRandomizerDistribution }, { name: 'AnswerRandomizer - Matching Questions', test: testAnswerRandomizerMatching }, { name: 'ComplexityAdapter - Grade Level Adaptation', test: testComplexityAdapterGradeLevels }, { name: 'ComplexityAdapter - Vocabulary Adaptation', test: testComplexityAdapterVocabulary }, { name: 'ComplexityAdapter - Question Filtering', test: testComplexityAdapterFiltering }, { name: 'QualityValidator - Flashcard Validation', test: testQualityValidatorFlashcards }, { name: 'QualityValidator - Quiz Validation', test: testQualityValidatorQuiz }, { name: 'QualityValidator - Auto Correction', test: testQualityValidatorCorrection }, { name: 'AssessmentEngine - Complete Generation', test: testAssessmentEngineComplete }, { name: 'AssessmentEngine - Subject Enhancement', test: testAssessmentEngineSubjectEnhancement }, { name: 'AssessmentEngine - Integration Pipeline', test: testAssessmentEngineIntegration }, // Factory and convenience function tests { name: 'Factory Functions - Assessment Creation', test: testFactoryFunctions }, { name: 'Convenience Functions - Comprehensive Assessment', test: testConvenienceFunctions }, // Integration tests { name: 'Integration - Full Assessment Pipeline', test: testFullAssessmentPipeline }, { name: 'Integration - Error Handling', test: testErrorHandling }, { name: 'Integration - Performance', test: testPerformance } ]; for (const { name, test } of tests) { results.total++; try { console.log(`\n⏳ Running: ${name}`); const startTime = Date.now(); await test(); const duration = Date.now() - startTime; console.log(`✅ PASSED: ${name} (${duration}ms)`); results.passed++; } catch (error) { console.log(`❌ FAILED: ${name}`); console.log(` Error: ${error.message}`); results.failed++; results.errors.push({ test: name, error: error.message }); } } // Print test summary console.log('\n' + '='.repeat(60)); console.log('📊 Assessment Generation Test Results'); console.log('='.repeat(60)); console.log(`Total Tests: ${results.total}`); console.log(`✅ Passed: ${results.passed}`); console.log(`❌ Failed: ${results.failed}`); console.log(`📈 Success Rate: ${((results.passed / results.total) * 100).toFixed(1)}%`); if (results.errors.length > 0) { console.log('\n❌ Failed Tests:'); results.errors.forEach(({ test, error }) => { console.log(` - ${test}: ${error}`); }); } return results; } // FlashcardGenerator Tests async function testFlashcardGeneratorBasic() { const generator = new FlashcardGenerator(); const flashcards = await generator.generateFlashcards(mockContent, mockTopicAnalysis); if (!Array.isArray(flashcards)) { throw new Error('Flashcards should be an array'); } if (flashcards.length < 5) { throw new Error('Should generate at least 5 flashcards'); } const firstCard = flashcards[0]; if (!firstCard.front || !firstCard.back || !firstCard.type) { throw new Error('Flashcards should have front, back, and type properties'); } } async function testFlashcardGeneratorTypeVariety() { const generator = new FlashcardGenerator(); const flashcards = await generator.generateFlashcards(mockContent, mockTopicAnalysis); const types = new Set(flashcards.map(card => card.type)); if (types.size < 2) { throw new Error('Should generate multiple flashcard types'); } } async function testFlashcardGeneratorQuality() { const generator = new FlashcardGenerator(); const flashcards = await generator.generateFlashcards(mockContent, mockTopicAnalysis); // Check content quality for (const card of flashcards) { if (card.front.length < 5 || card.back.length < 10) { throw new Error('Flashcard content too short'); } if (!card.difficulty || !card.tags) { throw new Error('Flashcards should have difficulty and tags'); } } // Check statistics const stats = generator.calculateStatistics(flashcards); if (stats.qualityScore < 70) { throw new Error('Flashcard quality score too low'); } } // QuizGenerator Tests async function testQuizGeneratorBasic() { const generator = new QuizGenerator(); const quiz = await generator.generateQuiz(mockContent, mockTopicAnalysis); if (!quiz.questions || !Array.isArray(quiz.questions)) { throw new Error('Quiz should have questions array'); } if (quiz.questions.length < 3) { throw new Error('Should generate at least 3 questions'); } if (!quiz.metadata || !quiz.instructions) { throw new Error('Quiz should have metadata and instructions'); } } async function testQuizGeneratorTypes() { const generator = new QuizGenerator(); const quiz = await generator.generateQuiz(mockContent, mockTopicAnalysis); const types = new Set(quiz.questions.map(q => q.type)); if (types.size < 2) { throw new Error('Should generate multiple question types'); } // Check specific question types const mcQuestions = quiz.questions.filter(q => q.type === 'multiple_choice'); if (mcQuestions.length === 0) { throw new Error('Should generate multiple choice questions'); } const mcQuestion = mcQuestions[0]; if (!mcQuestion.options || mcQuestion.options.length < 2) { throw new Error('Multiple choice questions should have options'); } } async function testQuizGeneratorDifficulty() { const generator = new QuizGenerator(); const quiz = await generator.generateQuiz(mockContent, mockTopicAnalysis); const difficulties = new Set(quiz.questions.map(q => q.difficulty)); if (difficulties.size < 2) { throw new Error('Should generate questions with varied difficulty'); } } // AnswerRandomizer Tests async function testAnswerRandomizerMC() { const randomizer = new AnswerRandomizer(); const question = { type: 'multiple_choice', question: 'Test question?', options: ['A', 'B', 'C', 'D'], correct: 0 }; const randomized = await randomizer.randomizeQuestion(question); if (!randomized.randomization) { throw new Error('Randomized question should have randomization metadata'); } if (randomized.options[randomized.correct] !== 'A') { throw new Error('Correct answer should still be correct after randomization'); } } async function testAnswerRandomizerDistribution() { const randomizer = new AnswerRandomizer(); // Generate multiple randomized questions const questions = []; for (let i = 0; i < 20; i++) { const question = { type: 'multiple_choice', question: `Test question ${i}?`, options: ['A', 'B', 'C', 'D'], correct: 0 }; questions.push(question); } const assessment = { quiz: { questions } }; const randomized = await randomizer.randomizeAssessment(assessment); // Check position distribution const positions = randomized.quiz.questions.map(q => q.correct); const uniquePositions = new Set(positions); if (uniquePositions.size < 2) { throw new Error('Answer positions should be distributed'); } } async function testAnswerRandomizerMatching() { const randomizer = new AnswerRandomizer(); const question = { type: 'matching', leftColumn: ['A', 'B', 'C'], rightColumn: ['1', '2', '3'], correctPairs: [ { left: 0, right: 0 }, { left: 1, right: 1 }, { left: 2, right: 2 } ] }; const randomized = await randomizer.randomizeQuestion(question); if (!randomized.randomization) { throw new Error('Matching question should have randomization metadata'); } // Verify correct pairs are still valid for (const pair of randomized.correctPairs) { const leftItem = randomized.leftColumn[pair.left]; const rightItem = randomized.rightColumn[pair.right]; // Basic validation that pairing makes sense if (!leftItem || !rightItem) { throw new Error('Invalid correct pair after randomization'); } } } // ComplexityAdapter Tests async function testComplexityAdapterGradeLevels() { const adapter = new ComplexityAdapter(); const assessment = { flashcards: [ { front: 'Complex terminology test', back: 'Advanced explanation', difficulty: 'hard' } ], quiz: { questions: [ { type: 'multiple_choice', question: 'Complex question with advanced terminology?', options: ['A', 'B', 'C', 'D'], correct: 0, difficulty: 'hard' } ] } }; const adapted = await adapter.adaptAssessment(assessment, 'fundamental-1'); if (!adapted.metadata || adapted.metadata.adaptedGradeLevel !== 'fundamental-1') { throw new Error('Assessment should be adapted for fundamental-1 level'); } } async function testComplexityAdapterVocabulary() { const adapter = new ComplexityAdapter(); const text = 'Compreender o conceito fundamental é significativo para a metodologia.'; const simplified = adapter.adaptVocabulary(text, 'simple'); if (simplified.includes('compreender') || simplified.includes('metodologia')) { throw new Error('Complex vocabulary should be simplified'); } } async function testComplexityAdapterFiltering() { const adapter = new ComplexityAdapter(); const questions = [ { type: 'multiple_choice', category: 'knowledge', difficulty: 'easy' }, { type: 'short_answer', category: 'evaluation', difficulty: 'hard' } ]; const adapted = await adapter.adaptQuestions(questions, 'fundamental-1'); // Should filter out evaluation questions for fundamental level const evaluationQuestions = adapted.filter(q => q.category === 'evaluation'); if (evaluationQuestions.length > 0) { throw new Error('High-level questions should be filtered for lower grade levels'); } } // QualityValidator Tests async function testQualityValidatorFlashcards() { const validator = new QualityValidator(); const flashcards = [ { front: 'What is X?', back: 'X is...', type: 'concept', difficulty: 'easy' }, { front: 'Example of Y?', back: 'Y examples include...', type: 'example', difficulty: 'medium' } ]; const validation = await validator.validateFlashcards(flashcards); if (validation.score < 0 || validation.score > 100) { throw new Error('Validation score should be between 0-100'); } if (!Array.isArray(validation.issues)) { throw new Error('Validation should return issues array'); } } async function testQualityValidatorQuiz() { const validator = new QualityValidator(); const quiz = { questions: [ { type: 'multiple_choice', question: 'Test question?', options: ['A', 'B', 'C', 'D'], correct: 0, difficulty: 'medium' } ] }; const validation = await validator.validateQuiz(quiz); if (validation.score < 0 || validation.score > 100) { throw new Error('Quiz validation score should be between 0-100'); } } async function testQualityValidatorCorrection() { const validator = new QualityValidator({ enableAutoCorrection: true }); // Create assessment with insufficient content const poorAssessment = { flashcards: [ { front: 'Q1', back: 'A1', type: 'concept', difficulty: 'easy' } ], // Too few flashcards quiz: { questions: [ { type: 'multiple_choice', question: 'Q?', options: ['A', 'B'], correct: 0, difficulty: 'medium' } ] } }; const validated = await validator.validateAssessment(poorAssessment); if (!validated.validation) { throw new Error('Validated assessment should have validation metadata'); } // Should have more flashcards after correction if (validated.flashcards.length <= poorAssessment.flashcards.length) { throw new Error('Auto-correction should add content when insufficient'); } } // AssessmentEngine Tests async function testAssessmentEngineComplete() { const engine = new AssessmentEngine(); const assessment = await engine.generateAssessment(mockContent, mockTopicAnalysis); if (!assessment.flashcards || !assessment.quiz) { throw new Error('Assessment should have flashcards and quiz'); } if (!assessment.metadata) { throw new Error('Assessment should have metadata'); } if (assessment.flashcards.length === 0 || assessment.quiz.questions.length === 0) { throw new Error('Assessment should have content'); } } async function testAssessmentEngineSubjectEnhancement() { const engine = new AssessmentEngine(); const assessment = await engine.generateSubjectSpecificAssessment( mockContent, mockTopicAnalysis, 'physics' ); if (!assessment.metadata.subjectEnhancements) { throw new Error('Physics assessment should have subject enhancements'); } } async function testAssessmentEngineIntegration() { const engine = new AssessmentEngine(); // Test the full pipeline const assessment = await engine.generateAssessment(mockContent, mockTopicAnalysis, { includeFlashcards: true, includeQuiz: true, gradeLevel: 'medio' }); // Check randomization was applied if (!assessment.analytics || !assessment.analytics.randomizationApplied) { throw new Error('Assessment should show randomization was applied'); } // Check quality validation if (!assessment.validation || !assessment.validation.qualityScore) { throw new Error('Assessment should have quality validation'); } } // Factory Function Tests async function testFactoryFunctions() { const engine = await createAssessmentEngine({ minFlashcards: 5 }); if (!engine || typeof engine.generateAssessment !== 'function') { throw new Error('Factory should create functional AssessmentEngine'); } } async function testConvenienceFunctions() { const assessment = await generateComprehensiveAssessment( mockContent, mockTopicAnalysis, { includeFlashcards: true } ); if (!assessment.flashcards || !assessment.quiz) { throw new Error('Convenience function should generate complete assessment'); } } // Integration Tests async function testFullAssessmentPipeline() { // Test the complete pipeline from content to validated assessment const engine = new AssessmentEngine({ enableRandomization: true, qualityThreshold: 0.7 }); const assessment = await engine.generateAssessment(mockContent, mockTopicAnalysis, { includeFlashcards: true, includeQuiz: true, gradeLevel: 'medio' }); // Verify all pipeline steps were executed if (!assessment.flashcards || assessment.flashcards.length === 0) { throw new Error('Pipeline should generate flashcards'); } if (!assessment.quiz || !assessment.quiz.questions || assessment.quiz.questions.length === 0) { throw new Error('Pipeline should generate quiz questions'); } if (!assessment.validation || !assessment.validation.qualityScore) { throw new Error('Pipeline should include quality validation'); } if (!assessment.analytics || !assessment.analytics.randomizationApplied) { throw new Error('Pipeline should include randomization'); } } async function testErrorHandling() { const engine = new AssessmentEngine(); try { // Test with invalid input await engine.generateAssessment(null, null); throw new Error('Should throw error with invalid input'); } catch (error) { if (!error.message.includes('failed')) { throw new Error('Should throw descriptive error message'); } } } async function testPerformance() { const engine = new AssessmentEngine(); const startTime = Date.now(); const assessment = await engine.generateAssessment(mockContent, mockTopicAnalysis); const duration = Date.now() - startTime; if (duration > 5000) { // 5 seconds throw new Error(`Assessment generation too slow: ${duration}ms`); } if (!assessment.flashcards || !assessment.quiz) { throw new Error('Performance test should still generate complete assessment'); } } // Export test runner for integration with main test suite export { runAssessmentGenerationTests };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkm097git/euconquisto-composer-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server