Skip to content

Commit 479932a

Browse files
dmadisettipre-commit-ci[bot]akshayka
authored
feat: release pytest from experimental (#4467)
## 📝 Summary Added docs and flipped the flag for pytest run @akshayka OR @mscolnick --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Akshay Agrawal <akshay@marimo.io>
1 parent e2e100a commit 479932a

File tree

16 files changed

+102
-35
lines changed

16 files changed

+102
-35
lines changed

docs/guides/testing/pytest.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,48 @@
1-
# Running unit tests with pytest
1+
# Testing with pytest
2+
3+
## Testing in notebook
4+
5+
Be default, marimo detects and runs tests in your notebooks automatically. If
6+
the optional `pytest` library is installed, marimo will run `pytest` on any cells that
7+
contain test functions (functions that start with `test_`) or test classes
8+
(classes that start with `Test`) on a per cell basis.
9+
10+
For example,
11+
12+
/// marimo-embed
13+
14+
```python
15+
@app.cell
16+
def __():
17+
import pytest
18+
def inc(x):
19+
return x + 1
20+
return inc, pytest
21+
22+
@app.cell
23+
def __(inc, pytest):
24+
def test_fails():
25+
assert inc(3) == 5, "This test fails"
26+
27+
def test_sanity():
28+
assert inc(3) == 4, "This test passes"
29+
30+
class TestBlock:
31+
@pytest.mark.parametrize(("x", "y"), [(3, 4), (4, 5)])
32+
def test_parameterized(x, y):
33+
assert inc(x) == y
34+
return
35+
```
36+
37+
///
38+
39+
!!! note "Reactive tests can be disabled"
40+
41+
You can disable this behavior with the runtime.reactive_test option in the
42+
configuration file.
43+
44+
45+
## Testing at the command-line
246

347
Since marimo notebooks are Python programs, you can test them using
448
[`pytest`](https://docs.pytest.org/en/stable/), a popular testing framework

frontend/src/components/app-config/optional-features.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ const OPTIONAL_DEPENDENCIES: OptionalFeature[] = [
8181
additionalPackageInstalls: [],
8282
description: "Export as IPYNB",
8383
},
84+
{
85+
id: "testing",
86+
packagesRequired: [{ name: "pytest" }],
87+
additionalPackageInstalls: [],
88+
description: "Autorun unit tests",
89+
},
8490
];
8591

8692
if (getFeatureFlag("lsp")) {

frontend/src/components/app-config/user-config-form.tsx

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,37 @@ export const UserConfigForm: React.FC = () => {
914914
</div>
915915
)}
916916
/>
917+
<FormField
918+
control={form.control}
919+
name="runtime.reactive_tests"
920+
render={({ field }) => (
921+
<div className="flex flex-col gap-y-1">
922+
<FormItem className={formItemClasses}>
923+
<FormLabel className="font-normal">
924+
Autorun Unit Tests
925+
</FormLabel>
926+
<FormControl>
927+
<Checkbox
928+
data-testid="reactive-test-checkbox"
929+
checked={field.value === true}
930+
onCheckedChange={field.onChange}
931+
/>
932+
</FormControl>
933+
</FormItem>
934+
<IsOverridden
935+
userConfig={config}
936+
name="runtime.reactive_tests"
937+
/>
938+
<FormMessage />
939+
<FormDescription>
940+
Enable reactive pytest tests in notebook. When a cell
941+
contains only test functions (test_*) and classes (Test_*),
942+
marimo will automatically run them with pytest (requires
943+
notebook restart).
944+
</FormDescription>{" "}
945+
</div>
946+
)}
947+
/>
917948

918949
<FormDescription>
919950
Learn more in the{" "}
@@ -1324,31 +1355,6 @@ export const UserConfigForm: React.FC = () => {
13241355
</div>
13251356
)}
13261357
/>
1327-
<FormField
1328-
control={form.control}
1329-
name="experimental.reactive_tests"
1330-
render={({ field }) => (
1331-
<div className="flex flex-col gap-y-1">
1332-
<FormItem className={formItemClasses}>
1333-
<FormLabel className="font-normal">
1334-
Autorun Unit Tests
1335-
</FormLabel>
1336-
<FormControl>
1337-
<Checkbox
1338-
data-testid="reactive-test-checkbox"
1339-
checked={field.value === true}
1340-
onCheckedChange={field.onChange}
1341-
/>
1342-
</FormControl>
1343-
</FormItem>
1344-
<FormDescription>
1345-
Enable experimental reactive pytest tests in notebook. When
1346-
a cell contains only test functions and classes, marimo will
1347-
automatically run relevant tests.
1348-
</FormDescription>{" "}
1349-
</div>
1350-
)}
1351-
/>
13521358
<FormField
13531359
control={form.control}
13541360
name="experimental.toplevel_defs"

frontend/src/components/editor/__tests__/data-attributes.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ describe("Cell data attributes", () => {
5454
auto_reload: "off",
5555
on_cell_change: "lazy",
5656
watcher_on_save: "lazy",
57+
reactive_tests: true,
5758
output_max_bytes: 1_000_000,
5859
std_stream_max_bytes: 1_000_000,
5960
pythonpath: [],
@@ -65,7 +66,7 @@ describe("Cell data attributes", () => {
6566
},
6667
save: { autosave: "off", autosave_delay: 1000, format_on_save: false },
6768
ai: {},
68-
};
69+
} as UserConfig;
6970

7071
const { container } = render(
7172
<TooltipProvider>

marimo/_ast/app_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Copyright 2025 Marimo. All rights reserved.
12
from dataclasses import asdict, dataclass, field
23
from typing import Any, Literal, Optional
34

marimo/_config/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class RuntimeConfig(TypedDict):
107107
- `auto_reload`: if `lazy`, cells importing modified modules will marked
108108
as stale; if `autorun`, affected cells will be automatically run. similar
109109
to IPython's %autoreload extension but with more code intelligence.
110+
- `reactive_tests`: if `True`, marimo will automatically run pytest on cells containing only test functions and test classes.
111+
execution.
110112
- `on_cell_change`: if `lazy`, cells will be marked stale when their
111113
ancestors run but won't autorun; if `autorun`, cells will automatically
112114
run when their ancestors run.
@@ -130,6 +132,7 @@ class RuntimeConfig(TypedDict):
130132

131133
auto_instantiate: bool
132134
auto_reload: Literal["off", "lazy", "autorun"]
135+
reactive_tests: bool
133136
on_cell_change: OnCellChangeType
134137
watcher_on_save: Literal["lazy", "autorun"]
135138
output_max_bytes: int
@@ -401,6 +404,7 @@ class PartialMarimoConfig(TypedDict, total=False):
401404
"runtime": {
402405
"auto_instantiate": True,
403406
"auto_reload": "off",
407+
"reactive_tests": True,
404408
"on_cell_change": "autorun",
405409
"watcher_on_save": "lazy",
406410
"output_max_bytes": int(

marimo/_runtime/runtime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ def __init__(
515515
self._original_environ = os.environ.copy()
516516

517517
# Adds in a post_execution hook to run pytest immediately
518-
if user_config.get("experimental", {}).get("reactive_tests", False):
518+
if user_config["runtime"].get("reactive_tests", False):
519519
from marimo._runtime.runner.hooks_post_execution import (
520520
_attempt_pytest,
521521
)

marimo/_server/print.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def print_experimental_features(config: MarimoConfig) -> None:
117117
"tracing",
118118
"markdown",
119119
"sql_engines",
120+
"reactive_tests",
120121
}
121122
keys = keys - finished_experiments
122123

openapi/api.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,8 @@ components:
15271527
items:
15281528
type: string
15291529
type: array
1530+
reactive_tests:
1531+
type: boolean
15301532
std_stream_max_bytes:
15311533
type: integer
15321534
watcher_on_save:
@@ -1537,6 +1539,7 @@ components:
15371539
required:
15381540
- auto_instantiate
15391541
- auto_reload
1542+
- reactive_tests
15401543
- on_cell_change
15411544
- watcher_on_save
15421545
- output_max_bytes
@@ -2500,7 +2503,7 @@ components:
25002503
type: object
25012504
info:
25022505
title: marimo API
2503-
version: 0.12.6
2506+
version: 0.12.7
25042507
openapi: 3.1.0
25052508
paths:
25062509
/@file/{filename_and_length}:

openapi/src/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,6 +2968,7 @@ export interface components {
29682968
on_cell_change: "lazy" | "autorun";
29692969
output_max_bytes: number;
29702970
pythonpath?: string[];
2971+
reactive_tests: boolean;
29712972
std_stream_max_bytes: number;
29722973
/** @enum {string} */
29732974
watcher_on_save: "lazy" | "autorun";

0 commit comments

Comments
 (0)