mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add more unit tests for JupyterServerInstallation (#12675)
This commit is contained in:
@@ -55,7 +55,6 @@ export interface IJupyterServerInstallation {
|
|||||||
uninstallPipPackages(packages: PythonPkgDetails[]): Promise<void>;
|
uninstallPipPackages(packages: PythonPkgDetails[]): Promise<void>;
|
||||||
pythonExecutable: string;
|
pythonExecutable: string;
|
||||||
pythonInstallationPath: string;
|
pythonInstallationPath: string;
|
||||||
installPythonPackage(backgroundOperation: azdata.BackgroundOperation, usingExistingPython: boolean, pythonInstallationPath: string, outputChannel: vscode.OutputChannel): Promise<void>;
|
|
||||||
}
|
}
|
||||||
export class JupyterServerInstallation implements IJupyterServerInstallation {
|
export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||||
public extensionPath: string;
|
public extensionPath: string;
|
||||||
@@ -160,7 +159,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
|||||||
vscode.window.showInformationMessage(msgInstallPkgFinish);
|
vscode.window.showInformationMessage(msgInstallPkgFinish);
|
||||||
}
|
}
|
||||||
|
|
||||||
public installPythonPackage(backgroundOperation: azdata.BackgroundOperation, usingExistingPython: boolean, pythonInstallationPath: string, outputChannel: vscode.OutputChannel): Promise<void> {
|
private installPythonPackage(backgroundOperation: azdata.BackgroundOperation, usingExistingPython: boolean, pythonInstallationPath: string, outputChannel: vscode.OutputChannel): Promise<void> {
|
||||||
if (usingExistingPython) {
|
if (usingExistingPython) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
|
||||||
import * as azdata from 'azdata';
|
|
||||||
import * as should from 'should';
|
import * as should from 'should';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as TypeMoq from 'typemoq';
|
import * as TypeMoq from 'typemoq';
|
||||||
@@ -217,8 +215,7 @@ describe('Manage Package Providers', () => {
|
|||||||
getCondaExePath: () => { return ''; },
|
getCondaExePath: () => { return ''; },
|
||||||
pythonExecutable: '',
|
pythonExecutable: '',
|
||||||
pythonInstallationPath: '',
|
pythonInstallationPath: '',
|
||||||
usingConda: false,
|
usingConda: false
|
||||||
installPythonPackage: (backgroundOperation: azdata.BackgroundOperation, usingExistingPython: boolean, pythonInstallationPath: string, outputChannel: vscode.OutputChannel) => {return Promise.resolve(); }
|
|
||||||
},
|
},
|
||||||
piPyClient: {
|
piPyClient: {
|
||||||
fetchPypiPackage: (packageName) => { return Promise.resolve(); }
|
fetchPypiPackage: (packageName) => { return Promise.resolve(); }
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import * as sinon from 'sinon';
|
|||||||
import * as TypeMoq from 'typemoq';
|
import * as TypeMoq from 'typemoq';
|
||||||
import * as uuid from 'uuid';
|
import * as uuid from 'uuid';
|
||||||
import * as fs from 'fs-extra';
|
import * as fs from 'fs-extra';
|
||||||
import { JupyterServerInstallation, PythonPkgDetails } from '../../jupyter/jupyterServerInstallation';
|
import * as request from 'request';
|
||||||
|
import * as utils from '../../common/utils';
|
||||||
|
import { JupyterServerInstallation, PythonInstallSettings, PythonPkgDetails } from '../../jupyter/jupyterServerInstallation';
|
||||||
|
import { powershellDisplayName, pysparkDisplayName, python3DisplayName, sparkRDisplayName, sparkScalaDisplayName, winPlatform } from '../../common/constants';
|
||||||
|
|
||||||
describe('Jupyter Server Installation', function () {
|
describe('Jupyter Server Installation', function () {
|
||||||
let outputChannelStub: TypeMoq.IMock<vscode.OutputChannel>;
|
let outputChannelStub: TypeMoq.IMock<vscode.OutputChannel>;
|
||||||
@@ -21,12 +24,18 @@ describe('Jupyter Server Installation', function () {
|
|||||||
outputChannelStub.setup(c => c.appendLine(TypeMoq.It.isAnyString()));
|
outputChannelStub.setup(c => c.appendLine(TypeMoq.It.isAnyString()));
|
||||||
|
|
||||||
installation = new JupyterServerInstallation('', outputChannelStub.object);
|
installation = new JupyterServerInstallation('', outputChannelStub.object);
|
||||||
|
installation.execOptions = { env: Object.assign({}, process.env) };
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function (): void {
|
afterEach(function (): void {
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Getters and setters', async function() {
|
||||||
|
let pythonPath = installation.pythonInstallationPath;
|
||||||
|
should(pythonPath).be.equal(JupyterServerInstallation.getPythonInstallPath());
|
||||||
|
});
|
||||||
|
|
||||||
it('Get pip packages', async function() {
|
it('Get pip packages', async function() {
|
||||||
// Should return nothing if passed an invalid python path
|
// Should return nothing if passed an invalid python path
|
||||||
let fakePath = uuid.v4();
|
let fakePath = uuid.v4();
|
||||||
@@ -43,7 +52,7 @@ describe('Jupyter Server Installation', function () {
|
|||||||
// Should return nothing on error
|
// Should return nothing on error
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
sinon.stub(JupyterServerInstallation, 'isPythonInstalled').returns(true);
|
sinon.stub(JupyterServerInstallation, 'isPythonInstalled').returns(true);
|
||||||
sinon.stub(installation, 'executeBufferedCommand').rejects(new Error('Expected test failure.'));
|
sinon.stub(utils, 'executeBufferedCommand').rejects(new Error('Expected test failure.'));
|
||||||
pkgResult = await installation.getInstalledPipPackages();
|
pkgResult = await installation.getInstalledPipPackages();
|
||||||
should(pkgResult).not.be.undefined();
|
should(pkgResult).not.be.undefined();
|
||||||
should(pkgResult.length).be.equal(0);
|
should(pkgResult.length).be.equal(0);
|
||||||
@@ -59,13 +68,13 @@ describe('Jupyter Server Installation', function () {
|
|||||||
version: '4.5.6'
|
version: '4.5.6'
|
||||||
}];
|
}];
|
||||||
sinon.stub(JupyterServerInstallation, 'isPythonInstalled').returns(true);
|
sinon.stub(JupyterServerInstallation, 'isPythonInstalled').returns(true);
|
||||||
sinon.stub(installation, 'executeBufferedCommand').resolves(JSON.stringify(testPackages));
|
sinon.stub(utils, 'executeBufferedCommand').resolves(JSON.stringify(testPackages));
|
||||||
pkgResult = await installation.getInstalledPipPackages();
|
pkgResult = await installation.getInstalledPipPackages();
|
||||||
should(pkgResult).be.deepEqual(testPackages);
|
should(pkgResult).be.deepEqual(testPackages);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Install pip package', async function() {
|
it('Install pip package', async function() {
|
||||||
let commandStub = sinon.stub(installation, 'executeStreamedCommand').resolves();
|
let commandStub = sinon.stub(utils, 'executeStreamedCommand').resolves();
|
||||||
|
|
||||||
// Should not execute any commands when passed an empty package list
|
// Should not execute any commands when passed an empty package list
|
||||||
await installation.installPipPackages(undefined, false);
|
await installation.installPipPackages(undefined, false);
|
||||||
@@ -95,7 +104,7 @@ describe('Jupyter Server Installation', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Uninstall pip package', async function() {
|
it('Uninstall pip package', async function() {
|
||||||
let commandStub = sinon.stub(installation, 'executeStreamedCommand').resolves();
|
let commandStub = sinon.stub(utils, 'executeStreamedCommand').resolves();
|
||||||
|
|
||||||
let testPackages = [{
|
let testPackages = [{
|
||||||
name: 'jupyter',
|
name: 'jupyter',
|
||||||
@@ -120,7 +129,7 @@ describe('Jupyter Server Installation', function () {
|
|||||||
// Should return nothing on error
|
// Should return nothing on error
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
sinon.stub(fs, 'existsSync').returns(true);
|
sinon.stub(fs, 'existsSync').returns(true);
|
||||||
sinon.stub(installation, 'executeBufferedCommand').rejects(new Error('Expected test failure.'));
|
sinon.stub(utils, 'executeBufferedCommand').rejects(new Error('Expected test failure.'));
|
||||||
pkgResult = await installation.getInstalledCondaPackages();
|
pkgResult = await installation.getInstalledCondaPackages();
|
||||||
should(pkgResult).not.be.undefined();
|
should(pkgResult).not.be.undefined();
|
||||||
should(pkgResult.length).be.equal(0);
|
should(pkgResult.length).be.equal(0);
|
||||||
@@ -142,14 +151,14 @@ describe('Jupyter Server Installation', function () {
|
|||||||
channel: 'conda'
|
channel: 'conda'
|
||||||
}];
|
}];
|
||||||
sinon.stub(fs, 'existsSync').returns(true);
|
sinon.stub(fs, 'existsSync').returns(true);
|
||||||
sinon.stub(installation, 'executeBufferedCommand').resolves(JSON.stringify(testPackages));
|
sinon.stub(utils, 'executeBufferedCommand').resolves(JSON.stringify(testPackages));
|
||||||
pkgResult = await installation.getInstalledCondaPackages();
|
pkgResult = await installation.getInstalledCondaPackages();
|
||||||
let filteredPackages = testPackages.filter(pkg => pkg.channel !== 'pypi');
|
let filteredPackages = testPackages.filter(pkg => pkg.channel !== 'pypi');
|
||||||
should(pkgResult).be.deepEqual(filteredPackages);
|
should(pkgResult).be.deepEqual(filteredPackages);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Install conda package', async function() {
|
it('Install conda package', async function() {
|
||||||
let commandStub = sinon.stub(installation, 'executeStreamedCommand').resolves();
|
let commandStub = sinon.stub(utils, 'executeStreamedCommand').resolves();
|
||||||
|
|
||||||
// Should not execute any commands when passed an empty package list
|
// Should not execute any commands when passed an empty package list
|
||||||
await installation.installCondaPackages(undefined, false);
|
await installation.installCondaPackages(undefined, false);
|
||||||
@@ -179,7 +188,7 @@ describe('Jupyter Server Installation', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Uninstall conda package', async function() {
|
it('Uninstall conda package', async function() {
|
||||||
let commandStub = sinon.stub(installation, 'executeStreamedCommand').resolves();
|
let commandStub = sinon.stub(utils, 'executeStreamedCommand').resolves();
|
||||||
|
|
||||||
let testPackages = [{
|
let testPackages = [{
|
||||||
name: 'jupyter',
|
name: 'jupyter',
|
||||||
@@ -193,4 +202,101 @@ describe('Jupyter Server Installation', function () {
|
|||||||
let commandStr = commandStub.args[0][0] as string;
|
let commandStr = commandStub.args[0][0] as string;
|
||||||
should(commandStr.includes('"jupyter==1.0.0" "TestPkg2==4.5.6"')).be.true();
|
should(commandStr.includes('"jupyter==1.0.0" "TestPkg2==4.5.6"')).be.true();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Get required packages test - Undefined argument', async function() {
|
||||||
|
let packages = installation.getRequiredPackagesForKernel(undefined);
|
||||||
|
should(packages).not.be.undefined();
|
||||||
|
should(packages.length).be.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get required packages test - Fake kernel', async function() {
|
||||||
|
let packages = installation.getRequiredPackagesForKernel('NotARealKernel');
|
||||||
|
should(packages).not.be.undefined();
|
||||||
|
should(packages.length).be.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get required packages test - Python 3 kernel', async function() {
|
||||||
|
let expectedPackages: PythonPkgDetails[] = [{
|
||||||
|
name: 'jupyter',
|
||||||
|
version: '1.0.0'
|
||||||
|
}];
|
||||||
|
let packages = installation.getRequiredPackagesForKernel(python3DisplayName);
|
||||||
|
should(packages).be.deepEqual(expectedPackages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get required packages test - Powershell kernel', async function() {
|
||||||
|
let expectedPackages = [{
|
||||||
|
name: 'jupyter',
|
||||||
|
version: '1.0.0'
|
||||||
|
}, {
|
||||||
|
name: 'powershell-kernel',
|
||||||
|
version: '0.1.3'
|
||||||
|
}];
|
||||||
|
let packages = installation.getRequiredPackagesForKernel(powershellDisplayName);
|
||||||
|
should(packages).be.deepEqual(expectedPackages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get required packages test - Spark kernels', async function() {
|
||||||
|
let expectedPackages = [{
|
||||||
|
name: 'jupyter',
|
||||||
|
version: '1.0.0'
|
||||||
|
}, {
|
||||||
|
name: 'sparkmagic',
|
||||||
|
version: '0.12.9'
|
||||||
|
}, {
|
||||||
|
name: 'pandas',
|
||||||
|
version: '0.24.2'
|
||||||
|
}, {
|
||||||
|
name: 'prose-codeaccelerator',
|
||||||
|
version: '1.3.0'
|
||||||
|
}];
|
||||||
|
let packages = installation.getRequiredPackagesForKernel(pysparkDisplayName);
|
||||||
|
should(packages).be.deepEqual(expectedPackages, "Unexpected packages for PySpark kernel.");
|
||||||
|
|
||||||
|
packages = installation.getRequiredPackagesForKernel(sparkScalaDisplayName);
|
||||||
|
should(packages).be.deepEqual(expectedPackages, "Unexpected packages for Spark Scala kernel.");
|
||||||
|
|
||||||
|
packages = installation.getRequiredPackagesForKernel(sparkRDisplayName);
|
||||||
|
should(packages).be.deepEqual(expectedPackages, "Unexpected packages for Spark R kernel.");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Install python test - Run install while Python is already running', async function() {
|
||||||
|
// Should reject overwriting an existing python install if running on Windows and python is currently running.
|
||||||
|
if (process.platform === winPlatform) {
|
||||||
|
sinon.stub(utils, 'executeBufferedCommand').resolves('python.exe');
|
||||||
|
|
||||||
|
let installSettings: PythonInstallSettings = {
|
||||||
|
installPath: `${process.env['USERPROFILE']}\\ads-python`,
|
||||||
|
existingPython: false,
|
||||||
|
packages: []
|
||||||
|
};
|
||||||
|
await should(installation.startInstallProcess(false, installSettings)).be.rejected();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Install python test - Run install with existing Python instance', async function() {
|
||||||
|
let installSettings: PythonInstallSettings = {
|
||||||
|
installPath: `${process.env['USERPROFILE']}\\ads-python`,
|
||||||
|
existingPython: true,
|
||||||
|
packages: installation.getRequiredPackagesForKernel(python3DisplayName)
|
||||||
|
};
|
||||||
|
|
||||||
|
sinon.stub(utils, 'exists').resolves(true);
|
||||||
|
sinon.stub(fs, 'existsSync').returns(false);
|
||||||
|
sinon.stub(utils, 'executeBufferedCommand').resolves(`${installSettings.installPath}\\site-packages`);
|
||||||
|
|
||||||
|
// Both of these are called from upgradePythonPackages
|
||||||
|
sinon.stub(installation, 'getInstalledPipPackages').resolves([]);
|
||||||
|
let pipInstallStub = sinon.stub(installation, 'installPipPackages').resolves();
|
||||||
|
|
||||||
|
let httpRequestSpy = sinon.spy(request, 'get');
|
||||||
|
|
||||||
|
await should(installation.startInstallProcess(false, installSettings)).be.resolved();
|
||||||
|
|
||||||
|
should(httpRequestSpy.callCount).be.equal(0);
|
||||||
|
should(pipInstallStub.callCount).be.equal(1);
|
||||||
|
|
||||||
|
let packagesToInstall = pipInstallStub.firstCall.args[0] as PythonPkgDetails[];
|
||||||
|
should(packagesToInstall).be.deepEqual(installation.getRequiredPackagesForKernel(python3DisplayName));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user