Skip to main content
Glama
YUChoe

SQLite MCP Server

by YUChoe
getSchema.test.ts8.59 kB
/** * 스키마 정보 조회 도구 테스트 * **Feature: sqlite-mcp-server, Property 8: 스키마 정보 정확성** * **Validates: Requirements 6.1, 6.2** */ import { describe, test, expect, beforeEach, afterEach } from '@jest/globals'; import * as fc from 'fast-check'; import * as fs from 'fs'; import * as path from 'path'; import { getSchemaTool } from './getSchema'; import { createTableTool } from './createTable'; import { DatabaseManager } from '../database/DatabaseManager'; describe('Get Schema Tool Tests', () => { let testDbPath: string; let dbManager: DatabaseManager; beforeEach(() => { // 테스트용 임시 데이터베이스 파일 경로 생성 testDbPath = path.join(__dirname, '../../test-dbs', `test-schema-${Date.now()}.db`); // 테스트 디렉토리 생성 const testDir = path.dirname(testDbPath); if (!fs.existsSync(testDir)) { fs.mkdirSync(testDir, { recursive: true }); } dbManager = new DatabaseManager(); }); afterEach(() => { // 테스트 후 정리 try { dbManager.closeDatabase(testDbPath); if (fs.existsSync(testDbPath)) { fs.unlinkSync(testDbPath); } } catch (error) { // 정리 중 오류는 무시 } }); test('**Feature: sqlite-mcp-server, Property 8: 스키마 정보 정확성**', async () => { await fc.assert( fc.asyncProperty( // 테이블 정의 생성기 fc.array( fc.record({ tableName: fc.string({ minLength: 1, maxLength: 20 }) .filter(s => /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(s)), columns: fc.array( fc.record({ name: fc.string({ minLength: 1, maxLength: 20 }) .filter(s => /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(s)), type: fc.constantFrom('INTEGER', 'TEXT', 'REAL', 'BLOB'), constraints: fc.option( fc.constantFrom('PRIMARY KEY', 'NOT NULL', 'UNIQUE'), { freq: 3 } ) }), { minLength: 1, maxLength: 5 } ) }), { minLength: 1, maxLength: 3 } ), async (tableDefinitions) => { try { // 중복 테이블명 제거 const uniqueTableDefs = tableDefinitions.filter((def, index, arr) => arr.findIndex(d => d.tableName === def.tableName) === index ); if (uniqueTableDefs.length === 0) return; const createdTables: string[] = []; // 1. 테이블들 생성 for (const tableDef of uniqueTableDefs) { // 중복 컬럼명 제거 const uniqueColumns = tableDef.columns.filter((col, index, arr) => arr.findIndex(c => c.name === col.name) === index ); if (uniqueColumns.length === 0) continue; const createResult = await (createTableTool.handler as any)({ dbPath: testDbPath, tableName: tableDef.tableName, columns: uniqueColumns }); const createResponse = createResult.structuredContent || { success: false }; if (createResponse.success) { createdTables.push(tableDef.tableName); } } if (createdTables.length === 0) return; // 2. 전체 테이블 목록 조회 테스트 const allTablesResult = await (getSchemaTool.handler as any)({ dbPath: testDbPath }); const allTablesResponse = allTablesResult.structuredContent || JSON.parse(allTablesResult.content[0].text); // Property 8: 스키마 정보 정확성 검증 - 테이블 목록 expect(allTablesResponse.success).toBe(true); expect(allTablesResponse).toHaveProperty('tables'); expect(Array.isArray(allTablesResponse.tables)).toBe(true); // 생성된 모든 테이블이 목록에 포함되어야 함 for (const tableName of createdTables) { expect(allTablesResponse.tables).toContain(tableName); } // 3. 각 테이블의 스키마 정보 조회 테스트 for (let i = 0; i < Math.min(createdTables.length, 2); i++) { const tableName = createdTables[i]; const originalTableDef = uniqueTableDefs.find(def => def.tableName === tableName); if (!originalTableDef) continue; const schemaResult = await (getSchemaTool.handler as any)({ dbPath: testDbPath, tableName }); const schemaResponse = schemaResult.structuredContent || JSON.parse(schemaResult.content[0].text); // Property 8: 스키마 정보 정확성 검증 - 특정 테이블 스키마 expect(schemaResponse.success).toBe(true); expect(schemaResponse).toHaveProperty('columns'); expect(Array.isArray(schemaResponse.columns)).toBe(true); expect(schemaResponse).toHaveProperty('schema'); expect(typeof schemaResponse.schema).toBe('string'); // 컬럼 정보 검증 const uniqueColumns = originalTableDef.columns.filter((col, index, arr) => arr.findIndex(c => c.name === col.name) === index ); expect(schemaResponse.columns.length).toBe(uniqueColumns.length); // 각 컬럼이 올바르게 반환되는지 확인 for (const originalCol of uniqueColumns) { const returnedCol = schemaResponse.columns.find( (col: any) => col.name === originalCol.name ); expect(returnedCol).toBeDefined(); expect(returnedCol.type).toBe(originalCol.type); expect(typeof returnedCol.notnull).toBe('boolean'); expect(typeof returnedCol.pk).toBe('boolean'); } // DDL 스키마에 테이블명이 포함되어야 함 expect(schemaResponse.schema.toLowerCase()).toContain(tableName.toLowerCase()); } } catch (error) { // 예상치 못한 오류가 발생한 경우 실패 throw new Error(`Property test failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } ), { numRuns: 100 } ); }); test('존재하지 않는 테이블 스키마 조회 시 오류 반환', async () => { const result = await (getSchemaTool.handler as any)({ dbPath: testDbPath, tableName: 'nonexistent_table' }); const response = result.structuredContent || JSON.parse(result.content[0].text); expect(response.success).toBe(false); expect(response.error).toContain('존재하지 않습니다'); }); test('빈 데이터베이스의 테이블 목록 조회', async () => { const result = await (getSchemaTool.handler as any)({ dbPath: testDbPath }); const response = result.structuredContent || JSON.parse(result.content[0].text); expect(response.success).toBe(true); expect(response.tables).toEqual([]); }); test('특정 테이블의 상세 스키마 정보 조회', async () => { // 테스트 테이블 생성 await (createTableTool.handler as any)({ dbPath: testDbPath, tableName: 'test_table', columns: [ { name: 'id', type: 'INTEGER', constraints: 'PRIMARY KEY' }, { name: 'name', type: 'TEXT', constraints: 'NOT NULL' }, { name: 'age', type: 'INTEGER' } ] }); const result = await (getSchemaTool.handler as any)({ dbPath: testDbPath, tableName: 'test_table' }); const response = result.structuredContent || JSON.parse(result.content[0].text); expect(response.success).toBe(true); expect(response.columns).toHaveLength(3); // ID 컬럼이 PRIMARY KEY인지 확인 const idColumn = response.columns.find((col: any) => col.name === 'id'); expect(idColumn).toBeDefined(); expect(idColumn.pk).toBe(true); // NAME 컬럼이 NOT NULL인지 확인 const nameColumn = response.columns.find((col: any) => col.name === 'name'); expect(nameColumn).toBeDefined(); expect(nameColumn.notnull).toBe(true); }); });

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/YUChoe/sqlite-mcp'

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