Skip to content

Commit fa2760d

Browse files
Get test execution working (#9)
1 parent 8fe8f1d commit fa2760d

File tree

5 files changed

+81
-6
lines changed

5 files changed

+81
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [0.1.0] - 2025-02-14
99

1010
### Added
1111

12-
- Pytest plugin can collect jupyter notebooks and cells which use the `%%ipytest` magic
12+
- Pytest plugin collects jupyter notebooks and cells which use the `%%ipytest` magic
1313
- Published documentation for `CollectionTree`.
1414

1515
## [0.0.2] - 2025-02-12

__pyversion__

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.3
1+
0.1.0

pytest_ipynb2/plugin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,19 @@ def collect(self) -> Generator[Cell, None, None]:
4343
class Cell(pytest.Module):
4444
"""
4545
A collector for jupyter notebook cells.
46-
46+
4747
`pytest` will recognise these cells as `pytest.Module`s and use standard collection on them as it would any other
4848
python module.
4949
"""
5050

5151
def _getobj(self) -> ModuleType:
5252
notebook = self.stash[ipynb2_notebook]
53+
cellsabove = [source for cellid, source in notebook.getcodecells().items() if cellid < int(self.nodeid)]
54+
othercells = "\n".join(cellsabove)
5355
cellsource = notebook.gettestcells()[int(self.nodeid)]
5456
cellspec = importlib.util.spec_from_loader(f"Cell{self.name}", loader=None)
5557
cell = importlib.util.module_from_spec(cellspec)
56-
exec(cellsource, cell.__dict__) # noqa: S102
58+
exec(f"{othercells}\n{cellsource}", cell.__dict__) # noqa: S102
5759
return cell
5860

5961

pytest_ipynb2/pytester_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class CollectionTree:
2727
"""
2828

2929
@classmethod
30-
#TODO(MusicalNinjaDad): #8 Refactor CollectionTree.from_items to be easier to understand.
30+
# TODO(MusicalNinjaDad): #8 Refactor CollectionTree.from_items to be easier to understand.
3131
def from_items(cls, items: list[pytest.Item]) -> Self:
3232
"""Create a CollectionTree from a list of collection items, as returned by `pytester.genitems()`."""
3333

tests/test_runtests.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from pathlib import Path
2+
from typing import TYPE_CHECKING
3+
4+
import pytest
5+
6+
from pytest_ipynb2.pytester_helpers import CollectedDir, ExampleDir
7+
8+
if TYPE_CHECKING:
9+
from pytest_ipynb2.plugin import Cell
10+
11+
12+
@pytest.mark.parametrize(
13+
["example_dir", "outcomes"],
14+
[
15+
pytest.param(
16+
ExampleDir(
17+
files=[Path("tests/assets/notebook.ipynb").absolute()],
18+
conftest="pytest_plugins = ['pytest_ipynb2.plugin']",
19+
),
20+
{
21+
"passed": 2,
22+
},
23+
id="Simple Notebook",
24+
),
25+
pytest.param(
26+
ExampleDir(
27+
files=[Path("tests/assets/notebook_2tests.ipynb").absolute()],
28+
conftest="pytest_plugins = ['pytest_ipynb2.plugin']",
29+
),
30+
{
31+
"passed": 3,
32+
},
33+
id="Notebook 2 test cells",
34+
),
35+
pytest.param(
36+
ExampleDir(
37+
files=[
38+
Path("tests/assets/notebook_2tests.ipynb").absolute(),
39+
Path("tests/assets/notebook.ipynb").absolute(),
40+
],
41+
conftest="pytest_plugins = ['pytest_ipynb2.plugin']",
42+
),
43+
{
44+
"passed": 5,
45+
},
46+
id="Both notebooks - unsorted",
47+
),
48+
],
49+
indirect=["example_dir"],
50+
)
51+
def test_runtests(example_dir: CollectedDir, outcomes: dict):
52+
results = example_dir.pytester_instance.runpytest()
53+
results.assert_outcomes(**outcomes)
54+
55+
56+
@pytest.mark.parametrize(
57+
"example_dir",
58+
[
59+
pytest.param(
60+
ExampleDir(
61+
files=[Path("tests/assets/notebook.ipynb").absolute()],
62+
conftest="pytest_plugins = ['pytest_ipynb2.plugin']",
63+
),
64+
id="Simple Notebook",
65+
),
66+
],
67+
indirect=True,
68+
)
69+
def test_cellmodule_contents(example_dir: CollectedDir):
70+
cell: Cell = example_dir.items[0].parent
71+
expected_attrs = ["x", "y", "adder", "test_adder", "test_globals"]
72+
public_attrs = [attr for attr in cell._obj.__dict__ if not attr.startswith("__")] # noqa: SLF001
73+
assert public_attrs == expected_attrs

0 commit comments

Comments
 (0)