Skip to content
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

Simpler smoke tests #15640

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
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
82 changes: 81 additions & 1 deletion src/test/datascience/notebook/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import {
defaultNotebookFormat,
isWebExtension
} from '../../../platform/common/constants';
import { dispose } from '../../../platform/common/utils/lifecycle';
import { dispose, type DisposableStore } from '../../../platform/common/utils/lifecycle';
import { getDisplayPath } from '../../../platform/common/platform/fs-paths';
import { IFileSystem, IPlatformService } from '../../../platform/common/platform/types';
import { GLOBAL_MEMENTO, IDisposable, IMemento } from '../../../platform/common/types';
Expand Down Expand Up @@ -982,6 +982,47 @@ export async function waitForExecutionCompletedSuccessfully(
await sleep(100);
}

export async function waitForExecutionCompletedSuccessfullyV2(
cell: NotebookCell,
disposables: IDisposable[] | DisposableStore
) {
const checkCompletedSuccessfully = () => {
traceInfo(
`10.a Check execution summary: ${cell.index}: Success = ${cell.executionSummary?.success}, order = ${cell.executionSummary?.executionOrder}, End Time = ${cell.executionSummary?.timing?.endTime}`
);
return cell.executionSummary?.success &&
cell.executionSummary.executionOrder &&
cell.executionSummary.timing?.endTime
? true
: false;
};
traceInfo(`10. Check execution summary: Check ${cell.index}`);
if (checkCompletedSuccessfully()) {
traceInfo(`11. Check execution summary: Success ${cell.index}`);
return;
}
await new Promise((resolve) => {
traceInfo(`12. Check execution summary: Event Handler Added ${cell.index}`);
const disposable = workspace.onDidChangeNotebookDocument((e) => {
if (e.notebook !== cell.notebook) {
traceInfo(`13. Check execution summary: Wrong Notebook ${cell.index}`);
return;
}
traceInfo(`14. Check execution summary: Check ${cell.index}`);
if (checkCompletedSuccessfully()) {
traceInfo(`14. Check execution summary: Resolve ${cell.index}`);
disposable.dispose();
resolve;
}
});
if (Array.isArray(disposables)) {
disposables.push(disposable);
} else {
disposables.add(disposable);
}
});
}

export async function waitForCompletions(
completionProvider: CompletionItemProvider,
cell: NotebookCell,
Expand Down Expand Up @@ -1220,6 +1261,45 @@ export async function waitForTextOutput(
.join(',\n')}`
);
}
export async function waitForTextOutputV2(
cell: NotebookCell,
text: string,
index: number = 0,
isExactMatch = true,
disposables: IDisposable[] | DisposableStore
) {
try {
traceInfo(`2. Check output in cell ${cell.index}`);
assertHasTextOutputInVSCode(cell, text, index, isExactMatch);
traceInfo(`3. Check output in cell: Success ${cell.index}`);
return;
} catch (ex) {
traceInfo(`3.a Check output in cell: Fail ${cell.index}`, ex);
//
}
await new Promise<void>((resolve) => {
traceInfo(`4. Check output in cell: Added EventHandler ${cell.index}`);
const disposable = workspace.onDidChangeNotebookDocument((e) => {
if (e.notebook !== cell.notebook) {
traceInfo(`5. Check output in cell: Wrong Notebook ${cell.index}`);
return;
}
try {
traceInfo(`6. Check output in cell: Event Received ${cell.index}`);
assertHasTextOutputInVSCode(cell, text, index, isExactMatch);
traceInfo(`7. Check output in cell: Resolved ${cell.index}`);
resolve();
} catch {
//
}
});
if (Array.isArray(disposables)) {
disposables.push(disposable);
} else {
disposables.add(disposable);
}
});
}
export function assertNotHasTextOutputInVSCode(cell: NotebookCell, text: string, index: number, isExactMatch = true) {
const cellOutputs = cell.outputs;
assert.ok(cellOutputs, 'No output');
Expand Down
41 changes: 0 additions & 41 deletions src/test/pythonFiles/datascience/simple_nb.ipynb

This file was deleted.

67 changes: 24 additions & 43 deletions src/test/smoke/datascience.smoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@

import { assert } from 'chai';
/* eslint-disable , no-invalid-this, @typescript-eslint/no-explicit-any */
import * as fs from 'fs-extra';
import * as path from '../../platform/vscode-path/path';
import * as vscode from 'vscode';
import { traceInfo } from '../../platform/logging';
import { PYTHON_PATH, setAutoSaveDelayInWorkspaceRoot, waitForCondition } from '../common.node';
import { EXTENSION_ROOT_DIR_FOR_TESTS, IS_SMOKE_TEST, JVSC_EXTENSION_ID_FOR_TESTS } from '../constants.node';
import { sleep } from '../core';
import { PYTHON_PATH, waitForCondition } from '../common.node';
import { IS_SMOKE_TEST, JVSC_EXTENSION_ID_FOR_TESTS } from '../constants.node';
import { closeActiveWindows, initialize, initializeTest } from '../initialize.node';
import { captureScreenShot } from '../common';
import { getCachedEnvironments } from '../../platform/interpreter/helpers';
import { PythonExtension, type EnvironmentPath } from '@vscode/python-extension';
import { waitForExecutionCompletedSuccessfullyV2, waitForTextOutputV2 } from '../datascience/notebook/helper';
import { DisposableStore } from '../../platform/common/utils/lifecycle';

type JupyterApi = {
openNotebook(uri: vscode.Uri, env: EnvironmentPath): Promise<void>;
Expand All @@ -22,13 +21,13 @@ type JupyterApi = {
const timeoutForCellToRun = 3 * 60 * 1_000;
suite('Smoke Tests', function () {
this.timeout(timeoutForCellToRun);
const disposableStore = new DisposableStore();
suiteSetup(async function () {
this.timeout(timeoutForCellToRun);
if (!IS_SMOKE_TEST()) {
return this.skip();
}
await initialize();
await setAutoSaveDelayInWorkspaceRoot(1);
});
setup(async function () {
traceInfo(`Start Test ${this.currentTest?.title}`);
Expand All @@ -37,6 +36,7 @@ suite('Smoke Tests', function () {
});
suiteTeardown(closeActiveWindows);
teardown(async function () {
disposableStore.clear();
traceInfo(`End Test ${this.currentTest?.title}`);
if (this.currentTest?.isFailed()) {
await captureScreenShot(this);
Expand Down Expand Up @@ -73,48 +73,29 @@ suite('Smoke Tests', function () {
// }).timeout(timeoutForCellToRun);

test('Run Cell in Notebook', async function () {
const file = path.join(
EXTENSION_ROOT_DIR_FOR_TESTS,
'src',
'test',
'pythonFiles',
'datascience',
'simple_nb.ipynb'
);
const fileContents = await fs.readFile(file, { encoding: 'utf-8' });
const outputFile = path.join(path.dirname(file), 'ds_n.log');
await fs.writeFile(file, fileContents.replace("'ds_n.log'", `'${outputFile.replace(/\\/g, '/')}'`), {
encoding: 'utf-8'
});
if (await fs.pathExists(outputFile)) {
await fs.unlink(outputFile);
}
traceInfo(`Opening notebook file ${file}`);
const notebook = await vscode.workspace.openNotebookDocument(vscode.Uri.file(file));
await vscode.window.showNotebookDocument(notebook);

let pythonPath = PYTHON_PATH;
const nb = vscode.window.activeNotebookEditor?.notebook;
if (!nb) {
throw new Error('No active notebook');
}
const pythonEnv = await PythonExtension.api().then((api) => api.environments.resolveEnvironment(pythonPath));
if (!pythonEnv) {
throw new Error(`Python environment not found ${pythonPath}`);
}
const jupyterExt = vscode.extensions.getExtension<JupyterApi>(JVSC_EXTENSION_ID_FOR_TESTS);
if (!jupyterExt) {
throw new Error('Jupyter extension not found');
}
await jupyterExt?.activate();
await jupyterExt.exports.openNotebook(nb.uri, pythonEnv);

await vscode.commands.executeCommand<void>('notebook.execute');
const checkIfFileHasBeenCreated = () => fs.pathExists(outputFile);
await waitForCondition(checkIfFileHasBeenCreated, timeoutForCellToRun, `"${outputFile}" file not created`);
const cellData = new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'print("Hello World")', 'python');
const [pythonEnv, { notebook }] = await Promise.all([
PythonExtension.api().then((api) => api.environments.resolveEnvironment(PYTHON_PATH)),
vscode.workspace
.openNotebookDocument('jupyter-notebook', new vscode.NotebookData([cellData]))
.then((notebook) => vscode.window.showNotebookDocument(notebook)),
jupyterExt.activate()
]);

// Give time for the file to be saved before we shutdown
await sleep(300);
if (!pythonEnv) {
throw new Error(`Python environment not found ${PYTHON_PATH}`);
}
await jupyterExt.exports.openNotebook(notebook.uri, pythonEnv);
traceInfo(`1. Notebook Opened`);
await Promise.all([
vscode.commands.executeCommand<void>('notebook.execute'),
waitForTextOutputV2(notebook.cellAt(0), 'Hello World', 0, false, disposableStore),
waitForExecutionCompletedSuccessfullyV2(notebook.cellAt(0), disposableStore)
]);
}).timeout(timeoutForCellToRun);

test('Interactive window should always pick up current active interpreter', async function () {
Expand Down
Loading