mirror of
https://github.com/codeflash-ai/codeflash.git
synced 2026-05-04 18:25:17 +00:00
add vitest runner
This commit is contained in:
parent
c56002f287
commit
4bf664dc39
13 changed files with 7838 additions and 137 deletions
|
|
@ -14,15 +14,13 @@
|
|||
}
|
||||
},
|
||||
"../../../packages/codeflash": {
|
||||
"version": "0.1.0",
|
||||
"version": "0.3.1",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^3.0.0",
|
||||
"better-sqlite3": "^12.0.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-runner": "^29.7.0"
|
||||
"better-sqlite3": "^12.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"codeflash": "bin/codeflash.js",
|
||||
|
|
@ -33,7 +31,8 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"jest": ">=27.0.0",
|
||||
"jest-runner": ">=27.0.0"
|
||||
"jest-runner": ">=27.0.0",
|
||||
"vitest": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"jest": {
|
||||
|
|
@ -41,6 +40,9 @@
|
|||
},
|
||||
"jest-runner": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,15 +14,13 @@
|
|||
}
|
||||
},
|
||||
"../../../packages/codeflash": {
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.1",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^3.0.0",
|
||||
"better-sqlite3": "^12.0.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-runner": "^29.7.0"
|
||||
"better-sqlite3": "^12.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"codeflash": "bin/codeflash.js",
|
||||
|
|
@ -33,7 +31,8 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"jest": ">=27.0.0",
|
||||
"jest-runner": ">=27.0.0"
|
||||
"jest-runner": ">=27.0.0",
|
||||
"vitest": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"jest": {
|
||||
|
|
@ -41,6 +40,9 @@
|
|||
},
|
||||
"jest-runner": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
7409
code_to_optimize/js/code_to_optimize_js_esm/package-lock.json
generated
Normal file
7409
code_to_optimize/js/code_to_optimize_js_esm/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -20,7 +20,7 @@
|
|||
}
|
||||
},
|
||||
"../../../packages/codeflash": {
|
||||
"version": "0.1.0",
|
||||
"version": "0.3.1",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
|
|
@ -36,11 +36,19 @@
|
|||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jest": ">=27.0.0"
|
||||
"jest": ">=27.0.0",
|
||||
"jest-runner": ">=27.0.0",
|
||||
"vitest": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"jest": {
|
||||
"optional": true
|
||||
},
|
||||
"jest-runner": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,15 +15,13 @@
|
|||
}
|
||||
},
|
||||
"../../../packages/codeflash": {
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^3.0.0",
|
||||
"better-sqlite3": "^12.0.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-runner": "^29.7.0"
|
||||
"better-sqlite3": "^12.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"codeflash": "bin/codeflash.js",
|
||||
|
|
@ -34,7 +32,8 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"jest": ">=27.0.0",
|
||||
"jest-runner": ">=27.0.0"
|
||||
"jest-runner": ">=27.0.0",
|
||||
"vitest": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"jest": {
|
||||
|
|
@ -42,6 +41,9 @@
|
|||
},
|
||||
"jest-runner": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from codeflash.cli_cmds.extension import install_vscode_extension
|
|||
from codeflash.code_utils import env_utils
|
||||
from codeflash.code_utils.code_utils import exit_with_message
|
||||
from codeflash.code_utils.config_parser import parse_config_file
|
||||
from codeflash.languages.test_framework import set_current_test_framework
|
||||
from codeflash.lsp.helpers import is_LSP_enabled
|
||||
from codeflash.version import __version__ as version
|
||||
|
||||
|
|
@ -210,6 +211,11 @@ def process_pyproject_config(args: Namespace) -> Namespace:
|
|||
# For JS/TS projects, tests_root is optional (Jest auto-discovers tests)
|
||||
# Default to module_root if not specified
|
||||
is_js_ts_project = pyproject_config.get("language") in ("javascript", "typescript")
|
||||
|
||||
# Set the test framework singleton for JS/TS projects
|
||||
if is_js_ts_project and pyproject_config.get("test_runner"):
|
||||
set_current_test_framework(pyproject_config["test_runner"])
|
||||
|
||||
if args.tests_root is None:
|
||||
if is_js_ts_project:
|
||||
# Try common JS test directories, or default to module_root
|
||||
|
|
|
|||
|
|
@ -48,9 +48,19 @@ from codeflash.languages.registry import (
|
|||
get_supported_languages,
|
||||
register_language,
|
||||
)
|
||||
from codeflash.languages.test_framework import (
|
||||
current_test_framework,
|
||||
get_js_test_framework_or_default,
|
||||
is_jest,
|
||||
is_mocha,
|
||||
is_pytest,
|
||||
is_unittest,
|
||||
is_vitest,
|
||||
reset_test_framework,
|
||||
set_current_test_framework,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Base types
|
||||
"CodeContext",
|
||||
"FunctionInfo",
|
||||
"HelperFunction",
|
||||
|
|
@ -59,18 +69,25 @@ __all__ = [
|
|||
"ParentInfo",
|
||||
"TestInfo",
|
||||
"TestResult",
|
||||
# Current language singleton
|
||||
"current_language",
|
||||
"current_language_support",
|
||||
# Registry functions
|
||||
"current_test_framework",
|
||||
"detect_project_language",
|
||||
"get_js_test_framework_or_default",
|
||||
"get_language_support",
|
||||
"get_supported_extensions",
|
||||
"get_supported_languages",
|
||||
"is_javascript",
|
||||
"is_jest",
|
||||
"is_mocha",
|
||||
"is_pytest",
|
||||
"is_python",
|
||||
"is_typescript",
|
||||
"is_unittest",
|
||||
"is_vitest",
|
||||
"register_language",
|
||||
"reset_current_language",
|
||||
"reset_test_framework",
|
||||
"set_current_language",
|
||||
"set_current_test_framework",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1925,7 +1925,7 @@ class JavaScriptSupport:
|
|||
project_root: Path | None = None,
|
||||
enable_coverage: bool = False,
|
||||
candidate_index: int = 0,
|
||||
test_framework: str = "jest",
|
||||
test_framework: str | None = None,
|
||||
) -> tuple[Path, Any, Path | None, Path | None]:
|
||||
"""Run behavioral tests using the detected test framework.
|
||||
|
||||
|
|
@ -1937,13 +1937,17 @@ class JavaScriptSupport:
|
|||
project_root: Project root directory.
|
||||
enable_coverage: Whether to collect coverage information.
|
||||
candidate_index: Index of the candidate being tested.
|
||||
test_framework: Test framework to use ("jest" or "vitest").
|
||||
test_framework: Test framework to use ("jest" or "vitest"). If None, uses singleton.
|
||||
|
||||
Returns:
|
||||
Tuple of (result_file_path, subprocess_result, coverage_path, config_path).
|
||||
|
||||
"""
|
||||
if test_framework == "vitest":
|
||||
from codeflash.languages.test_framework import get_js_test_framework_or_default
|
||||
|
||||
framework = test_framework or get_js_test_framework_or_default()
|
||||
|
||||
if framework == "vitest":
|
||||
from codeflash.languages.javascript.vitest_runner import run_vitest_behavioral_tests
|
||||
|
||||
return run_vitest_behavioral_tests(
|
||||
|
|
@ -1978,7 +1982,7 @@ class JavaScriptSupport:
|
|||
min_loops: int = 5,
|
||||
max_loops: int = 100_000,
|
||||
target_duration_seconds: float = 10.0,
|
||||
test_framework: str = "jest",
|
||||
test_framework: str | None = None,
|
||||
) -> tuple[Path, Any]:
|
||||
"""Run benchmarking tests using the detected test framework.
|
||||
|
||||
|
|
@ -1991,13 +1995,17 @@ class JavaScriptSupport:
|
|||
min_loops: Minimum number of loops for benchmarking.
|
||||
max_loops: Maximum number of loops for benchmarking.
|
||||
target_duration_seconds: Target duration for benchmarking in seconds.
|
||||
test_framework: Test framework to use ("jest" or "vitest").
|
||||
test_framework: Test framework to use ("jest" or "vitest"). If None, uses singleton.
|
||||
|
||||
Returns:
|
||||
Tuple of (result_file_path, subprocess_result).
|
||||
|
||||
"""
|
||||
if test_framework == "vitest":
|
||||
from codeflash.languages.test_framework import get_js_test_framework_or_default
|
||||
|
||||
framework = test_framework or get_js_test_framework_or_default()
|
||||
|
||||
if framework == "vitest":
|
||||
from codeflash.languages.javascript.vitest_runner import run_vitest_benchmarking_tests
|
||||
|
||||
return run_vitest_benchmarking_tests(
|
||||
|
|
@ -2032,7 +2040,7 @@ class JavaScriptSupport:
|
|||
timeout: int | None = None,
|
||||
project_root: Path | None = None,
|
||||
line_profile_output_file: Path | None = None,
|
||||
test_framework: str = "jest",
|
||||
test_framework: str | None = None,
|
||||
) -> tuple[Path, Any]:
|
||||
"""Run tests for line profiling using the detected test framework.
|
||||
|
||||
|
|
@ -2043,13 +2051,17 @@ class JavaScriptSupport:
|
|||
timeout: Optional timeout in seconds.
|
||||
project_root: Project root directory.
|
||||
line_profile_output_file: Path where line profile results will be written.
|
||||
test_framework: Test framework to use ("jest" or "vitest").
|
||||
test_framework: Test framework to use ("jest" or "vitest"). If None, uses singleton.
|
||||
|
||||
Returns:
|
||||
Tuple of (result_file_path, subprocess_result).
|
||||
|
||||
"""
|
||||
if test_framework == "vitest":
|
||||
from codeflash.languages.test_framework import get_js_test_framework_or_default
|
||||
|
||||
framework = test_framework or get_js_test_framework_or_default()
|
||||
|
||||
if framework == "vitest":
|
||||
from codeflash.languages.javascript.vitest_runner import run_vitest_line_profile_tests
|
||||
|
||||
return run_vitest_line_profile_tests(
|
||||
|
|
|
|||
|
|
@ -51,6 +51,22 @@ def _find_vitest_project_root(file_path: Path) -> Path | None:
|
|||
return None
|
||||
|
||||
|
||||
def _is_vitest_coverage_available(project_root: Path) -> bool:
|
||||
"""Check if Vitest coverage package is available.
|
||||
|
||||
Args:
|
||||
project_root: The project root directory.
|
||||
|
||||
Returns:
|
||||
True if @vitest/coverage-v8 or @vitest/coverage-istanbul is installed.
|
||||
|
||||
"""
|
||||
node_modules = project_root / "node_modules"
|
||||
return (node_modules / "@vitest" / "coverage-v8").exists() or (
|
||||
node_modules / "@vitest" / "coverage-istanbul"
|
||||
).exists()
|
||||
|
||||
|
||||
def _ensure_runtime_files(project_root: Path) -> None:
|
||||
"""Ensure JavaScript runtime package is installed in the project.
|
||||
|
||||
|
|
@ -217,15 +233,19 @@ def run_vitest_behavioral_tests(
|
|||
# Ensure the codeflash npm package is installed
|
||||
_ensure_runtime_files(effective_cwd)
|
||||
|
||||
# Coverage output directory
|
||||
# Coverage output directory - only enable if coverage package is available
|
||||
coverage_dir = get_run_tmp_file(Path("vitest_coverage"))
|
||||
coverage_json_path = coverage_dir / "coverage-final.json" if enable_coverage else None
|
||||
coverage_available = _is_vitest_coverage_available(effective_cwd) if enable_coverage else False
|
||||
coverage_json_path = coverage_dir / "coverage-final.json" if coverage_available else None
|
||||
|
||||
if enable_coverage and not coverage_available:
|
||||
logger.debug("Vitest coverage package not installed, running without coverage")
|
||||
|
||||
# Build Vitest command
|
||||
vitest_cmd = _build_vitest_behavioral_command(test_files=test_files, timeout=timeout, output_file=result_file_path)
|
||||
|
||||
# Add coverage flags if enabled
|
||||
if enable_coverage:
|
||||
# Add coverage flags only if coverage is available
|
||||
if coverage_available:
|
||||
vitest_cmd.extend(["--coverage", "--coverage.reporter=json", f"--coverage.reportsDirectory={coverage_dir}"])
|
||||
|
||||
# Set up environment
|
||||
|
|
|
|||
145
codeflash/languages/test_framework.py
Normal file
145
codeflash/languages/test_framework.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
"""Singleton for the current test framework being used in the codeflash session.
|
||||
|
||||
This module provides a centralized way to access and set the current test framework
|
||||
throughout the codeflash codebase, similar to how the language singleton works.
|
||||
|
||||
For JavaScript/TypeScript projects, this determines whether to use Jest or Vitest
|
||||
for test execution.
|
||||
|
||||
Usage:
|
||||
from codeflash.languages.test_framework import (
|
||||
current_test_framework,
|
||||
set_current_test_framework,
|
||||
is_jest,
|
||||
is_vitest,
|
||||
)
|
||||
|
||||
# Set the test framework at the start of a session (auto-detected from package.json)
|
||||
set_current_test_framework("vitest")
|
||||
|
||||
# Check the current test framework anywhere in the codebase
|
||||
if is_vitest():
|
||||
# Vitest-specific code
|
||||
...
|
||||
|
||||
# Get the current test framework
|
||||
framework = current_test_framework()
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
TestFramework = Literal["jest", "vitest", "mocha", "pytest", "unittest"]
|
||||
|
||||
# Module-level singleton for the current test framework
|
||||
_current_test_framework: TestFramework | None = None
|
||||
|
||||
|
||||
def current_test_framework() -> TestFramework | None:
|
||||
"""Get the current test framework being used in this codeflash session.
|
||||
|
||||
Returns:
|
||||
The current test framework string, or None if not set.
|
||||
|
||||
"""
|
||||
return _current_test_framework
|
||||
|
||||
|
||||
def set_current_test_framework(framework: TestFramework | str | None) -> None:
|
||||
"""Set the current test framework for this codeflash session.
|
||||
|
||||
This should be called once at the start of an optimization run,
|
||||
typically after reading the project configuration.
|
||||
|
||||
Args:
|
||||
framework: Test framework name ("jest", "vitest", "mocha", "pytest", "unittest").
|
||||
|
||||
"""
|
||||
global _current_test_framework
|
||||
|
||||
if _current_test_framework is not None:
|
||||
return
|
||||
|
||||
if framework is not None:
|
||||
framework = framework.lower()
|
||||
if framework not in ("jest", "vitest", "mocha", "pytest", "unittest"):
|
||||
# Default to jest for unknown JS frameworks, pytest for unknown Python
|
||||
from codeflash.languages.current import is_javascript
|
||||
|
||||
framework = "jest" if is_javascript() else "pytest"
|
||||
|
||||
_current_test_framework = framework
|
||||
|
||||
|
||||
def reset_test_framework() -> None:
|
||||
"""Reset the current test framework to None.
|
||||
|
||||
Useful for testing or when starting a new session.
|
||||
"""
|
||||
global _current_test_framework
|
||||
_current_test_framework = None
|
||||
|
||||
|
||||
def is_jest() -> bool:
|
||||
"""Check if the current test framework is Jest.
|
||||
|
||||
Returns:
|
||||
True if the current test framework is Jest.
|
||||
|
||||
"""
|
||||
return _current_test_framework == "jest"
|
||||
|
||||
|
||||
def is_vitest() -> bool:
|
||||
"""Check if the current test framework is Vitest.
|
||||
|
||||
Returns:
|
||||
True if the current test framework is Vitest.
|
||||
|
||||
"""
|
||||
return _current_test_framework == "vitest"
|
||||
|
||||
|
||||
def is_mocha() -> bool:
|
||||
"""Check if the current test framework is Mocha.
|
||||
|
||||
Returns:
|
||||
True if the current test framework is Mocha.
|
||||
|
||||
"""
|
||||
return _current_test_framework == "mocha"
|
||||
|
||||
|
||||
def is_pytest() -> bool:
|
||||
"""Check if the current test framework is pytest.
|
||||
|
||||
Returns:
|
||||
True if the current test framework is pytest.
|
||||
|
||||
"""
|
||||
return _current_test_framework == "pytest"
|
||||
|
||||
|
||||
def is_unittest() -> bool:
|
||||
"""Check if the current test framework is unittest.
|
||||
|
||||
Returns:
|
||||
True if the current test framework is unittest.
|
||||
|
||||
"""
|
||||
return _current_test_framework == "unittest"
|
||||
|
||||
|
||||
def get_js_test_framework_or_default() -> TestFramework:
|
||||
"""Get the current test framework for JS/TS, defaulting to 'jest' if not set.
|
||||
|
||||
This is a convenience function for JS/TS code that needs a framework.
|
||||
|
||||
Returns:
|
||||
The current test framework, or 'jest' as default.
|
||||
|
||||
"""
|
||||
if _current_test_framework in ("jest", "vitest", "mocha"):
|
||||
return _current_test_framework
|
||||
return "jest"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "codeflash",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"description": "Codeflash - AI-powered code optimization for JavaScript and TypeScript",
|
||||
"main": "runtime/index.js",
|
||||
"types": "runtime/index.d.ts",
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
"codeflash-setup": "./bin/codeflash-setup.js"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
"access": "public"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
|
|
@ -52,7 +52,8 @@
|
|||
"typescript",
|
||||
"ai",
|
||||
"cli",
|
||||
"jest"
|
||||
"jest",
|
||||
"vitest"
|
||||
],
|
||||
"author": "Codeflash AI",
|
||||
"license": "MIT",
|
||||
|
|
@ -70,7 +71,8 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"jest": ">=27.0.0",
|
||||
"jest-runner": ">=27.0.0"
|
||||
"jest-runner": ">=27.0.0",
|
||||
"vitest": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"jest": {
|
||||
|
|
@ -78,12 +80,13 @@
|
|||
},
|
||||
"jest-runner": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^12.0.0",
|
||||
"@msgpack/msgpack": "^3.0.0",
|
||||
"jest-runner": "^29.7.0",
|
||||
"jest-junit": "^16.0.0"
|
||||
"@msgpack/msgpack": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
*
|
||||
* Usage:
|
||||
* npx jest --runner=codeflash/loop-runner
|
||||
*
|
||||
* NOTE: This runner requires jest-runner to be installed in your project.
|
||||
* It is a Jest-specific feature and does not work with Vitest.
|
||||
* For Vitest projects, external looping is handled by the Python runner.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
|
@ -27,9 +31,20 @@
|
|||
const { createRequire } = require('module');
|
||||
const path = require('path');
|
||||
|
||||
const jestRunnerPath = require.resolve('jest-runner');
|
||||
const internalRequire = createRequire(jestRunnerPath);
|
||||
const runTest = internalRequire('./runTest').default;
|
||||
// Try to load jest-runner - it's a peer dependency that must be installed by the user
|
||||
let runTest;
|
||||
let jestRunnerAvailable = false;
|
||||
|
||||
try {
|
||||
const jestRunnerPath = require.resolve('jest-runner');
|
||||
const internalRequire = createRequire(jestRunnerPath);
|
||||
runTest = internalRequire('./runTest').default;
|
||||
jestRunnerAvailable = true;
|
||||
} catch (e) {
|
||||
// jest-runner not installed - this is expected for Vitest projects
|
||||
// The runner will throw a helpful error if someone tries to use it without jest-runner
|
||||
jestRunnerAvailable = false;
|
||||
}
|
||||
|
||||
// Configuration
|
||||
const MAX_BATCHES = parseInt(process.env.CODEFLASH_PERF_LOOP_COUNT || '10000', 10);
|
||||
|
|
@ -90,6 +105,14 @@ function deepCopy(obj, seen = new WeakMap()) {
|
|||
*/
|
||||
class CodeflashLoopRunner {
|
||||
constructor(globalConfig, context) {
|
||||
if (!jestRunnerAvailable) {
|
||||
throw new Error(
|
||||
'codeflash/loop-runner requires jest-runner to be installed.\n' +
|
||||
'Please install it: npm install --save-dev jest-runner\n\n' +
|
||||
'If you are using Vitest, the loop-runner is not needed - ' +
|
||||
'Vitest projects use external looping handled by the Python runner.'
|
||||
);
|
||||
}
|
||||
this._globalConfig = globalConfig;
|
||||
this._context = context || {};
|
||||
this._eventEmitter = new SimpleEventEmitter();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
These tests verify that run_behavioral_tests, run_benchmarking_tests, and
|
||||
run_line_profile_tests correctly dispatch to Jest or Vitest based on the
|
||||
test_framework parameter.
|
||||
test_framework parameter or singleton.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -13,6 +13,7 @@ from unittest.mock import MagicMock, patch
|
|||
import pytest
|
||||
|
||||
from codeflash.languages.javascript.support import JavaScriptSupport, TypeScriptSupport
|
||||
from codeflash.languages.test_framework import reset_test_framework, set_current_test_framework
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -27,6 +28,14 @@ def ts_support() -> TypeScriptSupport:
|
|||
return TypeScriptSupport()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_singleton() -> None:
|
||||
"""Reset the test framework singleton before each test."""
|
||||
reset_test_framework()
|
||||
yield
|
||||
reset_test_framework()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_test_paths() -> MagicMock:
|
||||
"""Create a mock TestFiles object."""
|
||||
|
|
@ -43,87 +52,54 @@ class TestBehavioralTestsDispatch:
|
|||
|
||||
@patch("codeflash.languages.javascript.test_runner.run_jest_behavioral_tests")
|
||||
def test_dispatches_to_jest_by_default(
|
||||
self,
|
||||
mock_jest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Jest when test_framework is not specified."""
|
||||
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_behavioral_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
)
|
||||
js_support.run_behavioral_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
|
||||
|
||||
mock_jest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.test_runner.run_jest_behavioral_tests")
|
||||
def test_dispatches_to_jest_explicitly(
|
||||
self,
|
||||
mock_jest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Jest when test_framework='jest'."""
|
||||
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_behavioral_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
test_framework="jest",
|
||||
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="jest"
|
||||
)
|
||||
|
||||
mock_jest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_behavioral_tests")
|
||||
def test_dispatches_to_vitest(
|
||||
self,
|
||||
mock_vitest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Vitest when test_framework='vitest'."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_behavioral_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
test_framework="vitest",
|
||||
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
|
||||
)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_behavioral_tests")
|
||||
def test_typescript_support_dispatches_to_vitest(
|
||||
self,
|
||||
mock_vitest_runner: MagicMock,
|
||||
ts_support: TypeScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_vitest_runner: MagicMock, ts_support: TypeScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""TypeScriptSupport should also dispatch to Vitest when test_framework='vitest'."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
ts_support.run_behavioral_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
test_framework="vitest",
|
||||
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
|
||||
)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
|
@ -134,54 +110,33 @@ class TestBenchmarkingTestsDispatch:
|
|||
|
||||
@patch("codeflash.languages.javascript.test_runner.run_jest_benchmarking_tests")
|
||||
def test_dispatches_to_jest_by_default(
|
||||
self,
|
||||
mock_jest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Jest when test_framework is not specified."""
|
||||
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_benchmarking_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
)
|
||||
js_support.run_benchmarking_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
|
||||
|
||||
mock_jest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_benchmarking_tests")
|
||||
def test_dispatches_to_vitest(
|
||||
self,
|
||||
mock_vitest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Vitest when test_framework='vitest'."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_benchmarking_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
test_framework="vitest",
|
||||
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
|
||||
)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_benchmarking_tests")
|
||||
def test_passes_loop_parameters(
|
||||
self,
|
||||
mock_vitest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should pass loop parameters to Vitest runner."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
|
|
@ -209,54 +164,33 @@ class TestLineProfileTestsDispatch:
|
|||
|
||||
@patch("codeflash.languages.javascript.test_runner.run_jest_line_profile_tests")
|
||||
def test_dispatches_to_jest_by_default(
|
||||
self,
|
||||
mock_jest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Jest when test_framework is not specified."""
|
||||
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_line_profile_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
)
|
||||
js_support.run_line_profile_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
|
||||
|
||||
mock_jest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_line_profile_tests")
|
||||
def test_dispatches_to_vitest(
|
||||
self,
|
||||
mock_vitest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should dispatch to Vitest when test_framework='vitest'."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
js_support.run_line_profile_tests(
|
||||
test_paths=mock_test_paths,
|
||||
test_env={},
|
||||
cwd=tmp_path,
|
||||
project_root=tmp_path,
|
||||
test_framework="vitest",
|
||||
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="vitest"
|
||||
)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_line_profile_tests")
|
||||
def test_passes_line_profile_output_file(
|
||||
self,
|
||||
mock_vitest_runner: MagicMock,
|
||||
js_support: JavaScriptSupport,
|
||||
mock_test_paths: MagicMock,
|
||||
tmp_path: Path,
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should pass line_profile_output_file to Vitest runner."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
|
|
@ -286,3 +220,121 @@ class TestTestFrameworkProperty:
|
|||
def test_typescript_default_framework_is_jest(self, ts_support: TypeScriptSupport) -> None:
|
||||
"""TypeScriptSupport should have Jest as default test framework."""
|
||||
assert ts_support.test_framework == "jest"
|
||||
|
||||
|
||||
class TestTestFrameworkSingleton:
|
||||
"""Tests for test_framework singleton behavior."""
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_behavioral_tests")
|
||||
def test_uses_singleton_when_param_not_provided(
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Should use singleton test_framework when parameter is not provided."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
# Set singleton to vitest
|
||||
set_current_test_framework("vitest")
|
||||
|
||||
# Don't pass test_framework parameter - should use singleton
|
||||
js_support.run_behavioral_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.test_runner.run_jest_behavioral_tests")
|
||||
def test_explicit_param_overrides_singleton(
|
||||
self, mock_jest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""Explicit test_framework parameter should override singleton."""
|
||||
mock_jest_runner.return_value = (tmp_path / "result.xml", MagicMock(), None, None)
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
# Set singleton to vitest
|
||||
set_current_test_framework("vitest")
|
||||
|
||||
# Pass explicit test_framework=jest - should override singleton
|
||||
js_support.run_behavioral_tests(
|
||||
test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path, test_framework="jest"
|
||||
)
|
||||
|
||||
mock_jest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_benchmarking_tests")
|
||||
def test_benchmarking_uses_singleton(
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""run_benchmarking_tests should use singleton when param not provided."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
set_current_test_framework("vitest")
|
||||
|
||||
js_support.run_benchmarking_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
||||
@patch("codeflash.languages.javascript.vitest_runner.run_vitest_line_profile_tests")
|
||||
def test_line_profile_uses_singleton(
|
||||
self, mock_vitest_runner: MagicMock, js_support: JavaScriptSupport, mock_test_paths: MagicMock, tmp_path: Path
|
||||
) -> None:
|
||||
"""run_line_profile_tests should use singleton when param not provided."""
|
||||
mock_vitest_runner.return_value = (tmp_path / "result.xml", MagicMock())
|
||||
(tmp_path / "package.json").write_text('{"name": "test"}')
|
||||
|
||||
set_current_test_framework("vitest")
|
||||
|
||||
js_support.run_line_profile_tests(test_paths=mock_test_paths, test_env={}, cwd=tmp_path, project_root=tmp_path)
|
||||
|
||||
mock_vitest_runner.assert_called_once()
|
||||
|
||||
|
||||
class TestTestFrameworkSingletonModule:
|
||||
"""Tests for the test_framework singleton module itself."""
|
||||
|
||||
def test_initial_state_is_none(self) -> None:
|
||||
"""Singleton should start as None."""
|
||||
from codeflash.languages.test_framework import current_test_framework
|
||||
|
||||
assert current_test_framework() is None
|
||||
|
||||
def test_set_and_get(self) -> None:
|
||||
"""Should be able to set and get test framework."""
|
||||
from codeflash.languages.test_framework import current_test_framework, set_current_test_framework
|
||||
|
||||
set_current_test_framework("vitest")
|
||||
assert current_test_framework() == "vitest"
|
||||
|
||||
def test_set_only_once(self) -> None:
|
||||
"""Once set, singleton should not change."""
|
||||
from codeflash.languages.test_framework import current_test_framework, set_current_test_framework
|
||||
|
||||
set_current_test_framework("jest")
|
||||
set_current_test_framework("vitest") # Should be ignored
|
||||
assert current_test_framework() == "jest"
|
||||
|
||||
def test_is_jest(self) -> None:
|
||||
"""is_jest() should return True when framework is Jest."""
|
||||
from codeflash.languages.test_framework import is_jest, set_current_test_framework
|
||||
|
||||
set_current_test_framework("jest")
|
||||
assert is_jest() is True
|
||||
|
||||
def test_is_vitest(self) -> None:
|
||||
"""is_vitest() should return True when framework is Vitest."""
|
||||
from codeflash.languages.test_framework import is_vitest, set_current_test_framework
|
||||
|
||||
set_current_test_framework("vitest")
|
||||
assert is_vitest() is True
|
||||
|
||||
def test_get_js_test_framework_or_default_returns_jest(self) -> None:
|
||||
"""get_js_test_framework_or_default should return 'jest' when not set."""
|
||||
from codeflash.languages.test_framework import get_js_test_framework_or_default
|
||||
|
||||
assert get_js_test_framework_or_default() == "jest"
|
||||
|
||||
def test_get_js_test_framework_or_default_returns_vitest(self) -> None:
|
||||
"""get_js_test_framework_or_default should return 'vitest' when set."""
|
||||
from codeflash.languages.test_framework import get_js_test_framework_or_default, set_current_test_framework
|
||||
|
||||
set_current_test_framework("vitest")
|
||||
assert get_js_test_framework_or_default() == "vitest"
|
||||
|
|
|
|||
Loading…
Reference in a new issue