pytest-neon 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/PKG-INFO +26 -1
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/README.md +25 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/pyproject.toml +1 -1
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/src/pytest_neon/__init__.py +1 -1
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/src/pytest_neon/plugin.py +71 -18
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/conftest.py +7 -2
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/.env.example +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/.github/workflows/release.yml +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/.github/workflows/tests.yml +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/.gitignore +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/.neon +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/CLAUDE.md +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/LICENSE +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/src/pytest_neon/py.typed +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_branch_lifecycle.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_cli_options.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_env_var.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_fixture_errors.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_integration.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_reset_behavior.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/tests/test_skip_behavior.py +0 -0
- {pytest_neon-0.3.0 → pytest_neon-0.4.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-neon
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Pytest plugin for Neon database branch isolation in tests
|
|
5
5
|
Project-URL: Homepage, https://github.com/zain/pytest-neon
|
|
6
6
|
Project-URL: Repository, https://github.com/zain/pytest-neon
|
|
@@ -120,6 +120,7 @@ Returns a `NeonBranch` dataclass with:
|
|
|
120
120
|
- `project_id`: The Neon project ID
|
|
121
121
|
- `connection_string`: Full PostgreSQL connection URI
|
|
122
122
|
- `host`: The database host
|
|
123
|
+
- `parent_id`: The parent branch ID (used for resets)
|
|
123
124
|
|
|
124
125
|
```python
|
|
125
126
|
import os
|
|
@@ -237,6 +238,30 @@ pytest --neon-branch-expiry=0
|
|
|
237
238
|
pytest --neon-env-var=TEST_DATABASE_URL
|
|
238
239
|
```
|
|
239
240
|
|
|
241
|
+
### pyproject.toml / pytest.ini
|
|
242
|
+
|
|
243
|
+
You can also configure options in your `pyproject.toml`:
|
|
244
|
+
|
|
245
|
+
```toml
|
|
246
|
+
[tool.pytest.ini_options]
|
|
247
|
+
neon_database = "mydb"
|
|
248
|
+
neon_role = "myrole"
|
|
249
|
+
neon_keep_branches = true
|
|
250
|
+
neon_branch_expiry = "300"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Or in `pytest.ini`:
|
|
254
|
+
|
|
255
|
+
```ini
|
|
256
|
+
[pytest]
|
|
257
|
+
neon_database = mydb
|
|
258
|
+
neon_role = myrole
|
|
259
|
+
neon_keep_branches = true
|
|
260
|
+
neon_branch_expiry = 300
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Priority order**: CLI options > environment variables > ini settings > defaults
|
|
264
|
+
|
|
240
265
|
## CI/CD Integration
|
|
241
266
|
|
|
242
267
|
### GitHub Actions
|
|
@@ -78,6 +78,7 @@ Returns a `NeonBranch` dataclass with:
|
|
|
78
78
|
- `project_id`: The Neon project ID
|
|
79
79
|
- `connection_string`: Full PostgreSQL connection URI
|
|
80
80
|
- `host`: The database host
|
|
81
|
+
- `parent_id`: The parent branch ID (used for resets)
|
|
81
82
|
|
|
82
83
|
```python
|
|
83
84
|
import os
|
|
@@ -195,6 +196,30 @@ pytest --neon-branch-expiry=0
|
|
|
195
196
|
pytest --neon-env-var=TEST_DATABASE_URL
|
|
196
197
|
```
|
|
197
198
|
|
|
199
|
+
### pyproject.toml / pytest.ini
|
|
200
|
+
|
|
201
|
+
You can also configure options in your `pyproject.toml`:
|
|
202
|
+
|
|
203
|
+
```toml
|
|
204
|
+
[tool.pytest.ini_options]
|
|
205
|
+
neon_database = "mydb"
|
|
206
|
+
neon_role = "myrole"
|
|
207
|
+
neon_keep_branches = true
|
|
208
|
+
neon_branch_expiry = "300"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Or in `pytest.ini`:
|
|
212
|
+
|
|
213
|
+
```ini
|
|
214
|
+
[pytest]
|
|
215
|
+
neon_database = mydb
|
|
216
|
+
neon_role = myrole
|
|
217
|
+
neon_keep_branches = true
|
|
218
|
+
neon_branch_expiry = 300
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Priority order**: CLI options > environment variables > ini settings > defaults
|
|
222
|
+
|
|
198
223
|
## CI/CD Integration
|
|
199
224
|
|
|
200
225
|
### GitHub Actions
|
|
@@ -30,9 +30,10 @@ class NeonBranch:
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def pytest_addoption(parser: pytest.Parser) -> None:
|
|
33
|
-
"""Add Neon-specific command line options."""
|
|
33
|
+
"""Add Neon-specific command line options and ini settings."""
|
|
34
34
|
group = parser.getgroup("neon", "Neon database branching")
|
|
35
35
|
|
|
36
|
+
# CLI options
|
|
36
37
|
group.addoption(
|
|
37
38
|
"--neon-api-key",
|
|
38
39
|
dest="neon_api_key",
|
|
@@ -51,13 +52,11 @@ def pytest_addoption(parser: pytest.Parser) -> None:
|
|
|
51
52
|
group.addoption(
|
|
52
53
|
"--neon-database",
|
|
53
54
|
dest="neon_database",
|
|
54
|
-
default="neondb",
|
|
55
55
|
help="Database name (default: neondb)",
|
|
56
56
|
)
|
|
57
57
|
group.addoption(
|
|
58
58
|
"--neon-role",
|
|
59
59
|
dest="neon_role",
|
|
60
|
-
default="neondb_owner",
|
|
61
60
|
help="Database role (default: neondb_owner)",
|
|
62
61
|
)
|
|
63
62
|
group.addoption(
|
|
@@ -70,7 +69,6 @@ def pytest_addoption(parser: pytest.Parser) -> None:
|
|
|
70
69
|
"--neon-branch-expiry",
|
|
71
70
|
dest="neon_branch_expiry",
|
|
72
71
|
type=int,
|
|
73
|
-
default=DEFAULT_BRANCH_EXPIRY_SECONDS,
|
|
74
72
|
help=(
|
|
75
73
|
f"Branch auto-expiry in seconds "
|
|
76
74
|
f"(default: {DEFAULT_BRANCH_EXPIRY_SECONDS}). Set to 0 to disable."
|
|
@@ -79,19 +77,62 @@ def pytest_addoption(parser: pytest.Parser) -> None:
|
|
|
79
77
|
group.addoption(
|
|
80
78
|
"--neon-env-var",
|
|
81
79
|
dest="neon_env_var",
|
|
82
|
-
default="DATABASE_URL",
|
|
83
80
|
help="Environment variable to set with connection string (default: DATABASE_URL)", # noqa: E501
|
|
84
81
|
)
|
|
85
82
|
|
|
83
|
+
# INI file settings (pytest.ini, pyproject.toml, etc.)
|
|
84
|
+
parser.addini("neon_api_key", "Neon API key", default=None)
|
|
85
|
+
parser.addini("neon_project_id", "Neon project ID", default=None)
|
|
86
|
+
parser.addini("neon_parent_branch", "Parent branch ID", default=None)
|
|
87
|
+
parser.addini("neon_database", "Database name", default="neondb")
|
|
88
|
+
parser.addini("neon_role", "Database role", default="neondb_owner")
|
|
89
|
+
parser.addini(
|
|
90
|
+
"neon_keep_branches",
|
|
91
|
+
"Don't delete branches after tests",
|
|
92
|
+
type="bool",
|
|
93
|
+
default=False,
|
|
94
|
+
)
|
|
95
|
+
parser.addini(
|
|
96
|
+
"neon_branch_expiry",
|
|
97
|
+
"Branch auto-expiry in seconds",
|
|
98
|
+
default=str(DEFAULT_BRANCH_EXPIRY_SECONDS),
|
|
99
|
+
)
|
|
100
|
+
parser.addini(
|
|
101
|
+
"neon_env_var",
|
|
102
|
+
"Environment variable for connection string",
|
|
103
|
+
default="DATABASE_URL",
|
|
104
|
+
)
|
|
105
|
+
|
|
86
106
|
|
|
87
107
|
def _get_config_value(
|
|
88
|
-
config: pytest.Config,
|
|
108
|
+
config: pytest.Config,
|
|
109
|
+
option: str,
|
|
110
|
+
env_var: str,
|
|
111
|
+
ini_name: str | None = None,
|
|
112
|
+
default: str | None = None,
|
|
89
113
|
) -> str | None:
|
|
90
|
-
"""Get config value from CLI option, env var, or default.
|
|
114
|
+
"""Get config value from CLI option, env var, ini setting, or default.
|
|
115
|
+
|
|
116
|
+
Priority order: CLI option > environment variable > ini setting > default
|
|
117
|
+
"""
|
|
118
|
+
# 1. CLI option (highest priority)
|
|
91
119
|
value = config.getoption(option, default=None)
|
|
92
120
|
if value is not None:
|
|
93
121
|
return value
|
|
94
|
-
|
|
122
|
+
|
|
123
|
+
# 2. Environment variable
|
|
124
|
+
env_value = os.environ.get(env_var)
|
|
125
|
+
if env_value is not None:
|
|
126
|
+
return env_value
|
|
127
|
+
|
|
128
|
+
# 3. INI setting (pytest.ini, pyproject.toml, etc.)
|
|
129
|
+
if ini_name is not None:
|
|
130
|
+
ini_value = config.getini(ini_name)
|
|
131
|
+
if ini_value:
|
|
132
|
+
return ini_value
|
|
133
|
+
|
|
134
|
+
# 4. Default
|
|
135
|
+
return default
|
|
95
136
|
|
|
96
137
|
|
|
97
138
|
def _create_neon_branch(
|
|
@@ -104,20 +145,32 @@ def _create_neon_branch(
|
|
|
104
145
|
"""
|
|
105
146
|
config = request.config
|
|
106
147
|
|
|
107
|
-
api_key = _get_config_value(config, "neon_api_key", "NEON_API_KEY")
|
|
108
|
-
project_id = _get_config_value(
|
|
148
|
+
api_key = _get_config_value(config, "neon_api_key", "NEON_API_KEY", "neon_api_key")
|
|
149
|
+
project_id = _get_config_value(
|
|
150
|
+
config, "neon_project_id", "NEON_PROJECT_ID", "neon_project_id"
|
|
151
|
+
)
|
|
109
152
|
parent_branch_id = _get_config_value(
|
|
110
|
-
config, "neon_parent_branch", "NEON_PARENT_BRANCH_ID"
|
|
153
|
+
config, "neon_parent_branch", "NEON_PARENT_BRANCH_ID", "neon_parent_branch"
|
|
111
154
|
)
|
|
112
155
|
database_name = _get_config_value(
|
|
113
|
-
config, "neon_database", "NEON_DATABASE", "neondb"
|
|
156
|
+
config, "neon_database", "NEON_DATABASE", "neon_database", "neondb"
|
|
114
157
|
)
|
|
115
|
-
role_name = _get_config_value(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
158
|
+
role_name = _get_config_value(
|
|
159
|
+
config, "neon_role", "NEON_ROLE", "neon_role", "neondb_owner"
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# For boolean/int options, check CLI first, then ini
|
|
163
|
+
keep_branches = config.getoption("neon_keep_branches", default=None)
|
|
164
|
+
if keep_branches is None:
|
|
165
|
+
keep_branches = config.getini("neon_keep_branches")
|
|
166
|
+
|
|
167
|
+
branch_expiry = config.getoption("neon_branch_expiry", default=None)
|
|
168
|
+
if branch_expiry is None:
|
|
169
|
+
branch_expiry = int(config.getini("neon_branch_expiry"))
|
|
170
|
+
|
|
171
|
+
env_var_name = _get_config_value(
|
|
172
|
+
config, "neon_env_var", "", "neon_env_var", "DATABASE_URL"
|
|
119
173
|
)
|
|
120
|
-
env_var_name = config.getoption("neon_env_var", default="DATABASE_URL")
|
|
121
174
|
|
|
122
175
|
if not api_key:
|
|
123
176
|
pytest.skip(
|
|
@@ -301,7 +354,7 @@ def neon_branch(
|
|
|
301
354
|
conn_string = neon_branch.connection_string
|
|
302
355
|
"""
|
|
303
356
|
config = request.config
|
|
304
|
-
api_key = _get_config_value(config, "neon_api_key", "NEON_API_KEY")
|
|
357
|
+
api_key = _get_config_value(config, "neon_api_key", "NEON_API_KEY", "neon_api_key")
|
|
305
358
|
|
|
306
359
|
# Validate that branch has a parent for reset functionality
|
|
307
360
|
if not _neon_branch_for_reset.parent_id:
|
|
@@ -19,8 +19,13 @@ from pytest_neon.plugin import NeonBranch
|
|
|
19
19
|
@pytest.fixture(scope="module")
|
|
20
20
|
def neon_branch(request):
|
|
21
21
|
"""Mock neon_branch fixture for testing."""
|
|
22
|
-
keep_branches = request.config.getoption("neon_keep_branches", default=
|
|
23
|
-
|
|
22
|
+
keep_branches = request.config.getoption("neon_keep_branches", default=None)
|
|
23
|
+
if keep_branches is None:
|
|
24
|
+
keep_branches = False
|
|
25
|
+
|
|
26
|
+
env_var_name = request.config.getoption("neon_env_var", default=None)
|
|
27
|
+
if env_var_name is None:
|
|
28
|
+
env_var_name = "DATABASE_URL"
|
|
24
29
|
|
|
25
30
|
branch_info = NeonBranch(
|
|
26
31
|
branch_id="br-mock-123",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|