|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +PyOsmo is a Model-Based Testing (MBT) framework for Python that generates test cases automatically from programmatic models. It uses pure Python as the modeling language (unlike traditional graphical MBT tools), enabling flexible modeling of complex system behaviors. |
| 8 | + |
| 9 | +**Key Concepts:** |
| 10 | +- **Steps**: Test actions (`step_*` methods or `@step` decorator) |
| 11 | +- **Guards**: Preconditions that control step execution (`guard_*` methods or `@guard` decorator) |
| 12 | +- **Weights**: Step selection probabilities (`weight_*` methods or `@weight` decorator) |
| 13 | +- **Algorithms**: Step selection strategies (Random, Weighted, Balancing) |
| 14 | +- **End Conditions**: Test termination criteria (Length, Time, StepCoverage, Endless) |
| 15 | +- **Lifecycle Hooks**: `before_suite`, `before_test`, `before`, `after`, `after_test`, `after_suite` |
| 16 | + |
| 17 | +## Development Commands |
| 18 | + |
| 19 | +### Testing |
| 20 | +```bash |
| 21 | +# Run all tests |
| 22 | +pytest pyosmo/tests/ |
| 23 | + |
| 24 | +# With coverage |
| 25 | +pytest pyosmo/tests/ --cov=pyosmo |
| 26 | + |
| 27 | +# Single test file |
| 28 | +pytest pyosmo/tests/test_core.py |
| 29 | + |
| 30 | +# Specific test |
| 31 | +pytest pyosmo/tests/test_core.py::test_function_name |
| 32 | + |
| 33 | +# Mutation testing |
| 34 | +mutmut run |
| 35 | +``` |
| 36 | + |
| 37 | +### Linting & Formatting |
| 38 | +```bash |
| 39 | +# Lint code (ruff is the primary linter) |
| 40 | +ruff check pyosmo/ |
| 41 | + |
| 42 | +# Auto-fix issues |
| 43 | +ruff check pyosmo/ --fix |
| 44 | + |
| 45 | +# Format code |
| 46 | +ruff format pyosmo/ |
| 47 | + |
| 48 | +# Check formatting without changes |
| 49 | +ruff format --check pyosmo/ |
| 50 | + |
| 51 | +# Type checking |
| 52 | +mypy pyosmo/ |
| 53 | +``` |
| 54 | + |
| 55 | +### Installation & Building |
| 56 | +```bash |
| 57 | +# Development install |
| 58 | +pip install -e ".[dev]" |
| 59 | + |
| 60 | +# Build package |
| 61 | +python -m build |
| 62 | + |
| 63 | +# Run CLI |
| 64 | +pyosmo examples/calculator_example.py --algorithm weighted --test-len 100 |
| 65 | +``` |
| 66 | + |
| 67 | +## Architecture |
| 68 | + |
| 69 | +### Core Components |
| 70 | + |
| 71 | +**pyosmo/osmo.py** - Main entry point. The `Osmo` class orchestrates test generation: |
| 72 | +- Accepts model instances |
| 73 | +- Configures algorithms, end conditions, and error strategies |
| 74 | +- Provides fluent API for configuration |
| 75 | +- Executes test generation and tracks history |
| 76 | + |
| 77 | +**pyosmo/model.py** - Model parser that discovers steps, guards, weights, and lifecycle hooks using: |
| 78 | +1. Naming convention: `step_*`, `guard_*`, `weight_*` methods |
| 79 | +2. Decorator-based: `@step`, `@guard`, `@weight`, `@pre`, `@post`, `@requires` |
| 80 | + |
| 81 | +**pyosmo/config.py** - Configuration management using OsmoConfig class. Centralizes all test generation parameters. |
| 82 | + |
| 83 | +### Plugin Architecture |
| 84 | + |
| 85 | +**pyosmo/algorithm/** - Step selection strategies: |
| 86 | +- `RandomAlgorithm`: Pure random selection |
| 87 | +- `WeightedAlgorithm`: Weight-based random selection |
| 88 | +- `BalancingAlgorithm`: Balances step execution to achieve coverage |
| 89 | + |
| 90 | +**pyosmo/end_conditions/** - Test termination conditions: |
| 91 | +- `Length(n)`: Stop after n steps |
| 92 | +- `Time(seconds)`: Stop after elapsed time |
| 93 | +- `StepCoverage(percentage)`: Stop when coverage threshold reached |
| 94 | +- `And(*conditions)` / `Or(*conditions)`: Combine conditions |
| 95 | +- `Endless()`: Run forever (online testing) |
| 96 | + |
| 97 | +**pyosmo/error_strategy/** - Error handling: |
| 98 | +- `AlwaysRaise`: Fail fast on any error |
| 99 | +- `AlwaysIgnore`: Continue on all errors |
| 100 | +- `IgnoreAssertions`: Ignore assertion errors only |
| 101 | +- `AllowCount(n)`: Allow up to n errors |
| 102 | + |
| 103 | +**pyosmo/history/** - Execution tracking: |
| 104 | +- `History`: Main history tracker |
| 105 | +- `TestCase`: Individual test case records |
| 106 | +- `TestStepLog`: Step-level execution logs |
| 107 | +- `Statistics`: Coverage and execution statistics |
| 108 | + |
| 109 | +### Model Discovery |
| 110 | + |
| 111 | +Models can define test logic using either approach: |
| 112 | + |
| 113 | +**Naming Convention (classic):** |
| 114 | +```python |
| 115 | +class MyModel: |
| 116 | + def step_action_name(self): # Test step |
| 117 | + pass |
| 118 | + |
| 119 | + def guard_action_name(self): # Precondition |
| 120 | + return True |
| 121 | + |
| 122 | + def weight_action_name(self): # Weight (default: 1) |
| 123 | + return 10 |
| 124 | + |
| 125 | + def before_test(self): # Setup |
| 126 | + pass |
| 127 | +``` |
| 128 | + |
| 129 | +**Decorator-Based (modern):** |
| 130 | +```python |
| 131 | +from pyosmo import step, guard, weight |
| 132 | + |
| 133 | +class MyModel: |
| 134 | + @step |
| 135 | + @guard(lambda self: self.ready) |
| 136 | + @weight(10) |
| 137 | + def action_name(self): |
| 138 | + pass |
| 139 | +``` |
| 140 | + |
| 141 | +### Fluent Configuration API |
| 142 | + |
| 143 | +Osmo supports method chaining for configuration: |
| 144 | +```python |
| 145 | +Osmo(MyModel()) |
| 146 | + .random_algorithm(seed=42) |
| 147 | + .stop_after_steps(100) |
| 148 | + .run_tests(5) |
| 149 | + .raise_on_error() |
| 150 | + .generate() |
| 151 | +``` |
| 152 | + |
| 153 | +## Code Style |
| 154 | + |
| 155 | +- **Line length**: 120 characters |
| 156 | +- **Python version**: 3.11+ (supports 3.11-3.14) |
| 157 | +- **Linter**: Ruff (replaces flake8/black) |
| 158 | +- **Quote style**: Double quotes |
| 159 | +- **Type hints**: Encouraged for main code, not required for tests |
| 160 | +- **Import sorting**: Handled by ruff (isort rules) |
| 161 | + |
| 162 | +### Ruff Configuration |
| 163 | +Key enabled rules: pycodestyle (E/W), pyflakes (F), isort (I), pep8-naming (N), pyupgrade (UP), bugbear (B), comprehensions (C4), simplify (SIM), return (RET) |
| 164 | + |
| 165 | +Ignored rules: |
| 166 | +- E501 (line too long - handled by formatter) |
| 167 | +- B008 (function call in defaults) |
| 168 | +- B904 (raise from in except) |
| 169 | + |
| 170 | +## Testing Patterns |
| 171 | + |
| 172 | +- Tests located in `pyosmo/tests/` |
| 173 | +- Use pytest framework |
| 174 | +- Hypothesis for property-based testing available |
| 175 | +- Test coverage tracked via `--cov` flag |
| 176 | +- Mutation testing with mutmut configured |
| 177 | +- Per-file ignores: `__init__.py` allows unused imports, tests allow `assert False` |
| 178 | + |
| 179 | +## CI/CD |
| 180 | + |
| 181 | +GitHub Actions workflow (`.github/workflows/pr_check.yaml`): |
| 182 | +- Tests on Python 3.11, 3.12, 3.13, 3.14 |
| 183 | +- Uses `uv` for fast dependency management |
| 184 | +- Runs ruff linter and formatter checks |
| 185 | +- Executes pytest suite |
| 186 | + |
| 187 | +## Strategic Context |
| 188 | + |
| 189 | +PyOsmo aims to become the leading open-source MBT tool for Python by: |
| 190 | +- Emphasizing developer experience and pytest integration |
| 191 | +- Using pure Python for modeling (vs. graphical tools) |
| 192 | +- Supporting both offline (test generation) and online (real-time) testing |
| 193 | +- Enabling long-running, regression, and exploratory testing |
| 194 | + |
| 195 | +See `doc/strategic_vision_2025.md` for detailed roadmap and competitive analysis. |
| 196 | + |
| 197 | +## Additional Tools |
| 198 | + |
| 199 | +**model-creator/** - Autonomous website model generator that crawls websites and generates PyOsmo models automatically using BeautifulSoup4 and requests. See `model-creator/README.md` for usage. |
| 200 | + |
| 201 | +## Common Development Workflow |
| 202 | + |
| 203 | +1. Make changes to `pyosmo/` code |
| 204 | +2. Run `ruff check pyosmo/ --fix` and `ruff format pyosmo/` to lint and format |
| 205 | +3. Run `mypy pyosmo/` for type checking |
| 206 | +4. Run `pytest pyosmo/tests/` to verify tests pass |
| 207 | +5. Add/update tests in `pyosmo/tests/` for new functionality |
| 208 | +6. Verify coverage with `pytest pyosmo/tests/ --cov=pyosmo` |
0 commit comments