diff --git a/package.json b/package.json index 70225cf..e2efa00 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,8 @@ "onCommand:java.test.explorer.refresh", "onCommand:java.test.explorer.run", "onCommand:java.test.explorer.debug", + "onCommand:java.test.editor.run", + "onCommand:java.test.editor.debug", "onCommand:java.test.run", "onCommand:java.test.debug", "onCommand:java.test.cancel", @@ -148,6 +150,14 @@ "command": "java.test.explorer.debugAll", "when": "java:serverMode != LightWeight" }, + { + "command": "java.test.editor.run", + "when": "java:serverMode != LightWeight" + }, + { + "command": "java.test.editor.debug", + "when": "java:serverMode != LightWeight" + }, { "command": "java.test.relaunch", "when": "java:serverMode != LightWeight" @@ -203,6 +213,16 @@ "icon": "$(debug-restart)", "category": "Java" }, + { + "command": "java.test.editor.run", + "title": "%contributes.commands.java.test.editor.run.title%", + "category": "Java" + }, + { + "command": "java.test.editor.debug", + "title": "%contributes.commands.java.test.editor.debug.title%", + "category": "Java" + }, { "command": "java.test.cancel", "title": "%contributes.commands.java.test.cancel.title%", @@ -351,7 +371,7 @@ "items": { "type": "string" }, - "description": "%configuration.java.test.config.vmargs.description%", + "description": "%configuration.java.test.config.vmArgs.description%", "default": [] }, "args": { diff --git a/package.nls.json b/package.nls.json index e832f63..4b015ce 100644 --- a/package.nls.json +++ b/package.nls.json @@ -9,6 +9,8 @@ "contributes.commands.java.test.explorer.run.config.title": "Run With Configuration", "contributes.commands.java.test.explorer.debug.config.title": "Debug With Configuration", "contributes.commands.java.test.show.report.title": "Show Test Report", + "contributes.commands.java.test.editor.run.title": "Run Tests", + "contributes.commands.java.test.editor.debug.title": "Debug Tests", "contributes.commands.java.test.relaunch.title": "Relaunch the Tests", "contributes.commands.java.test.cancel.title": "Cancel Test Job", "contributes.commands.java.test.explorer.refresh.title": "Refresh", diff --git a/package.nls.zh.json b/package.nls.zh.json index beccc82..c871c32 100644 --- a/package.nls.zh.json +++ b/package.nls.zh.json @@ -9,6 +9,8 @@ "contributes.commands.java.test.explorer.run.config.title": "根据配置文件运行", "contributes.commands.java.test.explorer.debug.config.title": "根据配置文件调试", "contributes.commands.java.test.show.report.title": "显示测试报告", + "contributes.commands.java.test.editor.run.title": "运行测试用例", + "contributes.commands.java.test.editor.debug.title": "调试测试用例", "contributes.commands.java.test.relaunch.title": "重新执行测试任务", "contributes.commands.java.test.cancel.title": "取消测试任务", "contributes.commands.java.test.explorer.refresh.title": "刷新", diff --git a/src/commands/runFromUri.ts b/src/commands/runFromUri.ts new file mode 100644 index 0000000..6e0f126 --- /dev/null +++ b/src/commands/runFromUri.ts @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as path from 'path'; +import { Uri, window, workspace } from 'vscode'; +import { ITestItem, TestLevel } from '../protocols'; +import { IRunnerContext } from '../runners/models'; +import { runnerScheduler } from '../runners/runnerScheduler'; +import { testItemModel } from '../testItemModel'; + +export async function executeTestsFromUri(uri: Uri | undefined, isDebug: boolean): Promise { + if (!uri) { + if (!window.activeTextEditor) { + return; + } + uri = window.activeTextEditor.document.uri; + } + + if (uri.scheme !== 'file' || path.extname(uri.fsPath) !== '.java') { + return; + } + + if (!workspace.getWorkspaceFolder(uri)) { + window.showInformationMessage(`The file: '${uri.fsPath}' does not belong to the current workspace.`); + return; + } + + const tests: ITestItem[] = await testItemModel.getItemsForCodeLens(uri); + const testItemForPrimaryType: ITestItem | undefined = tests.find((test: ITestItem) => { + return test.level === TestLevel.Class; + }); + + if (!testItemForPrimaryType) { + window.showInformationMessage(`No tests in file: '${uri.fsPath}'.`); + return; + } + + const runnerContext: IRunnerContext = { + scope: testItemForPrimaryType.level, + testUri: testItemForPrimaryType.location.uri, + fullName: testItemForPrimaryType.fullName, + kind: testItemForPrimaryType.kind, + projectName: testItemForPrimaryType.project, + tests: [testItemForPrimaryType], + isDebug, + }; + + await runnerScheduler.run(runnerContext); +} diff --git a/src/constants/commands.ts b/src/constants/commands.ts index 183ca15..6ade314 100644 --- a/src/constants/commands.ts +++ b/src/constants/commands.ts @@ -20,6 +20,8 @@ export namespace JavaTestRunnerCommands { export const RUN_TEST_FROM_CODELENS: string = 'java.test.run'; export const DEBUG_TEST_FROM_CODELENS: string = 'java.test.debug'; export const RUN_TEST_FROM_EXPLORER: string = 'java.test.explorer.run'; + export const RUN_TEST_FROM_EDITOR: string = 'java.test.editor.run'; + export const DEBUG_TEST_FROM_EDITOR: string = 'java.test.editor.debug'; export const DEBUG_ALL_TEST_FROM_EXPLORER: string = 'java.test.explorer.debugAll'; export const RUN_ALL_TEST_FROM_EXPLORER: string = 'java.test.explorer.runAll'; export const DEBUG_TEST_FROM_EXPLORER: string = 'java.test.explorer.debug'; diff --git a/src/extension.ts b/src/extension.ts index 22f243f..c40eb04 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,6 +10,7 @@ import { testCodeLensController } from './codelens/TestCodeLensController'; import { debugTestsFromExplorer, openTextDocument, runTestsFromExplorer } from './commands/explorerCommands'; import { openLogFile, showOutputChannel } from './commands/logCommands'; import { runFromCodeLens } from './commands/runFromCodeLens'; +import { executeTestsFromUri } from './commands/runFromUri'; import { JavaTestRunnerCommands } from './constants/commands'; import { testExplorer } from './explorer/testExplorer'; import { logger } from './logger/logger'; @@ -100,6 +101,8 @@ async function doActivate(_operationId: string, context: ExtensionContext): Prom instrumentOperationAsVsCodeCommand(JavaTestRunnerCommands.OPEN_TEST_LOG, async () => await openLogFile(storagePath)), instrumentOperationAsVsCodeCommand(JavaTestRunnerCommands.JAVA_TEST_CANCEL, async () => await runnerScheduler.cleanUp(true /* isCancel */)), instrumentOperationAsVsCodeCommand(JavaTestRunnerCommands.JAVA_CONFIG_MIGRATE, async () => await migrateTestConfig()), + instrumentOperationAsVsCodeCommand(JavaTestRunnerCommands.RUN_TEST_FROM_EDITOR, async (uri?: Uri) => await executeTestsFromUri(uri, false /* isDebug */)), + instrumentOperationAsVsCodeCommand(JavaTestRunnerCommands.DEBUG_TEST_FROM_EDITOR, async (uri?: Uri) => await executeTestsFromUri(uri, true /* isDebug */)), ); } diff --git a/src/testItemModel.ts b/src/testItemModel.ts index 61cce15..6ac55de 100644 --- a/src/testItemModel.ts +++ b/src/testItemModel.ts @@ -32,7 +32,7 @@ class TestItemModel implements Disposable { return this.save(tests); } - public async getItemsForCodeLens(uri: Uri, token: CancellationToken): Promise { + public async getItemsForCodeLens(uri: Uri, token?: CancellationToken): Promise { const result: ITestItem[] = await searchTestCodeLens(uri.toString(), token); return this.save(result); } diff --git a/src/utils/commandUtils.ts b/src/utils/commandUtils.ts index 3399405..407aa5e 100644 --- a/src/utils/commandUtils.ts +++ b/src/utils/commandUtils.ts @@ -22,9 +22,13 @@ export async function searchTestItemsAll(request: ISearchTestItemParams, token: JavaTestRunnerDelegateCommands.SEARCH_TEST_ITEMS_ALL, JSON.stringify(request), token) || []; } -export async function searchTestCodeLens(uri: string, token: CancellationToken): Promise { +export async function searchTestCodeLens(uri: string, token?: CancellationToken): Promise { + if (token) { + return await executeJavaLanguageServerCommand( + JavaTestRunnerDelegateCommands.SEARCH_TEST_CODE_LENS, uri, token) || []; + } return await executeJavaLanguageServerCommand( - JavaTestRunnerDelegateCommands.SEARCH_TEST_CODE_LENS, uri, token) || []; + JavaTestRunnerDelegateCommands.SEARCH_TEST_CODE_LENS, uri) || []; } export async function searchTestLocation(fullName: string): Promise { diff --git a/test/gradle-junit5-suite/index.ts b/test/gradle-junit5-suite/index.ts index 7948be6..c00addb 100644 --- a/test/gradle-junit5-suite/index.ts +++ b/test/gradle-junit5-suite/index.ts @@ -23,11 +23,9 @@ export function run(testsRoot: string, cb: (error: any, failures?: number) => vo try { // Run the mocha test - mocha - .run(failures => { - cb(null, failures); - }); - + mocha.run(failures => { + cb(null, failures); + }); } catch (err) { cb(err); } diff --git a/test/gradle-junit5-suite/runFromEditor.test.ts b/test/gradle-junit5-suite/runFromEditor.test.ts new file mode 100644 index 0000000..9e01d29 --- /dev/null +++ b/test/gradle-junit5-suite/runFromEditor.test.ts @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as assert from 'assert'; +import { commands, TextDocument, window, workspace, extensions } from 'vscode'; +import { testResultManager, ITestResult, TestStatus } from '../../extension.bundle'; +import { Uris } from '../shared'; + +suite('Run from Editor Tests', function() { + + suiteSetup(async function() { + await extensions.getExtension('vscjava.vscode-java-test')!.activate(); + }); + + test("Can run from active editor", async function() { + const document: TextDocument = await workspace.openTextDocument(Uris.GRADLE_JUNIT5_META_ANNOTATION_TEST); + await window.showTextDocument(document); + + await commands.executeCommand('java.test.editor.run'); + + const detail: ITestResult| undefined = testResultManager.getResultById(`junit5@junit5.MetaAnnotationTest#myFastTest`); + assert.strictEqual(detail!.status, TestStatus.Pass); + }); + + teardown(async function() { + // Clear the result cache + testResultManager.dispose(); + await commands.executeCommand('workbench.action.closeActiveEditor'); + }); +});