Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/test/simulation/slash-test/testGen.py.stest.ts
13394 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import * as assert from 'assert';
6
import * as path from 'path';
7
import { Intent } from '../../../src/extension/common/constants';
8
import { IQualifiedFile, IRelativeFile } from '../../../src/platform/test/node/simulationWorkspace';
9
import { toPosixPath } from '../../../src/util/vs/base/common/extpath';
10
import { Schemas } from '../../../src/util/vs/base/common/network';
11
import { isWindows } from '../../../src/util/vs/base/common/platform';
12
import { URI } from '../../../src/util/vs/base/common/uri';
13
import { ssuite, stest } from '../../base/stest';
14
import { simulateInlineChat } from '../inlineChatSimulator';
15
import { assertSomeStrings, assertWorkspaceEdit, fromFixture } from '../stestUtil';
16
import { getFileContent } from '../outcomeValidators';
17
18
ssuite({ title: '/tests', location: 'inline', language: 'python', }, () => {
19
20
stest('py with pyproject.toml', (testingServiceCollection) => {
21
return simulateInlineChat(testingServiceCollection, {
22
files: [
23
fromFixture('tests/py-pyproject-toml/', 'src/mmath/add.py'),
24
],
25
queries: [{
26
file: 'src/mmath/add.py',
27
selection: [0, 4],
28
query: '/tests',
29
expectedIntent: Intent.Tests,
30
validate: async (outcome, workspace, accessor) => {
31
assertWorkspaceEdit(outcome);
32
assert.strictEqual(outcome.files.length, 1, 'Expected one file to be created');
33
assertSomeStrings(
34
getFileContent(outcome.files[0]),
35
[
36
'import unittest',
37
'from mmath.add import add',
38
],
39
2
40
);
41
}
42
}],
43
});
44
});
45
46
stest({ description: 'select existing test file using *_test.py format', language: 'python', }, (testingServiceCollection) => {
47
return simulateInlineChat(testingServiceCollection, {
48
workspaceFolders: [
49
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py_end_test'))
50
],
51
files: [
52
fromFixture('tests/py_end_test/', 'src/ex.py'),
53
fromFixture('tests/py_end_test/', 'tests/ex_test.py'),
54
],
55
queries: [{
56
file: 'src/ex.py',
57
selection: [3, 7],
58
query: '/tests',
59
expectedIntent: Intent.Tests,
60
validate: async (outcome, workspace, accessor) => {
61
// Here the existing ex_test.py file should be found and edited for the newest test written
62
assertWorkspaceEdit(outcome);
63
assert.strictEqual(outcome.files.length, 1, 'Expected one file to be created');
64
// make sure type is IRelativeFile
65
assert.ok(outcome.files[0].hasOwnProperty('fileName'));
66
const relFile = <IRelativeFile>outcome.files[0];
67
assert.strictEqual(relFile.fileName, 'ex_test.py');
68
assert.ok(getFileContent(outcome.files[0]).includes('decimal_to_fraction'));
69
}
70
}],
71
});
72
});
73
74
stest({ description: 'test with docstring', language: 'python', }, (testingServiceCollection) => {
75
return simulateInlineChat(testingServiceCollection, {
76
workspaceFolders: [
77
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py_start_test'))
78
],
79
files: [
80
fromFixture('tests/py_start_test/', 'src/ex.py'),
81
fromFixture('tests/py_start_test/', 'tests/test_ex.py'),
82
],
83
queries: [{
84
file: 'src/ex.py',
85
selection: [3, 7],
86
query: '/tests include a docstring',
87
expectedIntent: Intent.Tests,
88
validate: async (outcome, workspace, accessor) => {
89
// Here the outcome should include a docstring as requested in the query
90
assertWorkspaceEdit(outcome);
91
assert.strictEqual((getFileContent(outcome.files[0]).match(/"""/g) || []).length, 2, 'Expected 2 instances of """ in the test file for the doc string');
92
}
93
}],
94
});
95
});
96
97
stest({ description: 'parameterized tests', language: 'python', }, (testingServiceCollection) => {
98
return simulateInlineChat(testingServiceCollection, {
99
workspaceFolders: [
100
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py_start_test'))
101
],
102
files: [
103
fromFixture('tests/py_start_test/', 'src/ex.py'),
104
fromFixture('tests/py_start_test/', 'tests/test_ex.py'),
105
],
106
queries: [{
107
file: 'src/ex.py',
108
selection: [3, 7],
109
query: '/tests make them parameterized tests',
110
expectedIntent: Intent.Tests,
111
validate: async (outcome, workspace, accessor) => {
112
// Here the outcome should include parameterized tests as requested in the query
113
assertWorkspaceEdit(outcome);
114
assert.ok(getFileContent(outcome.files[0]).includes('import pytest'), 'Expected pytest import to be included');
115
assert.ok(getFileContent(outcome.files[0]).includes('@pytest.mark.parametrize'), 'Expected parameterized test decorator to be included');
116
}
117
}],
118
});
119
});
120
121
stest({ description: 'select test folder if exists for new test files', language: 'python', }, (testingServiceCollection) => {
122
return simulateInlineChat(testingServiceCollection, {
123
workspaceFolders: [
124
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py_start_test'))
125
],
126
files: [
127
fromFixture('tests/py_start_test/', 'src/ex.py'),
128
fromFixture('tests/py_start_test/', 'src/measure.py'),
129
fromFixture('tests/py_start_test/', 'tests/test_ex.py'),
130
],
131
queries: [{
132
file: 'src/measure.py',
133
selection: [1, 3],
134
query: '/tests',
135
expectedIntent: Intent.Tests,
136
validate: async (outcome, workspace, accessor) => {
137
// Here the general expectation is that the test file should be created in the existing test folder
138
// since the workspace has ex.py and test_ex.py defined; new tests should follow existing location / naming conventions
139
assertWorkspaceEdit(outcome);
140
assert.strictEqual(outcome.files.length, 1, 'Expected one file to be created');
141
assert.ok(outcome.files[0].hasOwnProperty('uri'));
142
const relFile = <IQualifiedFile>outcome.files[0];
143
assert.ok(relFile.uri.fsPath.endsWith('/tests/'), 'Expected test file to be in the existing test folder');
144
assert.ok(relFile.uri.fsPath.endsWith('/tests/measure_test.py'), 'Expected test file to be named in the same style as existing test files');
145
146
assert.ok(getFileContent(outcome.files[0]).includes('from src.measure import cm_to_inches'), 'Expected correct import to be generated');
147
assert.ok(getFileContent(outcome.files[0]).includes('cm_to_inches'), 'Expected function to be tested to be included in the test file');
148
149
150
}
151
}],
152
});
153
});
154
155
stest({ description: 'focal file at repo root', language: 'python', }, (testingServiceCollection) => {
156
return simulateInlineChat(testingServiceCollection, {
157
workspaceFolders: [
158
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py_start_test'))
159
],
160
files: [
161
fromFixture('tests/py_repo_root/', '__init__.py'),
162
fromFixture('tests/py_repo_root/', 'temp.py'),
163
],
164
queries: [{
165
file: 'temp.py',
166
selection: [1, 24],
167
query: '/tests make them parameterized tests',
168
expectedIntent: Intent.Tests,
169
validate: async (outcome, workspace, accessor) => {
170
// Here the expectation is that the test file should be created in the root of the repo, next to the focal file
171
// since the focal file is at the root (even though __init__.py exists), relative imports are not possible
172
assertWorkspaceEdit(outcome);
173
assert.ok(outcome.files[0].hasOwnProperty('uri'), 'Expected test file to be a newly created file as no testing files exist');
174
const relFile = <IQualifiedFile>outcome.files[0];
175
assert.ok(relFile.uri.fsPath.includes('test') && relFile.uri.fsPath.includes('.py') && relFile.uri.fsPath.includes('temp'), 'Expected test file to include "test", ".py" and the name of the focal file');
176
assert.ok(getFileContent(outcome.files[0]).includes('from . import ') === false, 'Expected no "from . import" statement');
177
assert.ok(getFileContent(outcome.files[0]).includes('import .') === false, 'Expected no "import ." statement');
178
assert.ok(getFileContent(outcome.files[0]).includes('convert_temperature'), 'Expected to call the function from the focal file');
179
assert.ok(getFileContent(outcome.files[0]).includes('import'), 'Expected import to be generated as this is a new file');
180
}
181
}],
182
});
183
});
184
185
stest({ description: 'update import statement', language: 'python', }, (testingServiceCollection) => {
186
return simulateInlineChat(testingServiceCollection, {
187
workspaceFolders: [
188
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py_start_test'))
189
],
190
files: [
191
fromFixture('tests/py_start_test/', 'src/ex.py'),
192
fromFixture('tests/py_start_test/', 'tests/test_ex.py'),
193
],
194
queries: [{
195
file: 'src/ex.py',
196
selection: [3, 7],
197
query: '/tests include a docstring',
198
expectedIntent: Intent.Tests,
199
validate: async (outcome, workspace, accessor) => {
200
assertWorkspaceEdit(outcome);
201
// check that the import statement is updated when a new function is being added as a reference in the test file
202
assert.ok(outcome.files[0].hasOwnProperty('fileName'), 'Expect new file created, which makes it a IRelativeFile with a fileName');
203
assert.ok((getFileContent(outcome.files[0]).includes('from src.ex import fraction_to_decimal, decimal_to_fraction')) || (getFileContent(outcome.files[0]).includes('from .ex import fraction_to_decimal, decimal_to_fraction')), 'Expected import statement to be updated with newest function.');
204
}
205
}],
206
});
207
});
208
209
stest({ description: 'python add to existing', language: 'python' }, (testingServiceCollection) => {
210
return simulateInlineChat(testingServiceCollection, {
211
workspaceFolders: [
212
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py-pyproject-toml'))
213
],
214
files: [
215
fromFixture('tests/py-pyproject-toml/', 'src/mmath/add.py'),
216
fromFixture('tests/py-pyproject-toml/', 'src/mmath/sub.py'),
217
fromFixture('tests/py-pyproject-toml/', 'src/mmath/__init__.py'),
218
fromFixture('tests/py-pyproject-toml/', 'tests/test_sub.py'),
219
],
220
queries: [{
221
file: 'src/mmath/sub.py',
222
selection: [4, 7],
223
query: '/tests',
224
expectedIntent: Intent.Tests,
225
validate: async (outcome, workspace, accessor) => {
226
assertWorkspaceEdit(outcome);
227
if (outcome.type === 'workspaceEdit') {
228
const workspaceEdits = outcome.edits.entries();
229
assert.strictEqual(workspaceEdits.length, 1, 'Expected exactly one file to be edited');
230
const workspaceEditUri: URI = workspaceEdits[0][0];
231
// check that the file 'tests/test_sub.py' was the one edited
232
const posixPath = isWindows ? toPosixPath(workspaceEditUri.path) : workspaceEditUri.path;
233
assert.ok(posixPath.endsWith('tests/test_sub.py'), 'Expected the URI of the first edit to end with "tests/test_sub.py"');
234
}
235
}
236
}],
237
});
238
});
239
240
stest({ description: 'python correct import', language: 'python' }, (testingServiceCollection) => {
241
return simulateInlineChat(testingServiceCollection, {
242
workspaceFolders: [
243
URI.file(path.join(__dirname, '../test/simulation/fixtures/tests/py-extra-nested'))
244
],
245
files: [
246
fromFixture('tests/py-extra-nested/', 'focus_module/data_controllers/grocery.py'),
247
fromFixture('tests/py-extra-nested/', 'tests/integration/test_other.py'),
248
fromFixture('tests/py-extra-nested/', 'focus_module/data_controllers/__init__.py'),
249
],
250
queries: [{
251
file: 'focus_module/data_controllers/grocery.py',
252
selection: [6, 8],
253
query: '/tests',
254
expectedIntent: Intent.Tests,
255
validate: async (outcome, workspace, accessor) => {
256
assertWorkspaceEdit(outcome);
257
if (outcome.type === 'workspaceEdit') {
258
const workspaceEdits = outcome.edits.entries();
259
assert.strictEqual(workspaceEdits.length, 1, 'Expected exactly one file to be edited');
260
const workspaceEditUri: URI = workspaceEdits[0][0];
261
262
assert.ok(workspaceEditUri.fsPath.endsWith('test_grocery.py'), 'Expected the URI of the first edit to end with "tests/test_grocery.py"');
263
// the optimal import statement would be 'from .grocery import create_grocery_item' or 'from . import grocery'
264
assert.ok(getFileContent(outcome.files[0]).includes('from .grocery') ||
265
getFileContent(outcome.files[0]).includes('from . import grocery'));
266
}
267
}
268
}],
269
});
270
271
});
272
});
273
274
ssuite({ title: '/tests', subtitle: 'real world', location: 'inline', language: 'python', }, () => {
275
276
stest('creates new test file with test method and includes method name and test method name', (testingServiceCollection) => {
277
return simulateInlineChat(testingServiceCollection, {
278
files: [
279
fromFixture('tests/py-newtest-4658/', 'ex.py'),
280
],
281
queries: [{
282
file: 'ex.py',
283
selection: [0, 18],
284
query: '/tests',
285
expectedIntent: Intent.Tests,
286
validate: async (outcome, workspace, accessor) => {
287
assertWorkspaceEdit(outcome);
288
289
assert.strictEqual(outcome.files.length, 1);
290
291
const [first] = outcome.files;
292
assert.strictEqual((<IQualifiedFile>first).uri.scheme, Schemas.untitled);
293
assert.ok((<IQualifiedFile>first).uri.path.endsWith('test_ex.py'));
294
295
assertSomeStrings(getFileContent(first),
296
[
297
' check_skipped_condition',
298
'test_check_skipped_condition'
299
],
300
2
301
);
302
}
303
}]
304
});
305
});
306
});
307
308