You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit fcf0ce2
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: .github/commands.json
+9Lines changed: 9 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -153,5 +153,14 @@
153
153
"addLabel": "info-needed",
154
154
"removeLabel": "~confirmation-needed",
155
155
"comment": "Please diagnose the root cause of the issue by running the command `F1 > Help: Troubleshoot Issue` and following the instructions. Once you have done that, please update the issue with the results.\n\nHappy Coding!"
156
+
},
157
+
{
158
+
"type": "label",
159
+
"name": "~spam",
160
+
"removeLabel": "~spam",
161
+
"addLabel": "spam",
162
+
"action": "close",
163
+
"reason": "not_planned",
164
+
"comment": "Thank you for your submission. This issue has been closed as it doesn't meet our community guidelines or appears to be spam.\n\n**If you believe this was closed in error:**\n- Please review our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/)\n- Ensure your issue contains a clear description of the problem or feature request\n- Feel free to open a new issue with appropriate detail if this was a legitimate concern\n\n**For legitimate issues, please include:**\n- Clear description of the problem\n- Steps to reproduce (for bugs)\n- Expected vs actual behavior\n- VS Code version and environment details\n\nThank you for helping us maintain a welcoming and productive community."
Copy file name to clipboardExpand all lines: .github/instructions/testing-workflow.instructions.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -578,3 +578,4 @@ envConfig.inspect
578
578
- When mocking `testController.createTestItem()` in unit tests, use `typemoq.It.isAny()` for parameters when testing handler behavior (not ID/label generation logic), but consider using specific matchers (e.g., `It.is((id: string) => id.startsWith('_error_'))`) when the actual values being passed are important for correctness - this balances test precision with maintainability (2)
579
579
- Remove unused variables from test code immediately - leftover tracking variables like `validationCallCount` that aren't referenced indicate dead code that should be simplified (1)
580
580
- Use `Uri.file(path).fsPath` for both sides of path comparisons in tests to ensure cross-platform compatibility - Windows converts forward slashes to backslashes automatically (1)
581
+
- When tests fail with "Cannot stub non-existent property", the method likely moved to a different class during refactoring - find the class that owns the method and test that class directly instead of stubbing on the original class (1)
-`src/client/testing/testController/common/projectAdapter.ts` — `ProjectAdapter` interface (represents a single Python project with its own test infrastructure).
32
+
-`src/client/testing/testController/common/projectUtils.ts` — utilities for project ID generation, display names, and shared adapter creation.
@@ -151,6 +155,78 @@ The adapters in the extension don't implement test discovery/run logic themselve
151
155
- Settings are consumed by `src/client/testing/common/testConfigurationManager.ts`, `src/client/testing/configurationFactory.ts`, and adapters under `src/client/testing/testController/*` which read settings to build CLI args and env for subprocesses.
152
156
- The setting definitions and descriptions are in `package.json` and localized strings in `package.nls.json`.
1.**Activation**: When the extension activates, `PythonTestController` checks if the Python Environments API is available.
180
+
2.**Project discovery**: `TestProjectRegistry.discoverAndRegisterProjects()` queries the API for all Python projects in each workspace.
181
+
3.**Nested handling**: `configureNestedProjectIgnores()` identifies child projects and adds their paths to parent projects' ignore lists.
182
+
4.**Test discovery**: For each project, the controller calls `project.discoveryAdapter.discoverTests()` with the project's URI. The adapter sets `PROJECT_ROOT_PATH` environment variable for the Python runner.
183
+
5.**Python side**:
184
+
- For pytest: `get_test_root_path()` in `vscode_pytest/__init__.py` returns `PROJECT_ROOT_PATH` (if set) or falls back to `cwd`.
185
+
- For unittest: `discovery.py` uses `PROJECT_ROOT_PATH` as `top_level_dir` and `project_root_path` to root the test tree at the project directory.
186
+
6.**Test tree**: Each project gets its own root node in the Test Explorer, with test IDs scoped by project ID using the `@@vsc@@` separator (defined in `projectUtils.ts`).
187
+
188
+
### Nested project handling: pytest vs unittest
189
+
190
+
**pytest** supports the `--ignore` flag to exclude paths during test collection. When nested projects are detected, parent projects automatically receive `--ignore` flags for child project paths. This ensures each test appears under exactly one project in the test tree.
191
+
192
+
**unittest** does not support path exclusion during `discover()`. Therefore, tests in nested project directories may appear under multiple project roots (both the parent and the child project). This is **expected behavior** for unittest:
193
+
194
+
- Each project discovers and displays all tests it finds within its directory structure
195
+
- There is no deduplication or collision detection
196
+
- Users may see the same test file under multiple project roots if their project structure has nesting
197
+
198
+
This approach was chosen because:
199
+
200
+
1. unittest's `TestLoader.discover()` has no built-in path exclusion mechanism
201
+
2. Implementing custom exclusion would add significant complexity with minimal benefit
202
+
3. The existing approach is transparent and predictable - each project shows what it finds
203
+
204
+
### Empty projects and root nodes
205
+
206
+
If a project discovers zero tests, its root node will still appear in the Test Explorer as an empty folder. This ensures consistent behavior and makes it clear which projects were discovered, even if they have no tests yet.
207
+
208
+
### Logging prefix
209
+
210
+
All project-based testing logs use the `[test-by-project]` prefix for easy filtering in the output channel.
211
+
212
+
### Key files
213
+
214
+
- Python side:
215
+
-`python_files/vscode_pytest/__init__.py` — `get_test_root_path()` function and `PROJECT_ROOT_PATH` environment variable for pytest.
216
+
-`python_files/unittestadapter/discovery.py` — `discover_tests()` with `project_root_path` parameter and `PROJECT_ROOT_PATH` handling for unittest discovery.
217
+
-`python_files/unittestadapter/execution.py` — `run_tests()` with `project_root_path` parameter and `PROJECT_ROOT_PATH` handling for unittest execution.
218
+
- TypeScript: `testProjectRegistry.ts`, `projectAdapter.ts`, `projectUtils.ts`, and the discovery/execution adapters.
-`src/test/testing/testController/common/projectUtils.unit.test.ts` — Project utility function tests
224
+
-`python_files/tests/pytestadapter/test_discovery.py` — pytest PROJECT_ROOT_PATH tests (see `test_project_root_path_env_var()` and `test_symlink_with_project_root_path()`)
0 commit comments