Skip to content

Commit 3a25051

Browse files
committed
updates to instructions
1 parent 3471de3 commit 3a25051

File tree

2 files changed

+70
-18
lines changed

2 files changed

+70
-18
lines changed

.github/instructions/testing-workflow.instructions.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,22 @@ envConfig.inspect
537537
- ❌ Tests that don't clean up mocks properly
538538
- ❌ Overly complex test setup that's hard to understand
539539

540+
## 🔄 Reviewing and Improving Existing Tests
541+
542+
### Quick Review Process
543+
544+
1. **Read test files** - Check structure and mock setup
545+
2. **Run tests** - Establish baseline functionality
546+
3. **Apply improvements** - Use patterns below
547+
4. **Verify** - Ensure tests still pass
548+
549+
### Common Fixes
550+
551+
- Over-complex mocks → Minimal mocks with only needed methods
552+
- Brittle assertions → Behavior-focused with error messages
553+
- Vague test names → Clear scenario descriptions
554+
- Missing structure → Mock → Run → Assert pattern
555+
540556
## 🧠 Agent Learnings
541557

542558
- Always use dynamic path construction with Node.js `path` module when testing functions that resolve paths against workspace folders to ensure cross-platform compatibility (1)
@@ -550,3 +566,5 @@ envConfig.inspect
550566
- Create proxy abstraction functions for Node.js APIs like `cp.spawn` to enable clean testing - use function overloads to preserve Node.js's intelligent typing while making the functions mockable (1)
551567
- When unit tests fail with VS Code API errors like `TypeError: X is not a constructor` or `Cannot read properties of undefined (reading 'Y')`, check if VS Code APIs are properly mocked in `/src/test/unittests.ts` - add missing Task-related APIs (`Task`, `TaskScope`, `ShellExecution`, `TaskRevealKind`, `TaskPanelKind`) and namespace mocks (`tasks`) following the existing pattern of `mockedVSCode.X = vscodeMocks.vscMockExtHostedTypes.X` (1)
552568
- Create minimal mock objects with only required methods and use TypeScript type assertions (e.g., mockApi as PythonEnvironmentApi) to satisfy interface requirements instead of implementing all interface methods when only specific methods are needed for the test (1)
569+
- When reviewing existing tests, focus on behavior rather than implementation details in test names and assertions - transform "should return X when Y" into "should [expected behavior] when [scenario context]" (1)
570+
- Simplify mock setup by only mocking methods actually used in tests and use `as unknown as Type` for TypeScript compatibility (1)

src/test/managers/builtin/venvUtils.uvTracking.unit.test.ts

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,75 +19,109 @@ suite('venvUtils UV Environment Tracking', () => {
1919
let getWorkspacePersistentStateStub: sinon.SinonStub;
2020

2121
setup(() => {
22+
// Create minimal mock state with only required methods
2223
mockState = {
2324
get: sinon.stub(),
2425
set: sinon.stub(),
2526
clear: sinon.stub(),
2627
};
2728
getWorkspacePersistentStateStub = sinon.stub(persistentState, 'getWorkspacePersistentState');
28-
getWorkspacePersistentStateStub.returns(Promise.resolve(mockState));
29+
getWorkspacePersistentStateStub.resolves(mockState);
2930
});
3031

3132
teardown(() => {
3233
sinon.restore();
3334
});
3435

35-
test('getUvEnvironments should return empty array when no environments stored', async () => {
36+
test('should return empty array when no UV environments have been stored', async () => {
37+
// Mock - No stored environments
3638
mockState.get.withArgs(UV_ENVS_KEY).resolves(undefined);
3739

40+
// Run
3841
const result = await getUvEnvironments();
39-
assert.deepStrictEqual(result, []);
42+
43+
// Assert - Should return empty array for fresh state
44+
assert.deepStrictEqual(result, [], 'Should return empty array when no environments stored');
4045
});
4146

42-
test('getUvEnvironments should return stored environments', async () => {
43-
const expectedEnvs = ['/path/to/env1', '/path/to/env2'];
44-
mockState.get.withArgs(UV_ENVS_KEY).resolves(expectedEnvs);
47+
test('should return previously stored UV environments', async () => {
48+
// Mock - Existing stored environments
49+
const storedEnvs = ['/path/to/env1', '/path/to/env2'];
50+
mockState.get.withArgs(UV_ENVS_KEY).resolves(storedEnvs);
4551

52+
// Run
4653
const result = await getUvEnvironments();
47-
assert.deepStrictEqual(result, expectedEnvs);
54+
55+
// Assert - Should return stored environments
56+
assert.deepStrictEqual(result, storedEnvs, 'Should return all stored UV environments');
4857
});
4958

50-
test('addUvEnvironment should add new environment to list', async () => {
59+
test('should add new environment to tracking list', async () => {
60+
// Mock - Existing environment list
5161
const existingEnvs = ['/path/to/env1'];
5262
const newEnvPath = '/path/to/env2';
5363
mockState.get.withArgs(UV_ENVS_KEY).resolves(existingEnvs);
5464

65+
// Run
5566
await addUvEnvironment(newEnvPath);
5667

57-
assert.ok(mockState.set.calledWith(UV_ENVS_KEY, ['/path/to/env1', '/path/to/env2']));
68+
// Assert - Should store updated list with new environment
69+
const expectedList = ['/path/to/env1', '/path/to/env2'];
70+
assert.ok(mockState.set.calledWith(UV_ENVS_KEY, expectedList), 'Should add new environment to existing list');
5871
});
5972

60-
test('addUvEnvironment should not add duplicate environment', async () => {
73+
test('should ignore duplicate environment additions', async () => {
74+
// Mock - Environment already exists in list
6175
const existingEnvs = ['/path/to/env1', '/path/to/env2'];
6276
const duplicateEnvPath = '/path/to/env1';
6377
mockState.get.withArgs(UV_ENVS_KEY).resolves(existingEnvs);
6478

79+
// Run
6580
await addUvEnvironment(duplicateEnvPath);
6681

67-
assert.ok(mockState.set.notCalled);
82+
// Assert - Should not modify state for duplicates
83+
assert.ok(mockState.set.notCalled, 'Should not update storage when adding duplicate environment');
6884
});
6985

70-
test('removeUvEnvironment should remove environment from list', async () => {
86+
test('should remove specified environment from tracking list', async () => {
87+
// Mock - List with multiple environments
7188
const existingEnvs = ['/path/to/env1', '/path/to/env2'];
7289
const envToRemove = '/path/to/env1';
7390
mockState.get.withArgs(UV_ENVS_KEY).resolves(existingEnvs);
7491

92+
// Run
7593
await removeUvEnvironment(envToRemove);
7694

77-
assert.ok(mockState.set.calledWith(UV_ENVS_KEY, ['/path/to/env2']));
95+
// Assert - Should store filtered list without removed environment
96+
const expectedList = ['/path/to/env2'];
97+
assert.ok(
98+
mockState.set.calledWith(UV_ENVS_KEY, expectedList),
99+
'Should remove specified environment from tracking list',
100+
);
78101
});
79102

80-
test('clearUvEnvironments should set empty array', async () => {
103+
test('should clear all tracked UV environments', async () => {
104+
// Mock - (no setup needed for clear operation)
105+
106+
// Run
81107
await clearUvEnvironments();
82108

83-
assert.ok(mockState.set.calledWith(UV_ENVS_KEY, []));
109+
// Assert - Should reset to empty list
110+
assert.ok(mockState.set.calledWith(UV_ENVS_KEY, []), 'Should clear all UV environments from tracking');
84111
});
85112

86-
test('clearVenvCache should clear UV environments along with other caches', async () => {
113+
test('should include UV environments when clearing venv cache', async () => {
114+
// Mock - (no setup needed for clear operation)
115+
116+
// Run
87117
await clearVenvCache();
88118

89-
// Check that clear was called with the right keys including UV_ENVS_KEY
119+
// Assert - Should clear UV environments as part of cache clearing
120+
assert.ok(mockState.clear.called, 'Should call clear on persistent state');
90121
const clearArgs = mockState.clear.getCall(0).args[0];
91-
assert.ok(clearArgs.includes(UV_ENVS_KEY));
122+
assert.ok(
123+
Array.isArray(clearArgs) && clearArgs.includes(UV_ENVS_KEY),
124+
'Should include UV environments key in cache clearing',
125+
);
92126
});
93127
});

0 commit comments

Comments
 (0)