UNPKG

testify-universal-cli

Version:

Universal interactive CLI tool for scanning and executing tests across multiple programming languages

216 lines (196 loc) 6.22 kB
import { execa } from 'execa'; import path from 'node:path'; /** * Get a Python test runner * * @param {string} customRunner - Custom test runner * @returns {object} - Python test runner */ export function getPythonRunner(customRunner) { return { /** * Run all tests * * @param {Array<{filePath: string, relativePath: string, markers: string[]}>} testFiles - Test files * @param {string} cwd - Current working directory * @param {string[]} markers - Test markers * @returns {Promise<{stdout: string, failed: boolean}>} - Test results */ async runAll(testFiles, cwd, markers = []) { // Check if pytest is available const hasPytest = await checkCommand('pytest'); if (!hasPytest) { throw new Error('pytest is not installed or not available in PATH'); } let args = ['-v']; // Add markers if provided if (markers.length > 0) { args.push('-m', markers.join(' or ')); } try { // Use platform-specific command execution if (global.pytestCommand && global.pytestCommand.includes(' ')) { // Using python -m pytest on Windows const [cmd, ...cmdArgs] = global.pytestCommand.split(' '); // Combine the command args with our args const fullArgs = [...cmdArgs, ...args]; const { stdout, stderr, exitCode } = await execa(cmd, fullArgs, { cwd, all: true, reject: false, }); return { stdout: stdout || stderr, failed: exitCode !== 0, }; } else { // Regular pytest command const { stdout, stderr, exitCode } = await execa('pytest', args, { cwd, all: true, reject: false, }); return { stdout: stdout || stderr, failed: exitCode !== 0, }; } } catch (error) { return { stdout: error.message, failed: true, }; } }, /** * Run a single test file * * @param {object} testFile - Test file * @param {string} testFile.filePath - Path to test file * @param {string[]} testFile.markers - Test markers * @param {string} cwd - Current working directory * @returns {Promise<{stdout: string, failed: boolean}>} - Test results */ async runFile(testFile, cwd) { // Check if pytest is available const hasPytest = await checkCommand('pytest'); if (!hasPytest) { throw new Error('pytest is not installed or not available in PATH'); } try { // Normalize path for cross-platform compatibility const testPath = path.normalize(testFile.filePath); const fileArgs = [testPath, '-v']; // Use platform-specific command execution if (global.pytestCommand && global.pytestCommand.includes(' ')) { // Using python -m pytest on Windows const [cmd, ...cmdArgs] = global.pytestCommand.split(' '); // Combine the command args with our file args const fullArgs = [...cmdArgs, ...fileArgs]; const { stdout, stderr, exitCode } = await execa(cmd, fullArgs, { cwd, all: true, reject: false, }); return { stdout: stdout || stderr, failed: exitCode !== 0, }; } else { // Regular pytest command const { stdout, stderr, exitCode } = await execa('pytest', fileArgs, { cwd, all: true, reject: false, }); return { stdout: stdout || stderr, failed: exitCode !== 0, }; } } catch (error) { return { stdout: error.message, failed: true, }; } }, }; } /** * Check if a command is available * * @param {string} command - Command to check * @returns {Promise<boolean>} - Whether the command is available */ async function checkCommand(command) { try { // Handle Windows-specific command issues if (process.platform === 'win32') { // On Windows, the command might have a different name // Check common variations for Python commands if (command === 'python' || command === 'python3') { // Try python, python3, and py (Windows Python launcher) try { await execa('python', ['--version']); return true; } catch (e) { try { await execa('py', ['--version']); // If py works, replace the global command for future uses global.pythonCommand = 'py'; return true; } catch (e2) { return false; } } } else if (command === 'pytest') { // Try various ways pytest might be installed on Windows try { await execa('pytest', ['--version']); return true; } catch (e) { try { // Try with python -m pytest const pythonCmd = global.pythonCommand || 'python'; await execa(pythonCmd, ['-m', 'pytest', '--version']); // If this works, update the global pytest command global.pytestCommand = `${pythonCmd} -m pytest`; return true; } catch (e2) { return false; } } } } // Default approach for non-Windows platforms await execa(command, ['--version']); return true; } catch (error) { return false; } } /** * Get all available pytest markers * * @param {string} cwd - Current working directory * @returns {Promise<string[]>} - Available markers */ export async function getPytestMarkers(cwd) { try { const { stdout } = await execa('pytest', ['--markers'], { cwd, reject: false, }); // Parse markers from output const markers = []; const markerRegex = /@pytest\.mark\.([a-zA-Z0-9_]+)/g; let match; while ((match = markerRegex.exec(stdout)) !== null) { markers.push(match[1]); } return markers; } catch (error) { return []; } }