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