Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
91 changes: 0 additions & 91 deletions .github/agents/test-specialist.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,30 +149,6 @@ If ANY test fails during full suite execution:
- Compare against SensorIdField pattern
- See Lead's Click context error pattern

### Integration with Lead

The Test Specialist MUST provide evidence of full test suite execution to Lead.

**Required evidence format:**
```
Full test suite execution:
- Command: pytest
- Results: 2,847 tests passed (100%)
- Duration: 145.3s
- Warnings: None
- Coverage: 87.2% (unchanged)
```

**Lead verification:**
Lead's session close checklist includes:
- [ ] Test Specialist confirmed full test suite execution
- [ ] All tests pass (100%)
- [ ] Test output captured and reviewed

**Enforcement:**
Lead cannot close session until Test Specialist provides evidence of full test suite execution with 100% pass rate.


### Testing Patterns for FlexMeasures

FlexMeasures uses pytest with two main fixture patterns for database management:
Expand Down Expand Up @@ -240,18 +216,6 @@ def test_create_annotation(client, setup_api_fresh_test_data, fresh_db):
assert annotation is not None
```

**Performance Impact**

Module-scoped `db` fixture:
- ✅ **Faster**: Database created once per test module
- ✅ **Shared data**: All tests use same database state
- ⚠️ **Limitation**: Tests must not modify data (read-only)

Function-scoped `fresh_db` fixture:
- ✅ **Isolation**: Each test gets fresh database
- ✅ **Modifications OK**: Tests can create/update/delete freely
- ⚠️ **Slower**: Database created/destroyed per test function

**Decision Tree**

```
Expand Down Expand Up @@ -409,22 +373,6 @@ def test_annotation_post_invalid_entity_id(client, entity_type, invalid_id):
assert "does not exist" in response.json["message"].lower()
```

#### When You Get 404 vs 422

```python
# 404: Route doesn't exist
response = client.get("/api/dev/nonexistent-endpoint")
assert response.status_code == 404

# 422: Field validation fails (route exists, data invalid)
response = client.post("/api/dev/annotation/assets/99999", json={"content": "test"})
assert response.status_code == 422

# 201: Everything valid
response = client.post("/api/dev/annotation/assets/1", json={"content": "test"})
assert response.status_code == 201 # Created
```

**Related FlexMeasures patterns**: Marshmallow schema validation, webargs error handling, REST API conventions

### Installation and Setup
Expand Down Expand Up @@ -572,45 +520,6 @@ environment you must have these running yourself before executing tests.

If setup steps fail or are unclear, escalate to the Tooling & CI Specialist.

### Test Execution Workflow (CRITICAL)

Follow `.github/workflows/copilot-setup-steps.yml` for the authoritative environment setup. In summary:

1. **PostgreSQL** must be running with user/db `flexmeasures_test` and password `flexmeasures_test`.
2. **Redis** must be running on `localhost:6379`.
3. **Install dependencies**: `uv sync --locked --group test`
4. **Set env vars**: `FLEXMEASURES_ENV=testing`, `SQLALCHEMY_DATABASE_URI=postgresql://flexmeasures_test:flexmeasures_test@127.0.0.1:5432/flexmeasures_test`, `FLEXMEASURES_REDIS_URL=redis://127.0.0.1:6379/0`
5. **Run tests**: `uv run poe test` or `pytest`

If setup fails, escalate to the Tooling & CI Specialist.

❌ **Don't**: Assume PostgreSQL is running
✅ **Do**: Check service status before running tests

❌ **Don't**: Skip environment variable setup
✅ **Do**: Export all required variables (FLEXMEASURES_ENV, SQLALCHEMY_DATABASE_URI, etc.)

❌ **Don't**: Claim "tests pass" without showing pytest output
✅ **Do**: Capture and verify actual test results (passed/failed counts)

❌ **Don't**: Ignore connection errors and move on
✅ **Do**: Debug and fix setup issues before proceeding

### Running Tests in FlexMeasures Dev Environment

```bash
# Install test dependencies
uv sync --locked --group test
# Run all tests (canonical command)
uv run poe test
# Run specific file or function
uv run pytest path/to/test_file.py::test_function_name -v
# Check pre-commit before committing
pre-commit run --all-files
```

**Key pitfalls**: Don't just suggest tests — run them and show output. Don't assume the environment is ready without checking. Don't commit without running pre-commit.

### Testing DataSource Properties After API Calls

When writing tests that verify data source properties (e.g. `account_id`, `user`, `type`) after an API call:
Expand Down
9 changes: 9 additions & 0 deletions .github/agents/tooling-ci-specialist.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,15 @@ pytest -k test_auth_token # Ensure auth setup runs
- Update checklist based on real issues
- Refine guidance on caching and optimization

### Lessons Learned

#### `uv sync --locked` fails after `uv lock --upgrade` (PR #2148)

- **Symptom**: `uv sync --locked` fails with "needs to be updated, but `--locked` was provided" even after running `uv lock`
- **Root cause**: New packages (e.g. `numba`/`llvmlite`) introduce fork markers with impossible platform combos (e.g. `os_name == 'nt' AND sys_platform == 'darwin'`), causing coverage check to fail
- **Fix**: Add `[tool.uv] environments` to `pyproject.toml` limiting resolution to actual target platforms, then regenerate `uv.lock`
- **Verification**: After any significant `uv lock --upgrade`, run `uv sync --locked` locally and confirm exit code 0

### Continuous Improvement

- Monitor CI run times and optimize
Expand Down
2 changes: 1 addition & 1 deletion documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ New features
Infrastructure / Support
----------------------
* Remove legacy rolling viewpoint forecasting code and utilities after migrating to fixed-point forecasting [see `PR #2082 <https://www.github.com/FlexMeasures/flexmeasures/pull/2082>`_]
* Upgraded dependencies [see `PR #2114 <https://www.github.com/FlexMeasures/flexmeasures/pull/2114>`_]
* Upgraded dependencies [see `PR #2114 <https://www.github.com/FlexMeasures/flexmeasures/pull/2114>`_ and `PR #2148 <https://www.github.com/FlexMeasures/flexmeasures/pull/2148>`_]
* Run ``flexmeasures jobs run-worker`` with RQ's embedded scheduler on by default so jobs created with ``enqueue_in`` are promoted from the scheduled registry when due; pass ``--without-scheduler`` to disable [see `PR #2112 <https://www.github.com/FlexMeasures/flexmeasures/pull/2112>`_]

Bugfixes
Expand Down
5 changes: 5 additions & 0 deletions flexmeasures/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from importlib_metadata import version, PackageNotFoundError

import numpy as np

from flexmeasures.data.models.annotations import Annotation
from flexmeasures.data.models.audit_log import AssetAuditLog
from flexmeasures.data.models.user import (
Expand All @@ -21,6 +23,9 @@

__version__ = "Unknown"

# https://github.com/sqlalchemy/sqlalchemy/discussions/11712
np.set_printoptions(legacy="1.25")

# This uses importlib.metadata behaviour added in Python 3.8
# and relies on setuptools_scm.
try:
Expand Down
2 changes: 1 addition & 1 deletion flexmeasures/utils/calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def integrate_time_series(
)

# Convert from flow to stock change, applying conversion efficiencies
stock_change = pd.Series(data=np.NaN, index=series.index)
stock_change = pd.Series(data=np.nan, index=series.index)
stock_change.loc[series > 0] = (
series[series > 0]
* (
Expand Down
16 changes: 14 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ dependencies = [
# pinned to <6.9 due to a HiGHS deadlock, see https://github.com/FlexMeasures/flexmeasures/issues/1443
"pyomo>=5.6,<6.9",
"tabulate>=0.9.0",
# 3.5.2: fixed issue with resampling to instantaneous
"timely-beliefs[forecast]>=3.5.4",
# 3.5.5: got rid of BlockManager deprecation warnings
"timely-beliefs[forecast]>=3.5.5",
"python-dotenv>=1.2.1",
# see GH#607 for issue on this pin
"sqlalchemy>=2.0",
Expand Down Expand Up @@ -263,3 +263,15 @@ addopts = "--strict-markers --ignore=docker-compose-data"
markers = [
"skip_github: skip test in GitHub Actions. Useful in case the test passes, but breaks the test suite on GH Actions."
]

# Restrict uv's dependency resolution to the three real target platforms.
# Without this, uv generates fork markers for impossible platform combinations
# (e.g. os_name == 'nt' AND sys_platform == 'darwin'), which causes
# `uv sync --locked` to fail because the fork markers don't fully cover the
# declared environment space.
[tool.uv]
environments = [
"sys_platform == 'linux'",
"sys_platform == 'darwin'",
"sys_platform == 'win32'",
]
Loading
Loading