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
- **Analyze Existing Tests:** Before writing new tests, study `tests/test_sync.py`, `tests/test_config.py`, and other relevant test files to understand existing patterns, fixture usage, and assertion styles.
10
+
- **Maintain Consistency:** Strive for homogeneity in test structure, naming conventions, and overall style.
11
+
- **Project Conventions:** Adhere to project-specific conventions like using `typing as t` and `pathlib.Path` for all path manipulations.
12
+
13
+
## 2. Fixture Prioritization and Usage
14
+
- **`libvcs` Fixtures First:** For any VCS-related operations (creating repos, committing, checking status), **always** prioritize using fixtures from `libvcs.pytest_plugin` (available via `vcspull/conftest.py`). Examples:
15
+
- `create_git_remote_repo`, `create_svn_remote_repo`, `create_hg_remote_repo` (and their `mercurial`/`subversion` counterparts if using those directly) for setting up test repositories.
16
+
- `git_repo`, `svn_repo`, `hg_repo` for pre-configured `Sync` objects.
17
+
- `git_commit_envvars` for environment variables needed for git commits.
18
+
- **Pytest Built-in Fixtures:** Utilize standard `pytest` fixtures like `tmp_path` for temporary files and directories.
19
+
- **Custom Project Fixtures:**
20
+
- For common non-VCS setup (e.g., mocked home/CWD, config file setup), use or create well-defined fixtures.
21
+
- Place shared fixtures in `vcspull/conftest.py` or `vcspull/tests/conftest.py`. Module-specific fixtures can reside in the test file itself.
22
+
- Example: `home_path`, `cwd_path` (refactored to use `monkeypatch`), `setup_teardown_test_config_dir`.
23
+
- **`autouse=True`:** Use sparingly, only for fixtures that genuinely apply to *all* tests within their scope.
24
+
25
+
## 3. Mocking Strategy: `monkeypatch` vs. `mocker`
26
+
- **`monkeypatch` (pytest built-in):**
27
+
- **Environment & Globals:** Use for modifying global settings, environment variables (`monkeypatch.setenv()`, `monkeypatch.delenv()`), the current working directory (`monkeypatch.chdir()`), or `sys.path`.
28
+
- **Patching Attributes/Builtins:** Use `monkeypatch.setattr()` to modify attributes of classes/objects (e.g., `pathlib.Path.home`) or to replace functions/methods in external libraries or Python builtins.
29
+
- **Dictionary Items:** Use `monkeypatch.setitem()` and `monkeypatch.delitem()` for modifying dictionaries.
30
+
- Refer to [Pytest Monkeypatch Documentation](https://docs.pytest.org/en/stable/how-to/monkeypatch.html).
31
+
- **`mocker` (from `pytest-mock`):**
32
+
- **Application Code:** Primarily use for patching functions, methods, or objects *within the `vcspull` application code itself* (e.g., `mocker.patch('vcspull.cli.add.some_function')`).
33
+
- **Assertions:** Use `mocker` when you need to assert how a mock was called, its return values, or to simulate side effects for your application's internal logic.
34
+
- **Clarity in Mocking (CRITICAL):**
35
+
- For **every** use of `mocker.patch()`, `mocker.patch.object()`, `monkeypatch.setattr()`, `monkeypatch.setenv()`, etc., include comments explaining:
36
+
- **`# WHAT:`**: What specific function, method, attribute, or environment variable is being simulated or altered.
37
+
- **`# WHY:`**: The reason for the mock – what behavior is being controlled or isolated for the test's purpose.
38
+
39
+
## 4. Test Structure and Assertions
40
+
- **Atomic Tests:** Each test function should verify a single, specific piece of functionality or scenario.
41
+
- **Clear Naming:** Test functions and fixtures should have descriptive names (e.g., `test_add_repo_new_config_cwd`).
42
+
- **Docstrings:** Test functions should have a concise docstring explaining what is being tested.
43
+
- **Plain Assertions:** Use standard `assert` statements for verifications.
44
+
- **Logging:** Use the `caplog` fixture to assert specific log messages when testing command output or internal logging.
45
+
- **Error Handling:** Explicitly test for expected exceptions using `pytest.raises()`.
46
+
47
+
## 5. Code Coverage and Quality
48
+
- **100% Coverage:** Aim for 100% test coverage for all new or modified code in `cli/add.py` and `cli/add_from_fs.py` (and any other modules).
49
+
- **Test All Paths:** Ensure tests cover success cases, failure cases, edge conditions, and all logical branches within the code.
50
+
- **Development Workflow:** Adhere to the project's quality assurance process:
51
+
```
52
+
uv run ruff check . --fix
53
+
uv run ruff format .
54
+
uv run mypy
55
+
uv run py.test --cov -v
56
+
```
57
+
(Run these commands locally to verify changes).
58
+
59
+
## 6. `vcspull`-Specific Considerations
60
+
- **Configuration Files:**
61
+
- When testing config loading, mock `find_home_config_files` appropriately.
62
+
- Use helpers like `vcspull.tests.helpers.save_config_yaml` (which internally uses `write_config`) for creating test configuration files in a controlled manner.
63
+
- **Path Expansion:** Be mindful of `expand_dir`. If testing logic that depends on its behavior, provide controlled mocks for it or ensure `home_path` / `cwd_path` fixtures correctly influence its resolution.
64
+
- **Avoid Manual VCS Subprocesses:**
65
+
- **Do not** use `subprocess.run(["git", ...])` or similar direct VCS command calls for setting up repository states in tests if a `libvcs` fixture or library function can achieve the same result.
66
+
- The only exception is when testing a function that *itself* directly uses `subprocess` (e.g., `get_git_origin_url`).
67
+
- Refactor tests like `test_add_from_fs_integration_with_libvcs` to use `create_git_remote_repo` from `libvcs` instead of manual `git init` calls via `subprocess`.
68
+
69
+
By following these rules, we can ensure that new tests are robust, maintainable, consistent with the existing test suite, and effectively leverage the capabilities of `pytest` and `libvcs`.
0 commit comments