Skip to content

Prompt to install test framework only if test frame is not installed #6768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/2 Fixes/5919.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prompt to insall test framework only if test frame is not already installed.
6 changes: 3 additions & 3 deletions src/client/testing/common/managers/baseTestManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ export abstract class BaseTestManager implements ITestManager {
sendTelemetryEvent(EventName.UNITTEST_DISCOVER, undefined, telementryProperties);
return tests;
})
.catch((reason: {}) => {
.catch(async (reason: {}) => {
if (userInitiated) {
this.testsStatusUpdaterService.updateStatusAsUnknown(this.workspaceFolder, this.tests);
}
if (isNotInstalledError(reason as Error) && !quietMode) {
if (isNotInstalledError(reason as Error) && !quietMode && !await this.installer.isInstalled(this.product, this.workspaceFolder)) {
this.installer.promptToInstall(this.product, this.workspaceFolder)
.catch(ex => traceError('isNotInstalledError', ex));
.catch(ex => traceError('isNotInstalledError', ex));
}

this.tests = undefined;
Expand Down
81 changes: 73 additions & 8 deletions src/test/testing/common/managers/baseTestManager.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@

// tslint:disable:no-any

import * as sinon from 'sinon';
import { anything, instance, mock, verify, when } from 'ts-mockito';
import { Disposable, OutputChannel, Uri } from 'vscode';
import { CommandManager } from '../../../../client/common/application/commandManager';
import { ICommandManager, IWorkspaceService } from '../../../../client/common/application/types';
import { WorkspaceService } from '../../../../client/common/application/workspace';
import { PythonSettings } from '../../../../client/common/configSettings';
import { ConfigurationService } from '../../../../client/common/configuration/service';
import { IConfigurationService, IDisposableRegistry, IOutputChannel, IPythonSettings } from '../../../../client/common/types';
import { ModuleNotInstalledError } from '../../../../client/common/errors/moduleNotInstalledError';
import { ProductInstaller } from '../../../../client/common/installer/productInstaller';
import { IConfigurationService, IDisposableRegistry, IInstaller, IOutputChannel, IPythonSettings } from '../../../../client/common/types';
import { ServiceContainer } from '../../../../client/ioc/container';
import { IServiceContainer } from '../../../../client/ioc/types';
import { CommandSource, TEST_OUTPUT_CHANNEL } from '../../../../client/testing/common/constants';
Expand All @@ -21,17 +24,19 @@ import { TestResultsService } from '../../../../client/testing/common/services/t
import { TestsStatusUpdaterService } from '../../../../client/testing/common/services/testsStatusService';
import { UnitTestDiagnosticService } from '../../../../client/testing/common/services/unitTestDiagnosticService';
import { TestsHelper } from '../../../../client/testing/common/testUtils';
import { ITestCollectionStorageService, ITestManager, ITestMessageService, ITestResultsService, ITestsHelper, ITestsStatusUpdaterService } from '../../../../client/testing/common/types';
import { ITestCollectionStorageService, ITestDiscoveryService, ITestManager, ITestMessageService, ITestResultsService, ITestsHelper, ITestsStatusUpdaterService } from '../../../../client/testing/common/types';
import { TestManager as NoseTestManager } from '../../../../client/testing/nosetest/main';
import { TestManager as PyTestTestManager } from '../../../../client/testing/pytest/main';
import { ArgumentsService } from '../../../../client/testing/pytest/services/argsService';
import { TestDiscoveryService } from '../../../../client/testing/pytest/services/discoveryService';
import { TestMessageService } from '../../../../client/testing/pytest/services/testMessageService';
import { IArgumentsService, ITestDiagnosticService, ITestManagerRunner } from '../../../../client/testing/types';
import { TestManager as UnitTestTestManager } from '../../../../client/testing/unittest/main';
import { TestManagerRunner } from '../../../../client/testing/unittest/runner';
import { noop } from '../../../core';
import { MockOutputChannel } from '../../../mockClasses';

// tslint:disable: max-func-body-length
suite('Unit Tests - Base Test Manager', () => {
[
{ name: 'nose', class: NoseTestManager },
Expand All @@ -51,6 +56,10 @@ suite('Unit Tests - Base Test Manager', () => {
let diagnosticService: ITestDiagnosticService;
let statusUpdater: ITestsStatusUpdaterService;
let commandManager: ICommandManager;
let testDiscoveryService: ITestDiscoveryService;
let installer: IInstaller;
const sandbox = sinon.createSandbox();
suiteTeardown(() => sandbox.restore());
setup(() => {
serviceContainer = mock(ServiceContainer);
settings = mock(PythonSettings);
Expand All @@ -62,6 +71,8 @@ suite('Unit Tests - Base Test Manager', () => {
diagnosticService = mock(UnitTestDiagnosticService);
statusUpdater = mock(TestsStatusUpdaterService);
commandManager = mock(CommandManager);
testDiscoveryService = mock(TestDiscoveryService);
installer = mock(ProductInstaller);

const argsService = mock(ArgumentsService);
const testsHelper = mock(TestsHelper);
Expand All @@ -83,21 +94,75 @@ suite('Unit Tests - Base Test Manager', () => {
when(serviceContainer.get<ITestManagerRunner>(ITestManagerRunner, anything())).thenReturn(instance(runner));
when(serviceContainer.get<ITestMessageService>(ITestMessageService, anything())).thenReturn(instance(messageService));

when(serviceContainer.get<ITestDiscoveryService>(ITestDiscoveryService, anything())).thenReturn(instance(testDiscoveryService));
when(serviceContainer.get<IInstaller>(IInstaller)).thenReturn(instance(installer));

when(configService.getSettings(anything())).thenReturn(instance(settings));
when(commandManager.executeCommand(anything(), anything(), anything())).thenResolve();

sandbox.restore();
sandbox.stub(item.class.prototype, 'getDiscoveryOptions').callsFake(() => ({} as any));

testManager = new item.class(workspaceFolder, workspaceFolder.fsPath, instance(serviceContainer));
});

test('Discovering tests should display test manager', async () => {
when(commandManager.executeCommand(anything(), anything(), anything())).thenResolve();
// We don't care about failures in running code
// Just test our expectations, ignore everything else.
await testManager.discoverTests(CommandSource.auto, true, true, true).catch(noop);

try {
await testManager.discoverTests(CommandSource.auto, true, true, true);
} catch {
noop();
verify(commandManager.executeCommand('setContext', 'testsDiscovered', true)).once();
});
test('When failing to discover tests prompt to install test framework', async function () {
if (item.name === 'unittest') {
// tslint:disable-next-line: no-invalid-this
return this.skip();
}

verify(commandManager.executeCommand('setContext', 'testsDiscovered', true)).once();
when(testDiscoveryService.discoverTests(anything())).thenReject(new ModuleNotInstalledError('Kaboom'));
when(installer.isInstalled(anything(), anything())).thenResolve(false);
when(installer.promptToInstall(anything(), anything())).thenResolve();

// We don't care about failures in running code
// Just test our expectations, ignore everything else.
await testManager.discoverTests(CommandSource.ui, true, false, true).catch(noop);

verify(installer.isInstalled(anything(), anything())).once();
verify(installer.promptToInstall(anything(), anything())).once();
});
test('When failing to discover tests do not prompt to install test framework', async function () {
if (item.name === 'unittest') {
// tslint:disable-next-line: no-invalid-this
return this.skip();
}

when(testDiscoveryService.discoverTests(anything())).thenReject(new Error('Kaboom'));
when(installer.isInstalled(anything(), anything())).thenResolve(false);
when(installer.promptToInstall(anything(), anything())).thenResolve();

// We don't care about failures in running code
// Just test our expectations, ignore everything else.
await testManager.discoverTests(CommandSource.ui, true, false, true).catch(noop);

verify(installer.isInstalled(anything(), anything())).never();
verify(installer.promptToInstall(anything(), anything())).never();
});
test('When failing to discover tests do not prompt to install test framework if installed', async function () {
if (item.name === 'unittest') {
// tslint:disable-next-line: no-invalid-this
return this.skip();
}

when(testDiscoveryService.discoverTests(anything())).thenReject(new ModuleNotInstalledError('Kaboom'));
when(installer.isInstalled(anything(), anything())).thenResolve(true);
when(installer.promptToInstall(anything(), anything())).thenResolve();

// We don't care about failures in running code
// Just test our expectations, ignore everything else.
await testManager.discoverTests(CommandSource.ui, true, false, true).catch(noop);

verify(installer.isInstalled(anything(), anything())).once();
verify(installer.promptToInstall(anything(), anything())).never();
});
});
});
Expand Down