diff --git a/tests/test_discrete_allocation.py b/tests/test_discrete_allocation.py index 3feca96d..f0953186 100644 --- a/tests/test_discrete_allocation.py +++ b/tests/test_discrete_allocation.py @@ -1,7 +1,7 @@ +from cvxpy.error import SolverError import numpy as np import pandas as pd import pytest -from cvxpy.error import SolverError from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices from tests.utilities_for_tests import get_data, setup_efficient_frontier diff --git a/tests/test_efficient_frontier.py b/tests/test_efficient_frontier.py index 4028e1a7..038788e0 100644 --- a/tests/test_efficient_frontier.py +++ b/tests/test_efficient_frontier.py @@ -608,7 +608,7 @@ def test_min_vol_pair_constraint(): ef.min_volatility() old_sum = ef.weights[:2].sum() ef = setup_efficient_frontier() - ef.add_constraint(lambda w: (w[1] + w[0] <= old_sum / 2)) + ef.add_constraint(lambda w: w[1] + w[0] <= old_sum / 2) ef.min_volatility() new_sum = ef.weights[:2].sum() assert new_sum <= old_sum / 2 + 1e-4 @@ -620,7 +620,7 @@ def test_max_sharpe_pair_constraint(): old_sum = ef.weights[:2].sum() ef = setup_efficient_frontier() - ef.add_constraint(lambda w: (w[1] + w[0] <= old_sum / 2)) + ef.add_constraint(lambda w: w[1] + w[0] <= old_sum / 2) ef.max_sharpe(risk_free_rate=0.02) new_sum = ef.weights[:2].sum() assert new_sum <= old_sum / 2 + 1e-4 diff --git a/tests/test_readme_examples.py b/tests/test_readme_examples.py new file mode 100644 index 00000000..12b77cbb --- /dev/null +++ b/tests/test_readme_examples.py @@ -0,0 +1,39 @@ +import os +from pathlib import Path +import re +import sys + +README_PATH = Path(__file__).resolve().parent.parent / "README.md" + + +def _extract_python_blocks(markdown_text: str) -> list[str]: + pattern = re.compile(r"```python[^\n]*\n(.*?)```", re.DOTALL) + return [block.strip() for block in pattern.findall(markdown_text)] + + +def test_readme_python_examples_run(): + readme_text = README_PATH.read_text(encoding="utf-8") + python_blocks = _extract_python_blocks(readme_text) + + assert python_blocks, "No python code blocks found in README.md" + + repo_root = README_PATH.parent + + # Make package importable + sys.path.insert(0, str(repo_root)) + + # Run from repo root so relative paths work + old_cwd = os.getcwd() + os.chdir(repo_root) + + globals_dict = {"__name__": "__main__"} + + try: + for idx, block in enumerate(python_blocks, start=1): + exec(block, globals_dict) + + except Exception as e: + raise AssertionError(f"README python block #{idx} failed:\n{block}") from e + + finally: + os.chdir(old_cwd)