Skip to content

Conversation

@EwoutH
Copy link
Member

@EwoutH EwoutH commented Dec 23, 2025

Description

Reorganizes the test directory structure to mirror the source code organization in mesa/, making it easier to locate and maintain tests. If you now want to update a visualization test for example, you can dive straight into tests/visualization

Changes

  • Created tests/discrete_space/ for discrete space-related tests
  • Created tests/experimental/ for experimental module tests
  • Created tests/visualization/ for visualization-related tests
  • Created tests/examples/ for example tests
  • Kept structure flat at one level deep (no nested subdirectories)
  • Root-level module tests remain at top level

New structure & comparison

tests/
├── __init__.py
├── read_requirements.py
├── test_agent.py
├── test_batch_run.py
├── test_datacollector.py
├── test_mesa_logging.py
├── test_model.py
├── test_space.py
├── test_import_namespace.py
├── test_lifespan.py
├── discrete_space/
│   ├── test_discrete_space.py
│   ├── test_grid.py
│   ├── test_hexgrid_torus_validation.py
├── experimental/
│   ├── test_continuous_space.py
│   ├── test_devs.py
│   ├── test_mesa_signals.py
│   └── test_meta_agents.py
├── visualization/
│   ├── test_backends.py
│   ├── test_components_matplotlib.py
│   ├── test_portrayal_components.py
│   ├── test_solara_viz.py
│   ├── test_solara_viz_updated.py
│   ├── test_space_drawer.py
│   └── test_space_renderer.py
└── examples/
    ├── test_examples.py
    ├── test_examples_viz.py
    └── test_end_to_end_viz.sh
image

@EwoutH EwoutH added testing Release notes label maintenance Release notes label labels Dec 23, 2025
@github-actions

This comment was marked as off-topic.

Move tests into subdirectories (discrete_space/, experimental/, visualization/, examples/) to match the mesa/ source layout while keeping structure flat at one level deep.
@EwoutH
Copy link
Member Author

EwoutH commented Dec 23, 2025

@tpike3 @quaquel do you have any idea why Codecov keeps reporting 0% coverage on this PR? https://app.codecov.io/gh/mesa/mesa/pull/2994

Edit: Apparently patch coverage is not changed, so it should be good?

@quaquel
Copy link
Member

quaquel commented Dec 23, 2025

@EwoutH, my hunch is that because none of the source files (e.g., model.py) themselves are changed, codecov is not running.

@EwoutH EwoutH merged commit cc5565f into mesa:main Dec 23, 2025
19 of 21 checks passed
falloficarus22 added a commit to falloficarus22/mesa that referenced this pull request Dec 24, 2025
Replace pytest-cov plugin with direct coverage.py invocation to resolve
0% coverage reporting issue that occurred after moving tests into nested
subdirectories.

Changes:
- Update CI workflow to use ============================= test session starts ==============================
platform linux -- Python 3.13.11, pytest-9.0.2, pluggy-1.6.0
rootdir: /root/mesa
configfile: pyproject.toml
plugins: mock-3.15.1, anyio-4.12.0, base-url-2.1.0, playwright-0.7.2, cov-7.0.0, ipywidgets-1.55.1
collected 379 items

tests/discrete_space/test_discrete_space.py ............................ [  7%]
..                                                                       [  7%]
tests/discrete_space/test_grid.py ...................................... [ 17%]
.                                                                        [ 18%]
tests/discrete_space/test_hexgrid_torus_validation.py .                  [ 18%]
tests/examples/test_examples.py ..........                               [ 21%]
tests/examples/test_examples_viz.py .........                            [ 23%]
tests/experimental/test_continuous_space.py .......                      [ 25%]
tests/experimental/test_devs.py .....                                    [ 26%]
tests/experimental/test_mesa_signals.py .....                            [ 27%]
tests/experimental/test_meta_agents.py ...............                   [ 31%]
tests/test_agent.py ......................                               [ 37%]
tests/test_batch_run.py ........                                         [ 39%]
tests/test_datacollector.py ...............                              [ 43%]
tests/test_import_namespace.py .                                         [ 44%]
tests/test_lifespan.py ..                                                [ 44%]
tests/test_mesa_logging.py ..                                            [ 45%]
tests/test_model.py ...........                                          [ 48%]
tests/test_space.py s................................................... [ 61%]
..............................................                           [ 73%]
tests/visualization/test_backends.py ..............                      [ 77%]
tests/visualization/test_components_matplotlib.py .......                [ 79%]
tests/visualization/test_portrayal_components.py .............           [ 82%]
tests/visualization/test_solara_viz.py .........                         [ 85%]
tests/visualization/test_solara_viz_updated.py ..........                [ 87%]
tests/visualization/test_space_drawer.py ..............................  [ 95%]
tests/visualization/test_space_renderer.py ................              [100%]

=============================== warnings summary ===============================
tests/visualization/test_space_renderer.py::test_property_layer_style_instance
  /root/mesa/tests/visualization/test_space_renderer.py:200: PendingDeprecationWarning: Passing propertylayer_portrayal to draw_propertylayer() is deprecated. Use setup_propertylayer(propertylayer_portrayal) before calling draw_propertylayer().
    sr.draw_propertylayer(style)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.11-final-0 _______________

Name                                                            Stmts   Miss Branch BrPart  Cover
-------------------------------------------------------------------------------------------------
mesa/__init__.py                                                   14      0      0      0   100%
mesa/agent.py                                                     194      1     78      3    99%
mesa/batchrunner.py                                                88      2     36      4    95%
mesa/datacollection.py                                            157      4     78      4    97%
mesa/discrete_space/__init__.py                                     9      0      0      0   100%
mesa/discrete_space/cell.py                                        82      1     18      0    99%
mesa/discrete_space/cell_agent.py                                  52      0     12      0   100%
mesa/discrete_space/cell_collection.py                             56      3     18      1    95%
mesa/discrete_space/discrete_space.py                              57      3      4      1    93%
mesa/discrete_space/grid.py                                       125      6     48      5    94%
mesa/discrete_space/network.py                                     29      0      6      0   100%
mesa/discrete_space/property_layer.py                             141     11     44      3    89%
mesa/discrete_space/voronoi.py                                    144      0     46      1    99%
mesa/examples/__init__.py                                          11      0      0      0   100%
mesa/examples/advanced/__init__.py                                  0      0      0      0   100%
mesa/examples/advanced/alliance_formation/agents.py                 8      0      0      0   100%
mesa/examples/advanced/alliance_formation/app.py                   23     10      0      0    57%
mesa/examples/advanced/alliance_formation/model.py                 74      2     34      4    94%
mesa/examples/advanced/epstein_civil_violence/__init__.py           0      0      0      0   100%
mesa/examples/advanced/epstein_civil_violence/agents.py            68      0     18      1    99%
mesa/examples/advanced/epstein_civil_violence/app.py               28      5      6      2    79%
mesa/examples/advanced/epstein_civil_violence/model.py             48      9     20      5    76%
mesa/examples/advanced/pd_grid/__init__.py                          0      0      0      0   100%
mesa/examples/advanced/pd_grid/agents.py                           28      3      6      3    82%
mesa/examples/advanced/pd_grid/app.py                              11      0      0      0   100%
mesa/examples/advanced/pd_grid/model.py                            31      9     10      3    61%
mesa/examples/advanced/sugarscape_g1mt/__init__.py                  0      0      0      0   100%
mesa/examples/advanced/sugarscape_g1mt/agents.py                  101      3     22      0    94%
mesa/examples/advanced/sugarscape_g1mt/app.py                      20      2      2      0    91%
mesa/examples/advanced/sugarscape_g1mt/model.py                    52      5     10      2    85%
mesa/examples/advanced/wolf_sheep/__init__.py                       0      0      0      0   100%
mesa/examples/advanced/wolf_sheep/agents.py                        60      1     14      1    97%
mesa/examples/advanced/wolf_sheep/app.py                           34      5     10      2    84%
mesa/examples/advanced/wolf_sheep/model.py                         34      0      6      2    95%
mesa/examples/basic/__init__.py                                     0      0      0      0   100%
mesa/examples/basic/boid_flockers/__init__.py                       0      0      0      0   100%
mesa/examples/basic/boid_flockers/agents.py                        28      0      2      0   100%
mesa/examples/basic/boid_flockers/app.py                           22      1      4      1    92%
mesa/examples/basic/boid_flockers/model.py                         34      2      4      1    92%
mesa/examples/basic/boltzmann_wealth_model/__init__.py              0      0      0      0   100%
mesa/examples/basic/boltzmann_wealth_model/agents.py               18      0      4      0   100%
mesa/examples/basic/boltzmann_wealth_model/app.py                  19      2      0      0    89%
mesa/examples/basic/boltzmann_wealth_model/model.py                22      0      0      0   100%
mesa/examples/basic/boltzmann_wealth_model/st_app.py               47     47     10      0     0%
mesa/examples/basic/conways_game_of_life/__init__.py                0      0      0      0   100%
mesa/examples/basic/conways_game_of_life/agents.py                 31      2      6      0    95%
mesa/examples/basic/conways_game_of_life/app.py                    16      3      0      0    81%
mesa/examples/basic/conways_game_of_life/model.py                  13      0      2      0   100%
mesa/examples/basic/conways_game_of_life/st_app.py                 40     40     10      0     0%
mesa/examples/basic/schelling/__init__.py                           0      0      0      0   100%
mesa/examples/basic/schelling/agents.py                            22      0      6      0   100%
mesa/examples/basic/schelling/app.py                               24      1      6      0    97%
mesa/examples/basic/schelling/model.py                             24      0      4      0   100%
mesa/examples/basic/virus_on_network/__init__.py                    0      0      0      0   100%
mesa/examples/basic/virus_on_network/agents.py                     34      0     12      0   100%
mesa/examples/basic/virus_on_network/app.py                        23      6      0      0    74%
mesa/examples/basic/virus_on_network/model.py                      36      0      2      0   100%
mesa/experimental/__init__.py                                       2      0      0      0   100%
mesa/experimental/continuous_space/__init__.py                      3      0      0      0   100%
mesa/experimental/continuous_space/continuous_space.py            112      4     14      1    96%
mesa/experimental/continuous_space/continuous_space_agents.py      45      0      4      0   100%
mesa/experimental/devs/__init__.py                                  3      0      0      0   100%
mesa/experimental/devs/eventlist.py                                78      2     20      1    97%
mesa/experimental/devs/simulator.py                               112      6     28      4    93%
mesa/experimental/mesa_signals/__init__.py                          3      0      0      0   100%
mesa/experimental/mesa_signals/mesa_signal.py                     190     10     66     10    92%
mesa/experimental/mesa_signals/observable_collections.py           41      2      0      0    95%
mesa/experimental/mesa_signals/signals_util.py                     19      2      2      0    90%
mesa/experimental/meta_agents/__init__.py                           2      0      0      0   100%
mesa/experimental/meta_agents/meta_agent.py                       128      3     60      6    95%
mesa/mesa_logging.py                                               82      2     14      1    95%
mesa/model.py                                                      97      5     16      2    94%
mesa/space.py                                                     584     40    222     17    92%
mesa/visualization/__init__.py                                      8      0      0      0   100%
mesa/visualization/backends/__init__.py                             3      0      0      0   100%
mesa/visualization/backends/abstract_renderer.py                   29      1      4      1    94%
mesa/visualization/backends/altair_backend.py                     139     11     40      8    89%
mesa/visualization/backends/matplotlib_backend.py                 186     20     68      9    87%
mesa/visualization/command_console.py                             191    155     48      0    15%
mesa/visualization/components/__init__.py                          18      6      8      1    58%
mesa/visualization/components/altair_components.py                190     82     66     11    55%
mesa/visualization/components/matplotlib_components.py             59     13     18      4    73%
mesa/visualization/components/portrayal_components.py              37      2     12      2    92%
mesa/visualization/mpl_space_drawing.py                           346     83    122     31    72%
mesa/visualization/solara_viz.py                                  378    187    160     21    48%
mesa/visualization/space_drawers.py                               291      7     74     10    95%
mesa/visualization/space_renderer.py                              180     50     74     12    66%
mesa/visualization/user_param.py                                   23      2      4      1    89%
mesa/visualization/utils.py                                         4      1      0      0    75%
-------------------------------------------------------------------------------------------------
TOTAL                                                            5815    885   1762    202    82%
============= 378 passed, 1 skipped, 1 warning in 98.00s (0:01:38) ============= with
- Change pyproject.toml to use  instead of
- Add  to coverage configuration

The pytest-cov plugin had conflicts with the new nested test package
structure introduced in PR mesa#2994. Using coverage.py directly with the
--cov-context flag resolves the tracing issues.
EwoutH pushed a commit that referenced this pull request Dec 27, 2025
## Summary
Improves coverage collection after test reorganization in #2994 by adopting `pytest`'s native coverage integration and measuring all code including tests.

## Problem
After moving tests into nested subdirectories, coverage.py reported 0% coverage. The root cause was a combination of:
1. Path resolution issues with nested test packages
2. Tests not being measured in coverage reports

## Solution
This PR implements reviewer feedback to adopt coverage best practices:

### Configuration Changes (`pyproject.toml`):
- **Added `source = ["."]`**: Measures all code in the project directory
- **Kept `source_pkgs = ["mesa"]`**: Specifically tracks the mesa package
- **Added `relative_files = true`**: Fixes path resolution for nested directories
- **Removed `omit = ["tests/*"]`**: Now measures test coverage (critical for verifying all tests run)
- **Added `[tool.coverage.paths]`**: Maps installed package paths for accurate coverage reporting

### CI Changes (`.github/workflows/build_lint.yml`):
- **Replaced** `coverage run -m pytest` + `coverage xml` (2 commands from #3005)
- **With** `python -Im pytest -p pytest_cov --cov --cov-report=xml --cov-report=markdown-append:"${GITHUB_STEP_SUMMARY}" --cov-context=test tests/` (single command)
- **Benefits**:
  - `-Im` flag ensures testing installed package, not git checkout
  - `-p pytest_cov` loads plugin early to avoid import issues
  - `--cov` (no value) measures everything per coverage config
  - Markdown report appears in GitHub Actions summary (better UX)
  - `--cov-context=test` enables per-test coverage tracking

---------

Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance Release notes label testing Release notes label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants