Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
807281b
Add world component tests
ColtonPayne Sep 13, 2025
2eaeb4e
test: ensure direct world function coverage
ColtonPayne Sep 13, 2025
e846921
Ensure world tests cover all branches
ColtonPayne Sep 13, 2025
5d5c133
Merge pull request #37 from ColtonPayne/codex/add-unit-tests-for-anno…
ColtonPayne Sep 19, 2025
3b065c1
Add api tests
ColtonPayne Sep 19, 2025
c9e1a99
Fix functional tests
ColtonPayne Sep 19, 2025
acf9d9f
Functional test update
ColtonPayne Sep 20, 2025
dbb2605
Functional test error reporting
ColtonPayne Sep 20, 2025
e337b64
Complete functional test fixes and error reports
ColtonPayne Sep 20, 2025
bad9687
Remove unneeded debug scripts
ColtonPayne Sep 20, 2025
8544a35
Fix fp marker
ColtonPayne Sep 20, 2025
9144688
Upd pre commit hooks
ColtonPayne Sep 20, 2025
45e3ff5
Update again
ColtonPayne Sep 20, 2025
aa402f8
Update again
ColtonPayne Sep 20, 2025
7226c40
Upd
ColtonPayne Sep 20, 2025
ee11196
stop gaslighting
ColtonPayne Sep 20, 2025
e549567
Remove api unit tests from commit hook
ColtonPayne Sep 20, 2025
f13cc59
Fix
ColtonPayne Sep 20, 2025
e1b52fa
upd?
ColtonPayne Sep 20, 2025
892104a
Rem old fp tests
ColtonPayne Sep 20, 2025
4490aac
Add deep debug
ColtonPayne Sep 22, 2025
1506d46
Transitive property debugging
ColtonPayne Sep 23, 2025
d65b340
Revert to old failure
ColtonPayne Sep 23, 2025
ab19f69
Comment out potentailly unsafe check
ColtonPayne Sep 23, 2025
2559323
Rem num ground atoms check
ColtonPayne Sep 23, 2025
a222833
Remove tests that don't make sense for fp version
ColtonPayne Sep 25, 2025
b3044dc
Add mmore test files
ColtonPayne Sep 25, 2025
9197f3a
Add changes
ColtonPayne Sep 27, 2025
4d5475f
fp tests, remove unsafe if condition
dyumanaditya Sep 29, 2025
61fd1c6
fp tests, remove unsafe if condition
dyumanaditya Sep 29, 2025
d05dbee
fixes #72
dyumanaditya Sep 29, 2025
5d8c8c6
fixes #73
dyumanaditya Sep 29, 2025
73203b5
change query to return (0,1) instead of (0,0) if predicate or compone…
dyumanaditya Sep 29, 2025
af8b0a7
change query to return (0,1) instead of (0,0) if predicate or compone…
dyumanaditya Sep 29, 2025
0165910
fixes #75
dyumanaditya Sep 29, 2025
db5a736
maybe the test was wrong for perfect convergence?
dyumanaditya Sep 29, 2025
500a0dc
maybe the test was wrong for perfect convergence?
dyumanaditya Sep 29, 2025
68bd365
maybe the test was wrong for perfect convergence? -- Nope, doesn't fi…
dyumanaditya Sep 29, 2025
e54f513
fixes #74 and fixes #75
dyumanaditya Sep 29, 2025
0bece20
fix other unit tests?
dyumanaditya Sep 29, 2025
02d73d2
Prep for merge
ColtonPayne Sep 30, 2025
e7b3019
Don'
ColtonPayne Sep 30, 2025
9b92845
Prep for merge
ColtonPayne Sep 30, 2025
df4f465
Cache status
ColtonPayne Sep 30, 2025
076ae2d
Rm results md file
ColtonPayne Sep 30, 2025
44dd899
Final changes
ColtonPayne Sep 30, 2025
1da45f2
Test parallel
ColtonPayne Sep 30, 2025
c61554e
Don't use numba wrapper test
ColtonPayne Sep 30, 2025
9230a91
Merge pull request #43 from ColtonPayne/test-updates
ColtonPayne Sep 30, 2025
2036010
test
ColtonPayne Sep 30, 2025
cf954a1
fix hook
ColtonPayne Sep 30, 2025
6616634
Merge pull request #44 from lab-v2/colton-fixes
ColtonPayne Sep 30, 2025
af84370
test updates
ColtonPayne Sep 30, 2025
172ad05
Merge pull request #77 from ColtonPayne/main
dyumanaditya Oct 6, 2025
1ab1b1a
Merge pull request #78 from ColtonPayne/dyuman-fixes
dyumanaditya Oct 6, 2025
b8e47b8
remove dynamic allocation of interpretation dict in interpretation_fp…
dyumanaditya Oct 6, 2025
bbba2c1
Test time fix interpretation_fp.py
dyumanaditya Oct 6, 2025
3546b81
Test time fix interpretation_fp.py
dyumanaditya Oct 6, 2025
645f795
Test time fix interpretation_fp.py
dyumanaditya Oct 6, 2025
2d46709
Test time fix interpretation_fp.py
dyumanaditya Oct 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
__pycache__/
*.py[cod]
*$py.class
.cache_status.yaml
# Cache status file when initialized
# Keep the initial false version in repo, ignore when it becomes true
.DS_STORE

# C extensions
Expand Down
32 changes: 21 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
exclude: 'pyreason/\.cache_status\.yaml'
repos:
- repo: local
hooks:
# --- Unit tests ---
- id: pytest-unit-with-coverage
name: Run unit tests with coverage and open report
entry: bash -c 'pytest tests/unit/disable_jit --cov pyreason --cov-report=html && ( (command -v xdg-open >/dev/null && xdg-open htmlcov/index.html) || (command -v open >/dev/null && open htmlcov/index.html) || (command -v start >/dev/null && start htmlcov/index.html) )'
# --- COMMIT STAGE: Fast unit tests only ---
- id: pytest-unit-no-jit
name: Run JIT-disabled unit tests
entry: .venv/bin/python -m pytest tests/unit/disable_jit -m "not slow" --tb=short -q
language: system
pass_filenames: false
stages: [pre-commit]

- id: pytest-unit-jit
name: Run JIT-enabled unit tests
entry: bash -c 'pytest tests/unit/dont_disable_jit'
name: Run JIT-enabled unit tests
entry: .venv/bin/python -m pytest tests/unit/dont_disable_jit -m "not slow" --tb=short -q
language: system
pass_filenames: false
stages: [pre-commit]

# --- Functional tests ---
- id: pytest-functional
name: Run functional tests
entry: bash -c 'pytest tests/functional'
# --- PUSH STAGE: Complete test suite ---

- id: pytest-unit-api
name: Run pyreason api unit tests
entry: .venv/bin/python -m pytest tests/unit/api_tests --tb=short -q
language: system
pass_filenames: false
stages: [pre-push]

- id: pytest-functional-complete
name: Run functional test suite
entry: .venv/bin/python -m pytest tests/functional/ --tb=short
language: system
pass_filenames: false
# Only run manually, not on every commit
stages: [pre-push]
179 changes: 179 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# PyReason Test Suite Makefile
# Provides convenient shortcuts for running different test configurations

.PHONY: help test test-all test-fast test-api test-jit test-no-jit test-consistency \
test-parallel test-no-coverage coverage-report coverage-html coverage-xml \
clean clean-coverage clean-reports install-deps lint check-deps

# Default target
.DEFAULT_GOAL := help

# Variables
PYTHON := python3
RUN_TESTS := $(PYTHON) run_tests.py
PIP := $(PYTHON) -m pip

# Auto-detect python if python3 doesn't work
PYTHON_CHECK := $(shell $(PYTHON) --version 2>/dev/null || echo "failed")
ifeq ($(PYTHON_CHECK),failed)
PYTHON := python
RUN_TESTS := $(PYTHON) run_tests.py
PIP := $(PYTHON) -m pip
endif

# Colors for output
BLUE := \033[34m
GREEN := \033[32m
YELLOW := \033[33m
RED := \033[31m
BOLD := \033[1m
RESET := \033[0m

# Help target
help: ## Show this help message
@echo "$(BOLD)PyReason Test Suite$(RESET)"
@echo "$(BLUE)Available targets:$(RESET)"
@echo ""
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " $(GREEN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST)
@echo ""
@echo "$(BLUE)Examples:$(RESET)"
@echo " make test # Run all test suites with coverage and open report"
@echo " make test-fast # Run only fast test suites"
@echo " make test-api # Run only API tests"
@echo " make test-parallel # Run tests in parallel where possible"
@echo " make coverage-html # Generate HTML coverage report"

# Main test targets
test: ## Run all test suites with coverage and open report
@echo "$(BOLD)$(BLUE)Running all test suites...$(RESET)"
$(RUN_TESTS)
@echo "$(BOLD)$(GREEN)Opening coverage report in browser...$(RESET)"
@if [ -f test_reports/htmlcov/index.html ]; then \
open test_reports/htmlcov/index.html 2>/dev/null || \
xdg-open test_reports/htmlcov/index.html 2>/dev/null || \
echo "$(GREEN)HTML report available at: test_reports/htmlcov/index.html$(RESET)"; \
else \
echo "$(YELLOW)No HTML coverage report found$(RESET)"; \
fi

test-all: test ## Alias for 'test' target

test-only: ## Run all test suites with coverage (no browser)
@echo "$(BOLD)$(BLUE)Running all test suites...$(RESET)"
$(RUN_TESTS)

test-fast: ## Run only fast test suites (api_tests, dont_disable_jit)
@echo "$(BOLD)$(BLUE)Running fast test suites...$(RESET)"
$(RUN_TESTS) --fast

test-parallel: ## Run test suites in parallel where possible
@echo "$(BOLD)$(BLUE)Running test suites in parallel...$(RESET)"
$(RUN_TESTS) --parallel

test-no-coverage: ## Run all tests without coverage collection
@echo "$(BOLD)$(BLUE)Running tests without coverage...$(RESET)"
$(RUN_TESTS) --no-coverage

# Individual test suite targets
test-api: ## Run only API tests (tests/unit/api_tests)
@echo "$(BOLD)$(BLUE)Running API tests...$(RESET)"
$(RUN_TESTS) --suite api_tests

test-jit: ## Run only JIT-disabled tests (tests/unit/disable_jit)
@echo "$(BOLD)$(BLUE)Running JIT-disabled tests...$(RESET)"
$(RUN_TESTS) --suite don_disable_jit

test-no-jit: ## Run only JIT-enabled tests (tests/unit/dont_disable_jit)
@echo "$(BOLD)$(BLUE)Running JIT-enabled tests...$(RESET)"
$(RUN_TESTS) --suite disable_jit

test-consistency: ## Run numba consistency tests
@echo "$(BOLD)$(BLUE)Running consistency tests...$(RESET)"
$(PYTHON) -m pytest tests/unit/dont_disable_jit/test_numba_consistency.py -v

test-functional: ## Run functional/end-to-end tests
@echo "$(BOLD)$(BLUE)Running functional tests...$(RESET)"
$(RUN_TESTS) --suite functional


test-all-suites: ## Run all test suites including functional tests
@echo "$(BOLD)$(BLUE)Running all test suites including functional...$(RESET)"
$(RUN_TESTS)

# Coverage targets
coverage-report: ## Show coverage report in terminal
@echo "$(BOLD)$(BLUE)Generating coverage report...$(RESET)"
@if [ -f test_reports/coverage.xml ]; then \
coverage report --rcfile=test_reports/.coveragerc 2>/dev/null || \
echo "$(YELLOW)Run 'make test' first to generate coverage data$(RESET)"; \
else \
echo "$(YELLOW)No coverage data found. Run 'make test' first$(RESET)"; \
fi

coverage-html: ## Generate HTML coverage report
@echo "$(BOLD)$(BLUE)Opening HTML coverage report...$(RESET)"
@if [ -f test_reports/htmlcov/index.html ]; then \
open test_reports/htmlcov/index.html 2>/dev/null || \
xdg-open test_reports/htmlcov/index.html 2>/dev/null || \
echo "$(GREEN)HTML report available at: test_reports/htmlcov/index.html$(RESET)"; \
else \
echo "$(YELLOW)No HTML coverage report found. Run 'make test' first$(RESET)"; \
fi

coverage-xml: ## Show path to XML coverage report
@echo "$(BOLD)$(BLUE)XML Coverage Report:$(RESET)"
@if [ -f test_reports/coverage.xml ]; then \
echo "$(GREEN)XML report available at: test_reports/coverage.xml$(RESET)"; \
else \
echo "$(YELLOW)No XML coverage report found. Run 'make test' first$(RESET)"; \
fi

# Development targets
lint: ## Run linting checks
@echo "$(BOLD)$(BLUE)Running linting checks...$(RESET)"
@echo "$(YELLOW)Note: Add your preferred linter commands here$(RESET)"
# Example: flake8 pyreason tests
# Example: black --check pyreason tests
# Example: mypy pyreason

check-deps: ## Check if required dependencies are installed
@echo "$(BOLD)$(BLUE)Checking dependencies...$(RESET)"
@$(PYTHON) -c "import pytest; print('✓ pytest installed')" 2>/dev/null || \
(echo "$(RED)✗ pytest not installed$(RESET)" && exit 1)
@$(PYTHON) -c "import coverage; print('✓ coverage installed')" 2>/dev/null || \
(echo "$(RED)✗ coverage not installed$(RESET)" && exit 1)
@$(PYTHON) -c "import pyreason; print('✓ pyreason importable')" 2>/dev/null || \
(echo "$(YELLOW)⚠ pyreason not importable (may need installation)$(RESET)")
@echo "$(GREEN)Dependencies check complete$(RESET)"

install-deps: ## Install testing dependencies
@echo "$(BOLD)$(BLUE)Installing testing dependencies...$(RESET)"
$(PIP) install pytest coverage pytest-cov pytest-timeout
@echo "$(GREEN)Testing dependencies installed$(RESET)"

# Cleanup targets
clean: clean-coverage clean-reports ## Clean all generated files
@echo "$(BOLD)$(BLUE)Cleaning all generated files...$(RESET)"
@find . -name "*.pyc" -delete 2>/dev/null || true
@find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
@find . -name ".pytest_cache" -type d -exec rm -rf {} + 2>/dev/null || true
@echo "$(GREEN)Cleanup complete$(RESET)"

clean-coverage: ## Clean coverage files
@echo "$(BOLD)$(BLUE)Cleaning coverage files...$(RESET)"
@rm -f .coverage .coverage.* 2>/dev/null || true
@rm -rf test_reports/htmlcov 2>/dev/null || true
@rm -f test_reports/coverage.xml 2>/dev/null || true

clean-reports: ## Clean test report files
@echo "$(BOLD)$(BLUE)Cleaning test reports...$(RESET)"
@rm -rf test_reports 2>/dev/null || true

# Version and info
info: ## Show project and tool versions
@echo "$(BOLD)$(BLUE)Project Information:$(RESET)"
@echo "Python: $$($(PYTHON) --version)"
@echo "Pytest: $$($(PYTHON) -c 'import pytest; print(pytest.__version__)' 2>/dev/null || echo 'Not installed')"
@echo "Coverage: $$($(PYTHON) -c 'import coverage; print(coverage.__version__)' 2>/dev/null || echo 'Not installed')"
@echo "Working Directory: $$(pwd)"
@echo "Test Runner: $$(ls -la run_tests.py 2>/dev/null || echo 'Not found')"
114 changes: 107 additions & 7 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,118 @@ this command to view linting results:
ruff check .
```

## Running Tests Manually
## Running Tests

The automated hooks cover most scenarios, but you can invoke the test suites
directly:
### Enhanced Test Suite

PyReason uses a unified test runner that handles multiple test configurations automatically. The test suite is organized into four directories:

- **`tests/unit/api_tests/`** - Tests for main pyreason.py API functions (JIT enabled, real pyreason)
- **`tests/unit/disable_jit/`** - Tests for internal interpretation logic (JIT disabled, stubbed environment)
- **`tests/unit/dont_disable_jit/`** - Tests for components that benefit from JIT (JIT enabled, lightweight stubs)
- **`tests/functional/`** - End-to-end functional tests (JIT enabled, real pyreason, longer running)

### Quick Start

```bash
# Install testing dependencies
make install-deps

# Run all test suites with unified coverage
make test

# Run only fast test suites
make test-fast

# Generate HTML coverage report
make coverage-html
```

### Individual Test Suites

```bash
# API tests (real pyreason, JIT enabled)
make test-api

# JIT disabled tests (stubbed environment)
make test-jit

# JIT enabled tests (lightweight stubs)
make test-no-jit

# Consistency tests
make test-consistency

# Functional/end-to-end tests
make test-functional
```

### Advanced Options

```bash
# Run with parallel execution where possible
make test-parallel

# Run without coverage collection (faster)
python run_tests.py --no-coverage

# Run specific suites
python run_tests.py --suite api_tests --suite dont_disable_jit

# Run functional tests (multiple options)
make test-functional # Using test runner
pytest tests/functional # Traditional approach
```

### Traditional Pytest (Per Suite)

You can still run pytest directly on individual directories:

```bash
pytest tests/unit
# API tests
pytest tests/unit/api_tests/ -v

# JIT disabled tests
NUMBA_DISABLE_JIT=1 pytest tests/unit/disable_jit/ -v

# JIT enabled tests
pytest tests/unit/dont_disable_jit/ -v

# Functional tests
pytest tests/functional/ -v
```

### Coverage Reports

The test runner automatically combines coverage from all suites:

- **Terminal Report:** Summary shown after test execution
- **HTML Report:** `test_reports/htmlcov/index.html`
- **XML Report:** `test_reports/coverage.xml`

### Troubleshooting

```bash
pytest tests/functional
# Check system status and dependencies
make info
make check-deps

# Validate test runner setup
python test_runner_validation.py

# Test pytest configuration
python -c "import configparser; c=configparser.ConfigParser(); c.read('pytest.ini'); print('pytest.ini is valid')"

# Run a single functional test
pytest tests/functional/test_hello_world.py -v

# Clean up generated files
make clean
```

Running tests locally before committing or pushing helps catch issues early and
speeds up code review.
**Common Issues:**
- **Functional tests fail with warnings**: The pytest.ini has been updated to ignore expected warnings from numba and networkx
- **Tests time out**: Functional tests have longer timeouts (600s) and global timeout is disabled
- **Import errors**: Ensure pytest and dependencies are installed with `make install-deps`

Running tests locally before committing or pushing helps catch issues early and speeds up code review. The unified test runner ensures consistent behavior across different development environments.
5 changes: 0 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
[build-system]
requires = ['setuptools>=42']
build-backend = 'setuptools.build_meta'

[tool.pytest.ini_options]
pythonpath = [
"."
]
3 changes: 2 additions & 1 deletion pyreason/pyreason.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,9 @@ def reset_rules():
"""
Resets rules to none
"""
global __rules
global __rules, __annotation_functions
__rules = None
__annotation_functions = []
if __program is not None:
__program.reset_rules()

Expand Down
2 changes: 1 addition & 1 deletion pyreason/scripts/components/world.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ def __str__(self):
for label in self._world.keys():
result = result + label.get_value() + ',' + self._world[label].to_str() + '\n'

return result
return result
Loading