From ca0fa174f3de6587b344d221f253f6aa0becba2e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:46:45 -0700 Subject: [PATCH 01/18] flask and django tests --- src/test/debugger/web.framework.test.ts | 153 ++++++++++++++++++ .../workspace5/djangoApp/home/__init__.py | 0 .../djangoApp/home/templates/index.html | 9 ++ .../workspace5/djangoApp/home/urls.py | 7 + .../workspace5/djangoApp/home/views.py | 10 ++ .../workspace5/djangoApp/manage.py | 22 +++ .../workspace5/djangoApp/mysite/__init__.py | 0 .../workspace5/djangoApp/mysite/settings.py | 93 +++++++++++ .../workspace5/djangoApp/mysite/urls.py | 23 +++ .../workspace5/djangoApp/mysite/wsgi.py | 16 ++ .../workspace5/flaskApp/run.py | 13 ++ .../workspace5/flaskApp/templates/index.html | 9 ++ 12 files changed, 355 insertions(+) create mode 100644 src/test/debugger/web.framework.test.ts create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/__init__.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/views.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/manage.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/__init__.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py create mode 100644 src/testMultiRootWkspc/workspace5/flaskApp/run.py create mode 100644 src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts new file mode 100644 index 000000000000..e4f752678664 --- /dev/null +++ b/src/test/debugger/web.framework.test.ts @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal + +import { expect } from 'chai'; +import * as fs from 'fs'; +import * as getFreePort from 'get-port'; +import * as path from 'path'; +import { DebugClient } from 'vscode-debugadapter-testsupport'; +import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; +import { noop } from '../../client/common/core.utils'; +import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; +import { sleep } from '../common'; +import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; +import { DEBUGGER_TIMEOUT } from './common/constants'; +import { continueDebugging, createDebugAdapter, ExpectedVariable, hitHttpBreakpoint, makeHttpRequest, validateVariablesInFrame } from './utils'; + +let testCounter = 0; +const debuggerType = 'pythonExperimental'; +suite(`Django and Flask Debugging: ${debuggerType}`, () => { + let debugClient: DebugClient; + setup(async function () { + if (!IS_MULTI_ROOT_TEST || !TEST_DEBUGGER) { + this.skip(); + } + this.timeout(5 * DEBUGGER_TIMEOUT); + const coverageDirectory = path.join(EXTENSION_ROOT_DIR, `debug_coverage_django_flask${testCounter += 1}`); + debugClient = await createDebugAdapter(coverageDirectory); + }); + teardown(async function () { + if (this.currentTest.state !== 'passed') { + console.log(this.currentTest.title); + console.log(fs.readFileSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log')).toString()); + } + // Wait for a second before starting another test (sometimes, sockets take a while to get closed). + await sleep(1000); + try { + await debugClient.stop().catch(noop); + // tslint:disable-next-line:no-empty + } catch (ex) { } + await sleep(1000); + }); + function buildLaunchArgs(workspaceDirectory: string): LaunchRequestArguments { + const env = {}; + // tslint:disable-next-line:no-string-literal + env['PYTHONPATH'] = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd'); + + // tslint:disable-next-line:no-unnecessary-local-variable + const options: LaunchRequestArguments = { + cwd: workspaceDirectory, + program: '', + debugOptions: [DebugOptions.RedirectOutput], + pythonPath: 'python', + args: [], + env, + envFile: '', + logToFile: true, + type: debuggerType + }; + + return options; + } + async function buildFlaskLaunchArgs(workspaceDirectory: string) { + const port = await getFreePort({ host: 'localhost' }); + const options = buildLaunchArgs(workspaceDirectory); + + options.env!['FLASK_APP'] = path.join(workspaceDirectory, 'run.py'); + options.module = 'flask'; + options.debugOptions = [DebugOptions.RedirectOutput, DebugOptions.Jinja]; + options.args = [ + 'run', + '--no-debugger', + '--no-reload', + '--port', + `${port}` + ]; + + return { options, port }; + } + async function buildDjangoLaunchArgs(workspaceDirectory: string) { + const port = await getFreePort({ host: 'localhost' }); + const options = buildLaunchArgs(workspaceDirectory); + + options.program = path.join(workspaceDirectory, 'manage.py'); + options.debugOptions = [DebugOptions.RedirectOutput, DebugOptions.Django]; + options.args = [ + 'runserver', + '--noreload', + '--nothreading', + `${port}` + ]; + + return { options, port }; + } + + async function testTemplateDebugging(launchArgs: LaunchRequestArguments, port: number, viewFile: string, viewLine: number, templateFile: string, templateLine: number) { + await Promise.all([ + debugClient.configurationSequence(), + debugClient.launch(launchArgs), + debugClient.waitForEvent('initialized'), + debugClient.waitForEvent('process'), + debugClient.waitForEvent('thread') + ]); + + const httpResult = await makeHttpRequest(`http://localhost:${port}`); + + expect(httpResult).to.contain('Hello this_is_a_value_from_server'); + expect(httpResult).to.contain('Hello this_is_another_value_from_server'); + + await hitHttpBreakpoint(debugClient, `http://localhost:${port}`, viewFile, viewLine); + + await continueDebugging(debugClient); + await debugClient.setBreakpointsRequest({ breakpoints: [], lines: [], source: { path: viewFile } }); + + // Template debugging. + const [stackTrace, htmlResultPromise] = await hitHttpBreakpoint(debugClient, `http://localhost:${port}`, templateFile, templateLine); + + // Wait for breakpoint to hit + const expectedVariables: ExpectedVariable[] = [ + { name: 'value_from_server', type: 'str', value: '\'this_is_a_value_from_server\'' }, + { name: 'another_value_from_server', type: 'str', value: '\'this_is_another_value_from_server\'' } + ]; + await validateVariablesInFrame(debugClient, stackTrace, expectedVariables, 1); + + await debugClient.setBreakpointsRequest({ breakpoints: [], lines: [], source: { path: templateFile } }); + await continueDebugging(debugClient); + + const htmlResult = await htmlResultPromise; + expect(htmlResult).to.contain('Hello this_is_a_value_from_server'); + expect(htmlResult).to.contain('Hello this_is_another_value_from_server'); + } + + test('Test Flask Route and Template debugging', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); + const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); + + await testTemplateDebugging(options, port, + path.join(workspaceDirectory, 'run.py'), 7, + path.join(workspaceDirectory, 'templates', 'index.html'), 6); + }); + + test('Test Django Route and Template debugging', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); + const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); + + await testTemplateDebugging(options, port, + path.join(workspaceDirectory, 'home', 'views.py'), 10, + path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); + }); +}); diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/__init__.py b/src/testMultiRootWkspc/workspace5/djangoApp/home/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html b/src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html new file mode 100644 index 000000000000..6ca5107d23d6 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html @@ -0,0 +1,9 @@ + + + + +

Hello {{ value_from_server }}!

+

Hello {{ another_value_from_server }}!

+ + + diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py b/src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py new file mode 100644 index 000000000000..70a9606e88e6 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url('', views.index, name='index'), +] diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/views.py b/src/testMultiRootWkspc/workspace5/djangoApp/home/views.py new file mode 100644 index 000000000000..0494f868dc6f --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/home/views.py @@ -0,0 +1,10 @@ +from django.shortcuts import render +from django.template import loader + + +def index(request): + context = { + 'value_from_server':'this_is_a_value_from_server', + 'another_value_from_server':'this_is_another_value_from_server' + } + return render(request, 'index.html', context) diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/manage.py b/src/testMultiRootWkspc/workspace5/djangoApp/manage.py new file mode 100644 index 000000000000..afbc784aafd8 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/__init__.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py new file mode 100644 index 000000000000..4e182517ca2a --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py @@ -0,0 +1,93 @@ +""" +Django settings for mysite project. + +Generated by 'django-admin startproject' using Django 1.11.2. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '5u06*)07dvd+=kn)zqp8#b0^qt@*$8=nnjc&&0lzfc28(wns&l' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['localhost', '127.0.0.1'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.contenttypes', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ +] + +ROOT_URLCONF = 'mysite.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': ['home/templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'mysite.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py new file mode 100644 index 000000000000..9db383365e3e --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py @@ -0,0 +1,23 @@ +"""mysite URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url, include +from django.contrib import admin +from django.views.generic import RedirectView + +urlpatterns = [ + url(r'^home/', include('home.urls')), + url('', RedirectView.as_view(url='/home/')), +] diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py new file mode 100644 index 000000000000..74e7daeefe76 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for mysite project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") + +application = get_wsgi_application() diff --git a/src/testMultiRootWkspc/workspace5/flaskApp/run.py b/src/testMultiRootWkspc/workspace5/flaskApp/run.py new file mode 100644 index 000000000000..9c3172c3e918 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/flaskApp/run.py @@ -0,0 +1,13 @@ +from flask import Flask, render_template +app = Flask(__name__) + + +@app.route('/') +def hello(): + return render_template('index.html', + value_from_server='this_is_a_value_from_server', + another_value_from_server='this_is_another_value_from_server') + + +if __name__ == '__main__': + app.run() diff --git a/src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html b/src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html new file mode 100644 index 000000000000..6ca5107d23d6 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html @@ -0,0 +1,9 @@ + + + + +

Hello {{ value_from_server }}!

+

Hello {{ another_value_from_server }}!

+ + + From 0717b8ab7150beccd27b4657e1ec574ca8c16766 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:47:50 -0700 Subject: [PATCH 02/18] add flask and django requirements --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index e7f764089ecf..439a8d6999b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,5 @@ pytest fabric numba rope +flask +django From 102e4b5f704562971fe1bd202fa3b8ee10537dbb Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:52:08 -0700 Subject: [PATCH 03/18] fix typo --- src/test/debugger/web.framework.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index e4f752678664..b941a560bad0 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -46,7 +46,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { function buildLaunchArgs(workspaceDirectory: string): LaunchRequestArguments { const env = {}; // tslint:disable-next-line:no-string-literal - env['PYTHONPATH'] = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd'); + env['PYTHONPATH'] = '/home/don/Desktop/development/vscode/ptvsd'; // tslint:disable-next-line:no-unnecessary-local-variable const options: LaunchRequestArguments = { From b446c390b875222316cfe0cf1216b7b7567cad75 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:52:49 -0700 Subject: [PATCH 04/18] run only django tests --- src/test/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/index.ts b/src/test/index.ts index 135ca5d8b6c1..464caac75c18 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -13,7 +13,7 @@ process.env.IS_MULTI_ROOT_TEST = IS_MULTI_ROOT_TEST.toString(); // If running on CI server and we're running the debugger tests, then ensure we only run debug tests. // We do this to ensure we only run debugger test, as debugger tests are very flaky on CI. // So the solution is to run them separately and first on CI. -const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : undefined; +const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : 'Django and Flask Debugging'; // You can directly control Mocha options by uncommenting the following lines. // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info. @@ -23,7 +23,7 @@ const options: MochaSetupOptions & { retries: number } = { useColors: true, timeout: 25000, retries: 3, - grep + grep: 'Django and Flask Debugging' }; testRunner.configure(options, { coverageConfig: '../coverconfig.json' }); module.exports = testRunner; From 957ef09e695a759b43c65728e436f34b1ce0a516 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:55:23 -0700 Subject: [PATCH 05/18] fix typo --- src/test/debugger/web.framework.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index b941a560bad0..e4f752678664 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -46,7 +46,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { function buildLaunchArgs(workspaceDirectory: string): LaunchRequestArguments { const env = {}; // tslint:disable-next-line:no-string-literal - env['PYTHONPATH'] = '/home/don/Desktop/development/vscode/ptvsd'; + env['PYTHONPATH'] = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd'); // tslint:disable-next-line:no-unnecessary-local-variable const options: LaunchRequestArguments = { From 3a9e297be38026e316d60dc59904aeda02d9e2f4 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:29:30 -0700 Subject: [PATCH 06/18] more logging --- src/test/debugger/web.framework.test.ts | 48 ++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index e4f752678664..2aadbd2d0065 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -3,9 +3,10 @@ 'use strict'; -// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal +// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal no-console import { expect } from 'chai'; +import { spawn } from 'child_process'; import * as fs from 'fs'; import * as getFreePort from 'get-port'; import * as path from 'path'; @@ -133,6 +134,37 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { expect(htmlResult).to.contain('Hello this_is_another_value_from_server'); } + test('Dummy test', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); + const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); + const env = { ...process.env, ...options.env }; + console.log('step1'); + const proc = spawn('python', ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); + console.log('step2'); + proc.stdout.on('data', data => { + console.log(data.toString()); + }); + proc.stderr.on('data', data => { + console.error(data.toString()); + }); + proc.on('error', error => { + console.error(error); + }); + proc.on('close', () => { + console.error('closed'); + }); + proc.on('exit', () => { + console.error('exit'); + }); + console.log('step3'); + await sleep(3000); + console.log('step4'); + const httpResult = await makeHttpRequest(`http://localhost:${port}`); + console.log('step5'); + console.log(httpResult); + console.log('step6'); + }); + test('Test Flask Route and Template debugging', async () => { const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); @@ -142,12 +174,12 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { path.join(workspaceDirectory, 'templates', 'index.html'), 6); }); - test('Test Django Route and Template debugging', async () => { - const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); - const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); + // test('Test Django Route and Template debugging', async () => { + // const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); + // const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); - await testTemplateDebugging(options, port, - path.join(workspaceDirectory, 'home', 'views.py'), 10, - path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); - }); + // await testTemplateDebugging(options, port, + // path.join(workspaceDirectory, 'home', 'views.py'), 10, + // path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); + // }); }); From a426fb987163f1bc288071450e9a5fb8ad918d2b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:33:06 -0700 Subject: [PATCH 07/18] prefix pip with python -m --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fee4079ea762..1eb64ae75600 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,8 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: - - pip install --upgrade -r requirements.txt - - pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ + - python - m pip install --upgrade -r requirements.txt + - python - m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn script: From 8f58935d446b935154f1f740bfc50ebb8367b427 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:37:04 -0700 Subject: [PATCH 08/18] oops --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1eb64ae75600..915c33dd9cad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,8 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: - - python - m pip install --upgrade -r requirements.txt - - python - m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ + - python -m pip install --upgrade -r requirements.txt + - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn script: From 0a508a429f7528b97846464dea6a0deb8776256a Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:43:23 -0700 Subject: [PATCH 09/18] more changes --- src/test/debugger/utils.ts | 3 +++ src/test/debugger/web.framework.test.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/debugger/utils.ts b/src/test/debugger/utils.ts index ad59a2fd98e5..adc4a532221a 100644 --- a/src/test/debugger/utils.ts +++ b/src/test/debugger/utils.ts @@ -69,6 +69,9 @@ export async function validateVariablesInFrame(debugClient: DebugClient, export function makeHttpRequest(uri: string): Promise { return new Promise((resolve, reject) => { request.get(uri, (error: any, response: request.Response, body: any) => { + if (error) { + return reject(error); + } if (response.statusCode !== 200) { reject(new Error(`Status code = ${response.statusCode}`)); } else { diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index 2aadbd2d0065..0a9cf4f21065 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -32,7 +32,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { debugClient = await createDebugAdapter(coverageDirectory); }); teardown(async function () { - if (this.currentTest.state !== 'passed') { + if (this.currentTest.state !== 'passed' && fs.existsSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log'))) { console.log(this.currentTest.title); console.log(fs.readFileSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log')).toString()); } From 8de002af43ed1ef2364727797e2bbb9f53ee3388 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:51:31 -0700 Subject: [PATCH 10/18] more changes --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 915c33dd9cad..413bca964319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,9 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: + - which python + - python --version + - python -m pip --version - python -m pip install --upgrade -r requirements.txt - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn From 981d00915dfc1d17e89242a3c05f3bb8ac726330 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 18:04:22 -0700 Subject: [PATCH 11/18] get right python path from test environment --- src/test/common.ts | 11 +++++++++++ src/test/debugger/web.framework.test.ts | 6 +++--- src/test/initialize.ts | 13 +------------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/common.ts b/src/test/common.ts index e399012adf2c..5f6d6640e709 100644 --- a/src/test/common.ts +++ b/src/test/common.ts @@ -7,6 +7,8 @@ import { IS_MULTI_ROOT_TEST } from './initialize'; const fileInNonRootWorkspace = path.join(__dirname, '..', '..', 'src', 'test', 'pythonFiles', 'dummy.py'); export const rootWorkspaceUri = getWorkspaceRoot(); +export const PYTHON_PATH = getPythonPath(); + export type PythonSettingKeys = 'workspaceSymbols.enabled' | 'pythonPath' | 'linting.lintOnSave' | 'linting.enabled' | 'linting.pylintEnabled' | @@ -118,3 +120,12 @@ const globalPythonPathSetting = workspace.getConfiguration('python').inspect('py export const clearPythonPathInWorkspaceFolder = async (resource: string | Uri) => retryAsync(setPythonPathInWorkspace)(resource, ConfigurationTarget.WorkspaceFolder); export const setPythonPathInWorkspaceRoot = async (pythonPath: string) => retryAsync(setPythonPathInWorkspace)(undefined, ConfigurationTarget.Workspace, pythonPath); export const resetGlobalPythonPathSetting = async () => retryAsync(restoreGlobalPythonPathSetting)(); + +function getPythonPath(): string { + // tslint:disable-next-line:no-unsafe-any + if (process.env.TRAVIS_PYTHON_PATH && fs.existsSync(process.env.TRAVIS_PYTHON_PATH)) { + // tslint:disable-next-line:no-unsafe-any + return process.env.TRAVIS_PYTHON_PATH; + } + return 'python'; +} diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index 0a9cf4f21065..b31c7fa5ab72 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -14,7 +14,7 @@ import { DebugClient } from 'vscode-debugadapter-testsupport'; import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; import { noop } from '../../client/common/core.utils'; import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; -import { sleep } from '../common'; +import { PYTHON_PATH, sleep } from '../common'; import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { DEBUGGER_TIMEOUT } from './common/constants'; import { continueDebugging, createDebugAdapter, ExpectedVariable, hitHttpBreakpoint, makeHttpRequest, validateVariablesInFrame } from './utils'; @@ -54,7 +54,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { cwd: workspaceDirectory, program: '', debugOptions: [DebugOptions.RedirectOutput], - pythonPath: 'python', + pythonPath: PYTHON_PATH, args: [], env, envFile: '', @@ -139,7 +139,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); const env = { ...process.env, ...options.env }; console.log('step1'); - const proc = spawn('python', ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); + const proc = spawn(PYTHON_PATH, ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); console.log('step2'); proc.stdout.on('data', data => { console.log(data.toString()); diff --git a/src/test/initialize.ts b/src/test/initialize.ts index 5914d38185e9..f3cba26217bc 100644 --- a/src/test/initialize.ts +++ b/src/test/initialize.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { PythonSettings } from '../client/common/configSettings'; import { activated } from '../client/extension'; -import { clearPythonPathInWorkspaceFolder, resetGlobalPythonPathSetting, setPythonPathInWorkspaceRoot } from './common'; +import { clearPythonPathInWorkspaceFolder, PYTHON_PATH, resetGlobalPythonPathSetting, setPythonPathInWorkspaceRoot } from './common'; export * from './constants'; @@ -16,8 +16,6 @@ const workspace3Uri = vscode.Uri.file(path.join(multirootPath, 'workspace3')); //First thing to be executed. process.env['VSC_PYTHON_CI_TEST'] = '1'; -const PYTHON_PATH = getPythonPath(); - // Ability to use custom python environments for testing export async function initializePython() { await resetGlobalPythonPathSetting(); @@ -48,12 +46,3 @@ export async function closeActiveWindows(): Promise { // tslint:disable-next-line:no-unnecessary-callback-wrapper .then(() => resolve(), reject)); } - -function getPythonPath(): string { - // tslint:disable-next-line:no-unsafe-any - if (process.env.TRAVIS_PYTHON_PATH && fs.existsSync(process.env.TRAVIS_PYTHON_PATH)) { - // tslint:disable-next-line:no-unsafe-any - return process.env.TRAVIS_PYTHON_PATH; - } - return 'python'; -} From 1c614e3bc5f9b8b3b691828c62a6c987563fbf1e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 18:12:37 -0700 Subject: [PATCH 12/18] revert unnecessary changes --- src/test/debugger/web.framework.test.ts | 53 ++++--------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index b31c7fa5ab72..ca3ca6c6a19f 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -6,8 +6,6 @@ // tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal no-console import { expect } from 'chai'; -import { spawn } from 'child_process'; -import * as fs from 'fs'; import * as getFreePort from 'get-port'; import * as path from 'path'; import { DebugClient } from 'vscode-debugadapter-testsupport'; @@ -31,11 +29,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { const coverageDirectory = path.join(EXTENSION_ROOT_DIR, `debug_coverage_django_flask${testCounter += 1}`); debugClient = await createDebugAdapter(coverageDirectory); }); - teardown(async function () { - if (this.currentTest.state !== 'passed' && fs.existsSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log'))) { - console.log(this.currentTest.title); - console.log(fs.readFileSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log')).toString()); - } + teardown(async () => { // Wait for a second before starting another test (sometimes, sockets take a while to get closed). await sleep(1000); try { @@ -134,37 +128,6 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { expect(htmlResult).to.contain('Hello this_is_another_value_from_server'); } - test('Dummy test', async () => { - const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); - const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); - const env = { ...process.env, ...options.env }; - console.log('step1'); - const proc = spawn(PYTHON_PATH, ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); - console.log('step2'); - proc.stdout.on('data', data => { - console.log(data.toString()); - }); - proc.stderr.on('data', data => { - console.error(data.toString()); - }); - proc.on('error', error => { - console.error(error); - }); - proc.on('close', () => { - console.error('closed'); - }); - proc.on('exit', () => { - console.error('exit'); - }); - console.log('step3'); - await sleep(3000); - console.log('step4'); - const httpResult = await makeHttpRequest(`http://localhost:${port}`); - console.log('step5'); - console.log(httpResult); - console.log('step6'); - }); - test('Test Flask Route and Template debugging', async () => { const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); @@ -174,12 +137,12 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { path.join(workspaceDirectory, 'templates', 'index.html'), 6); }); - // test('Test Django Route and Template debugging', async () => { - // const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); - // const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); + test('Test Django Route and Template debugging', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); + const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); - // await testTemplateDebugging(options, port, - // path.join(workspaceDirectory, 'home', 'views.py'), 10, - // path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); - // }); + await testTemplateDebugging(options, port, + path.join(workspaceDirectory, 'home', 'views.py'), 10, + path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); + }); }); From 4ab004cf1e73cf5490c294866c050d44e9771359 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 19:02:19 -0700 Subject: [PATCH 13/18] revert unnecessary changes --- .travis.yml | 3 --- src/test/index.ts | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 413bca964319..915c33dd9cad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,9 +36,6 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: - - which python - - python --version - - python -m pip --version - python -m pip install --upgrade -r requirements.txt - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn diff --git a/src/test/index.ts b/src/test/index.ts index 464caac75c18..135ca5d8b6c1 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -13,7 +13,7 @@ process.env.IS_MULTI_ROOT_TEST = IS_MULTI_ROOT_TEST.toString(); // If running on CI server and we're running the debugger tests, then ensure we only run debug tests. // We do this to ensure we only run debugger test, as debugger tests are very flaky on CI. // So the solution is to run them separately and first on CI. -const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : 'Django and Flask Debugging'; +const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : undefined; // You can directly control Mocha options by uncommenting the following lines. // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info. @@ -23,7 +23,7 @@ const options: MochaSetupOptions & { retries: number } = { useColors: true, timeout: 25000, retries: 3, - grep: 'Django and Flask Debugging' + grep }; testRunner.configure(options, { coverageConfig: '../coverconfig.json' }); module.exports = testRunner; From 8fa9ed2372a60b799bd74aac25361d2af21ca106 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 19:35:03 -0700 Subject: [PATCH 14/18] :bug: use the right python version when running tests on Travis --- .../codeExecution/djangoShellCodeExecution.ts | 9 ++-- src/test/common/moduleInstaller.test.ts | 4 +- src/test/debugger/attach.ptvsd.test.ts | 4 +- src/test/debugger/attach.test.ts | 4 +- src/test/debugger/capabilities.test.ts | 3 +- src/test/debugger/misc.test.ts | 4 +- src/test/debugger/module.test.ts | 4 +- src/test/debugger/portAndHost.test.ts | 3 +- .../interpreters/interpreterVersion.test.ts | 9 ++-- .../interpreters/virtualEnvManager.test.ts | 13 ++--- .../shebangCodeLenseProvider.test.ts | 14 +++--- .../djangoShellCodeExect.test.ts | 5 +- .../codeExecution/terminalCodeExec.test.ts | 47 ++++++++++--------- 13 files changed, 64 insertions(+), 59 deletions(-) diff --git a/src/client/terminals/codeExecution/djangoShellCodeExecution.ts b/src/client/terminals/codeExecution/djangoShellCodeExecution.ts index 5fbe2ef2d19f..4fc230b6e21a 100644 --- a/src/client/terminals/codeExecution/djangoShellCodeExecution.ts +++ b/src/client/terminals/codeExecution/djangoShellCodeExecution.ts @@ -10,14 +10,13 @@ import { ICommandManager, IDocumentManager, IWorkspaceService } from '../../comm import '../../common/extensions'; import { IFileSystem, IPlatformService } from '../../common/platform/types'; import { ITerminalServiceFactory } from '../../common/terminal/types'; -import { IConfigurationService } from '../../common/types'; -import { IDisposableRegistry } from '../../common/types'; +import { IConfigurationService, IDisposableRegistry } from '../../common/types'; import { DjangoContextInitializer } from './djangoContext'; import { TerminalCodeExecutionProvider } from './terminalCodeExecution'; @injectable() export class DjangoShellCodeExecutionProvider extends TerminalCodeExecutionProvider { - constructor( @inject(ITerminalServiceFactory) terminalServiceFactory: ITerminalServiceFactory, + constructor(@inject(ITerminalServiceFactory) terminalServiceFactory: ITerminalServiceFactory, @inject(IConfigurationService) configurationService: IConfigurationService, @inject(IWorkspaceService) workspace: IWorkspaceService, @inject(IDocumentManager) documentManager: IDocumentManager, @@ -30,10 +29,10 @@ export class DjangoShellCodeExecutionProvider extends TerminalCodeExecutionProvi this.terminalTitle = 'Django Shell'; disposableRegistry.push(new DjangoContextInitializer(documentManager, workspace, fileSystem, commandManager)); } - public getReplCommandArgs(resource?: Uri): { command: string, args: string[] } { + public getReplCommandArgs(resource?: Uri): { command: string; args: string[] } { const pythonSettings = this.configurationService.getSettings(resource); const command = this.platformService.isWindows ? pythonSettings.pythonPath.replace(/\\/g, '/') : pythonSettings.pythonPath; - const args = pythonSettings.terminal.launchArgs.slice(); + const args = pythonSettings.terminal!.launchArgs.slice(); const workspaceUri = resource ? this.workspace.getWorkspaceFolder(resource) : undefined; const defaultWorkspace = Array.isArray(this.workspace.workspaceFolders) && this.workspace.workspaceFolders.length > 0 ? this.workspace.workspaceFolders[0].uri.fsPath : ''; diff --git a/src/test/common/moduleInstaller.test.ts b/src/test/common/moduleInstaller.test.ts index 698d424111a8..31ea81de250a 100644 --- a/src/test/common/moduleInstaller.test.ts +++ b/src/test/common/moduleInstaller.test.ts @@ -21,7 +21,7 @@ import { ITerminalService, ITerminalServiceFactory } from '../../client/common/t import { IConfigurationService, ICurrentProcess, IInstaller, ILogger, IPathUtils, IPersistentStateFactory, IPythonSettings, IsWindows } from '../../client/common/types'; import { ICondaService, IInterpreterLocatorService, IInterpreterService, INTERPRETER_LOCATOR_SERVICE, InterpreterType, PIPENV_SERVICE, PythonInterpreter } from '../../client/interpreter/contracts'; import { IServiceContainer } from '../../client/ioc/types'; -import { rootWorkspaceUri } from '../common'; +import { PYTHON_PATH, rootWorkspaceUri } from '../common'; import { MockModuleInstaller } from '../mocks/moduleInstaller'; import { MockProcessService } from '../mocks/proc'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; @@ -195,7 +195,7 @@ suite('Module Installer', () => { const interpreter: PythonInterpreter = { type: InterpreterType.Unknown, - path: 'python' + path: PYTHON_PATH }; interpreterService.setup(x => x.getActiveInterpreter(TypeMoq.It.isAny())).returns(() => Promise.resolve(interpreter)); diff --git a/src/test/debugger/attach.ptvsd.test.ts b/src/test/debugger/attach.ptvsd.test.ts index 87d7e77de17d..b5f0f9839e1b 100644 --- a/src/test/debugger/attach.ptvsd.test.ts +++ b/src/test/debugger/attach.ptvsd.test.ts @@ -19,7 +19,7 @@ import { PythonV2DebugConfigurationProvider } from '../../client/debugger'; import { PTVSD_PATH } from '../../client/debugger/Common/constants'; import { AttachRequestArguments, DebugOptions } from '../../client/debugger/Common/Contracts'; import { IServiceContainer } from '../../client/ioc/types'; -import { sleep } from '../common'; +import { PYTHON_PATH, sleep } from '../common'; import { initialize, IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { continueDebugging, createDebugAdapter } from './utils'; @@ -59,7 +59,7 @@ suite('Attach Debugger - Experimental', () => { // tslint:disable-next-line:no-string-literal env['PYTHONPATH'] = PTVSD_PATH; const pythonArgs = ['-m', 'ptvsd', '--server', '--port', `${port}`, '--file', fileToDebug.fileToCommandArgument()]; - proc = spawn('python', pythonArgs, { env: env, cwd: path.dirname(fileToDebug) }); + proc = spawn(PYTHON_PATH, pythonArgs, { env: env, cwd: path.dirname(fileToDebug) }); await sleep(3000); // Send initialize, attach diff --git a/src/test/debugger/attach.test.ts b/src/test/debugger/attach.test.ts index 5e346c6cb048..7747a0450c01 100644 --- a/src/test/debugger/attach.test.ts +++ b/src/test/debugger/attach.test.ts @@ -12,7 +12,7 @@ import { createDeferred } from '../../client/common/helpers'; import { BufferDecoder } from '../../client/common/process/decoder'; import { ProcessService } from '../../client/common/process/proc'; import { AttachRequestArguments } from '../../client/debugger/Common/Contracts'; -import { sleep } from '../common'; +import { PYTHON_PATH, sleep } from '../common'; import { initialize, IS_APPVEYOR, IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { DEBUGGER_TIMEOUT } from './common/constants'; @@ -67,7 +67,7 @@ suite('Attach Debugger', () => { // tslint:disable-next-line:no-string-literal customEnv['PYTHONPATH'] = ptvsdPath; const procService = new ProcessService(new BufferDecoder()); - const result = procService.execObservable('python', [fileToDebug, port.toString()], { env: customEnv, cwd: path.dirname(fileToDebug) }); + const result = procService.execObservable(PYTHON_PATH, [fileToDebug, port.toString()], { env: customEnv, cwd: path.dirname(fileToDebug) }); procToKill = result.proc; const expectedOutputs = [ diff --git a/src/test/debugger/capabilities.test.ts b/src/test/debugger/capabilities.test.ts index 5f7f6f53c159..416985681c24 100644 --- a/src/test/debugger/capabilities.test.ts +++ b/src/test/debugger/capabilities.test.ts @@ -20,6 +20,7 @@ import { PTVSD_PATH } from '../../client/debugger/Common/constants'; import { ProtocolParser } from '../../client/debugger/Common/protocolParser'; import { ProtocolMessageWriter } from '../../client/debugger/Common/protocolWriter'; import { PythonDebugger } from '../../client/debugger/mainV2'; +import { PYTHON_PATH } from '../common'; import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; class Request extends Message implements DebugProtocol.InitializeRequest { @@ -80,7 +81,7 @@ suite('Debugging - Capabilities', () => { const port = await getFreePort({ host, port: 3000 }); const env = { ...process.env }; env.PYTHONPATH = PTVSD_PATH; - proc = spawn('python', ['-m', 'ptvsd', '--server', '--port', `${port}`, '--file', fileToDebug], { cwd: path.dirname(fileToDebug), env }); + proc = spawn(PYTHON_PATH, ['-m', 'ptvsd', '--server', '--port', `${port}`, '--file', fileToDebug], { cwd: path.dirname(fileToDebug), env }); await sleep(3000); const connected = createDeferred(); diff --git a/src/test/debugger/misc.test.ts b/src/test/debugger/misc.test.ts index 0e17bc9a05c9..995be0db817a 100644 --- a/src/test/debugger/misc.test.ts +++ b/src/test/debugger/misc.test.ts @@ -15,7 +15,7 @@ import { FileSystem } from '../../client/common/platform/fileSystem'; import { PlatformService } from '../../client/common/platform/platformService'; import { PTVSD_PATH } from '../../client/debugger/Common/constants'; import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; -import { sleep } from '../common'; +import { PYTHON_PATH, sleep } from '../common'; import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { DEBUGGER_TIMEOUT } from './common/constants'; import { DebugClientEx } from './debugClient'; @@ -78,7 +78,7 @@ let testCounter = 0; cwd: debugFilesPath, stopOnEntry, debugOptions: [DebugOptions.RedirectOutput], - pythonPath: 'python', + pythonPath: PYTHON_PATH, args: [], env, envFile: '', diff --git a/src/test/debugger/module.test.ts b/src/test/debugger/module.test.ts index cdf88f27a68a..1e51b5e2b030 100644 --- a/src/test/debugger/module.test.ts +++ b/src/test/debugger/module.test.ts @@ -11,7 +11,7 @@ import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; import { noop } from '../../client/common/core.utils'; import { PTVSD_PATH } from '../../client/debugger/Common/constants'; import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; -import { sleep } from '../common'; +import { PYTHON_PATH, sleep } from '../common'; import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { createDebugAdapter } from './utils'; @@ -46,7 +46,7 @@ suite(`Module Debugging - Misc tests: ${debuggerType}`, () => { program: '', cwd: workspaceDirectory, debugOptions: [DebugOptions.RedirectOutput], - pythonPath: 'python', + pythonPath: PYTHON_PATH, args: [], env, envFile: '', diff --git a/src/test/debugger/portAndHost.test.ts b/src/test/debugger/portAndHost.test.ts index 6d2d79491bbf..32fdf3941a74 100644 --- a/src/test/debugger/portAndHost.test.ts +++ b/src/test/debugger/portAndHost.test.ts @@ -9,6 +9,7 @@ import * as path from 'path'; import { DebugClient } from 'vscode-debugadapter-testsupport'; import { noop } from '../../client/common/core.utils'; import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; +import { PYTHON_PATH } from '../common'; import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { DEBUGGER_TIMEOUT } from './common/constants'; @@ -50,7 +51,7 @@ const EXPERIMENTAL_DEBUG_ADAPTER = path.join(__dirname, '..', '..', 'client', 'd cwd: debugFilesPath, stopOnEntry, debugOptions: [DebugOptions.RedirectOutput], - pythonPath: 'python', + pythonPath: PYTHON_PATH, args: [], envFile: '', host, port, diff --git a/src/test/interpreters/interpreterVersion.test.ts b/src/test/interpreters/interpreterVersion.test.ts index 6bd728d669ab..9e78d8ee5e66 100644 --- a/src/test/interpreters/interpreterVersion.test.ts +++ b/src/test/interpreters/interpreterVersion.test.ts @@ -7,6 +7,7 @@ import '../../client/common/extensions'; import { IProcessService } from '../../client/common/process/types'; import { IInterpreterVersionService } from '../../client/interpreter/contracts'; import { PIP_VERSION_REGEX } from '../../client/interpreter/interpreterVersion'; +import { PYTHON_PATH } from '../common'; import { initialize, initializeTest } from '../initialize'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; @@ -31,10 +32,10 @@ suite('Interpreters display version', () => { test('Must return the Python Version', async () => { const pythonProcess = ioc.serviceContainer.get(IProcessService); - const output = await pythonProcess.exec('python', ['--version'], { cwd: __dirname, mergeStdOutErr: true }); + const output = await pythonProcess.exec(PYTHON_PATH, ['--version'], { cwd: __dirname, mergeStdOutErr: true }); const version = output.stdout.splitLines()[0]; const interpreterVersion = ioc.serviceContainer.get(IInterpreterVersionService); - const pyVersion = await interpreterVersion.getVersion('python', 'DEFAULT_TEST_VALUE'); + const pyVersion = await interpreterVersion.getVersion(PYTHON_PATH, 'DEFAULT_TEST_VALUE'); assert.equal(pyVersion, version, 'Incorrect version'); }); test('Must return the default value when Python path is invalid', async () => { @@ -44,7 +45,7 @@ suite('Interpreters display version', () => { }); test('Must return the pip Version', async () => { const pythonProcess = ioc.serviceContainer.get(IProcessService); - const result = await pythonProcess.exec('python', ['-m', 'pip', '--version'], { cwd: __dirname, mergeStdOutErr: true }); + const result = await pythonProcess.exec(PYTHON_PATH, ['-m', 'pip', '--version'], { cwd: __dirname, mergeStdOutErr: true }); const output = result.stdout.splitLines()[0]; // Take the second part, see below example. // pip 9.0.1 from /Users/donjayamanne/anaconda3/lib/python3.6/site-packages (python 3.6). @@ -55,7 +56,7 @@ suite('Interpreters display version', () => { assert.isAtLeast(matches!.length, 1, 'Version number not found'); const interpreterVersion = ioc.serviceContainer.get(IInterpreterVersionService); - const pipVersionPromise = interpreterVersion.getPipVersion('python'); + const pipVersionPromise = interpreterVersion.getPipVersion(PYTHON_PATH); // tslint:disable-next-line:no-non-null-assertion await expect(pipVersionPromise).to.eventually.equal(matches![0].trim()); }); diff --git a/src/test/interpreters/virtualEnvManager.test.ts b/src/test/interpreters/virtualEnvManager.test.ts index bfd498b55de3..3d00204b9269 100644 --- a/src/test/interpreters/virtualEnvManager.test.ts +++ b/src/test/interpreters/virtualEnvManager.test.ts @@ -10,6 +10,7 @@ import { IBufferDecoder, IProcessService } from '../../client/common/process/typ import { VirtualEnvironmentManager } from '../../client/interpreter/virtualEnvs'; import { ServiceContainer } from '../../client/ioc/container'; import { ServiceManager } from '../../client/ioc/serviceManager'; +import { PYTHON_PATH } from '../common'; suite('Virtual environment manager', () => { let serviceManager: ServiceManager; @@ -22,15 +23,15 @@ suite('Virtual environment manager', () => { serviceContainer = new ServiceContainer(cont); }); - test('Plain Python environment suffix', async () => await testSuffix('')); - test('Venv environment suffix', async () => await testSuffix('venv')); - test('Virtualenv Python environment suffix', async () => await testSuffix('virtualenv')); + test('Plain Python environment suffix', async () => testSuffix('')); + test('Venv environment suffix', async () => testSuffix('venv')); + test('Virtualenv Python environment suffix', async () => testSuffix('virtualenv')); test('Run actual virtual env detection code', async () => { serviceManager.addSingleton(IProcessService, ProcessService); serviceManager.addSingleton(IBufferDecoder, BufferDecoder); const venvManager = new VirtualEnvironmentManager(serviceContainer); - const name = await venvManager.getEnvironmentName('python'); + const name = await venvManager.getEnvironmentName(PYTHON_PATH); const result = name === '' || name === 'venv' || name === 'virtualenv'; expect(result).to.be.equal(true, 'Running venv detection code failed.'); }); @@ -41,13 +42,13 @@ suite('Virtual environment manager', () => { const venvManager = new VirtualEnvironmentManager(serviceContainer); process - .setup(x => x.exec('python', TypeMoq.It.isAny())) + .setup(x => x.exec(PYTHON_PATH, TypeMoq.It.isAny())) .returns(() => Promise.resolve({ stdout: expectedName, stderr: '' })); - const name = await venvManager.getEnvironmentName('python'); + const name = await venvManager.getEnvironmentName(PYTHON_PATH); expect(name).to.be.equal(expectedName, 'Virtual envrironment name suffix is incorrect.'); } }); diff --git a/src/test/providers/shebangCodeLenseProvider.test.ts b/src/test/providers/shebangCodeLenseProvider.test.ts index bc89c1761d5e..c486c2f55dd0 100644 --- a/src/test/providers/shebangCodeLenseProvider.test.ts +++ b/src/test/providers/shebangCodeLenseProvider.test.ts @@ -1,11 +1,11 @@ import * as assert from 'assert'; import * as child_process from 'child_process'; import * as path from 'path'; -import * as vscode from 'vscode'; -import { CancellationTokenSource } from 'vscode'; +import { CancellationTokenSource, TextDocument, workspace } from 'vscode'; import { IS_WINDOWS, PythonSettings } from '../../client/common/configSettings'; import { ShebangCodeLensProvider } from '../../client/interpreter/display/shebangCodeLensProvider'; import { getFirstNonEmptyLineFromMultilineString } from '../../client/interpreter/helpers'; +import { PYTHON_PATH } from '../common'; import { closeActiveWindows, initialize, initializeTest } from '../initialize'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; @@ -48,7 +48,7 @@ suite('Shebang detection', () => { test('Code lens will not appear when sheban python and python in settings are the same', async () => { PythonSettings.dispose(); - const pythonPath = await getFullyQualifiedPathToInterpreter('python'); + const pythonPath = await getFullyQualifiedPathToInterpreter(PYTHON_PATH); const document = await openFile(fileShebang); PythonSettings.getInstance(document.uri).pythonPath = pythonPath!; const codeLenses = await setupCodeLens(document); @@ -76,7 +76,7 @@ suite('Shebang detection', () => { }); test('Code lens will not appear even when shebang python uses env and python settings are the same', async () => { - const pythonPath = await getFullyQualifiedPathToInterpreter('python'); + const pythonPath = await getFullyQualifiedPathToInterpreter(PYTHON_PATH); const document = await openFile(fileShebangEnv); PythonSettings.getInstance(document.uri).pythonPath = pythonPath!; const codeLenses = await setupCodeLens(document); @@ -91,7 +91,7 @@ suite('Shebang detection', () => { }); async function openFile(fileName: string) { - return vscode.workspace.openTextDocument(fileName); + return workspace.openTextDocument(fileName); } async function getFullyQualifiedPathToInterpreter(pythonPath: string) { return new Promise(resolve => { @@ -101,8 +101,8 @@ suite('Shebang detection', () => { }).catch(() => undefined); } - async function setupCodeLens(document: vscode.TextDocument) { + async function setupCodeLens(document: TextDocument) { const codeLensProvider = new ShebangCodeLensProvider(ioc.serviceContainer); - return await codeLensProvider.provideCodeLenses(document, new CancellationTokenSource().token); + return codeLensProvider.provideCodeLenses(document, new CancellationTokenSource().token); } }); diff --git a/src/test/terminals/codeExecution/djangoShellCodeExect.test.ts b/src/test/terminals/codeExecution/djangoShellCodeExect.test.ts index b6814214abeb..e85da9496e88 100644 --- a/src/test/terminals/codeExecution/djangoShellCodeExect.test.ts +++ b/src/test/terminals/codeExecution/djangoShellCodeExect.test.ts @@ -13,6 +13,7 @@ import { ITerminalService, ITerminalServiceFactory } from '../../../client/commo import { IConfigurationService, IPythonSettings, ITerminalSettings } from '../../../client/common/types'; import { DjangoShellCodeExecutionProvider } from '../../../client/terminals/codeExecution/djangoShellCodeExecution'; import { ICodeExecutionService } from '../../../client/terminals/types'; +import { PYTHON_PATH } from '../../common'; // tslint:disable-next-line:max-func-body-length suite('Terminal - Django Shell Code Execution', () => { @@ -86,7 +87,7 @@ suite('Terminal - Django Shell Code Execution', () => { }); test('Ensure python path is returned as is, when building repl args on Windows', async () => { - const pythonPath = 'python'; + const pythonPath = PYTHON_PATH; const terminalArgs = ['-a', 'b', 'c']; const expectedTerminalArgs = terminalArgs.concat('manage.py', 'shell'); @@ -102,7 +103,7 @@ suite('Terminal - Django Shell Code Execution', () => { }); test('Ensure python path is returned as is, on non Windows', async () => { - const pythonPath = 'python'; + const pythonPath = PYTHON_PATH; const terminalArgs = ['-a', 'b', 'c']; const expectedTerminalArgs = terminalArgs.concat('manage.py', 'shell'); diff --git a/src/test/terminals/codeExecution/terminalCodeExec.test.ts b/src/test/terminals/codeExecution/terminalCodeExec.test.ts index 4466de64354f..2ada071c2f3c 100644 --- a/src/test/terminals/codeExecution/terminalCodeExec.test.ts +++ b/src/test/terminals/codeExecution/terminalCodeExec.test.ts @@ -15,6 +15,7 @@ import { DjangoShellCodeExecutionProvider } from '../../../client/terminals/code import { ReplProvider } from '../../../client/terminals/codeExecution/repl'; import { TerminalCodeExecutionProvider } from '../../../client/terminals/codeExecution/terminalCodeExecution'; import { ICodeExecutionService } from '../../../client/terminals/types'; +import { PYTHON_PATH } from '../../common'; // tslint:disable-next-line:max-func-body-length suite('Terminal Code Execution', () => { @@ -99,7 +100,7 @@ suite('Terminal Code Execution', () => { platform.setup(p => p.isWindows).returns(() => isWindows); platform.setup(p => p.isMac).returns(() => isOsx); platform.setup(p => p.isLinux).returns(() => isLinux); - settings.setup(s => s.pythonPath).returns(() => 'python'); + settings.setup(s => s.pythonPath).returns(() => PYTHON_PATH); terminalSettings.setup(t => t.launchArgs).returns(() => []); await executor.initializeRepl(); @@ -130,12 +131,12 @@ suite('Terminal Code Execution', () => { workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => workspaceFolder.object); workspaceFolder.setup(w => w.uri).returns(() => Uri.file(path.join('c', 'path', 'to'))); platform.setup(p => p.isWindows).returns(() => false); - settings.setup(s => s.pythonPath).returns(() => 'python'); + settings.setup(s => s.pythonPath).returns(() => PYTHON_PATH); terminalSettings.setup(t => t.launchArgs).returns(() => []); await executor.executeFile(file); - terminalService.verify(async t => await t.sendText(TypeMoq.It.isValue(`cd ${path.dirname(file.fsPath).fileToCommandArgument()}`)), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendText(TypeMoq.It.isValue(`cd ${path.dirname(file.fsPath).fileToCommandArgument()}`)), TypeMoq.Times.once()); } test('Ensure we set current directory before executing file (non windows)', async () => { await ensureWeSetCurrentDirectoryBeforeExecutingAFile(false); @@ -150,12 +151,12 @@ suite('Terminal Code Execution', () => { workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => workspaceFolder.object); workspaceFolder.setup(w => w.uri).returns(() => Uri.file(path.join('c', 'path', 'to'))); platform.setup(p => p.isWindows).returns(() => isWindows); - settings.setup(s => s.pythonPath).returns(() => 'python'); + settings.setup(s => s.pythonPath).returns(() => PYTHON_PATH); terminalSettings.setup(t => t.launchArgs).returns(() => []); await executor.executeFile(file); const dir = path.dirname(file.fsPath).fileToCommandArgument(); - terminalService.verify(async t => await t.sendText(TypeMoq.It.isValue(`cd ${dir}`)), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendText(TypeMoq.It.isValue(`cd ${dir}`)), TypeMoq.Times.once()); } test('Ensure we set current directory (and quote it when containing spaces) before executing file (non windows)', async () => { @@ -172,12 +173,12 @@ suite('Terminal Code Execution', () => { workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => workspaceFolder.object); workspaceFolder.setup(w => w.uri).returns(() => Uri.file(path.join('c', 'path', 'to', 'file with spaces in path'))); platform.setup(p => p.isWindows).returns(() => isWindows); - settings.setup(s => s.pythonPath).returns(() => 'python'); + settings.setup(s => s.pythonPath).returns(() => PYTHON_PATH); terminalSettings.setup(t => t.launchArgs).returns(() => []); await executor.executeFile(file); - terminalService.verify(async t => await t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); } test('Ensure we do not set current directory before executing file if in the same directory (non windows)', async () => { await ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileInSameDirectory(false); @@ -191,12 +192,12 @@ suite('Terminal Code Execution', () => { terminalSettings.setup(t => t.executeInFileDir).returns(() => true); workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => undefined); platform.setup(p => p.isWindows).returns(() => isWindows); - settings.setup(s => s.pythonPath).returns(() => 'python'); + settings.setup(s => s.pythonPath).returns(() => PYTHON_PATH); terminalSettings.setup(t => t.launchArgs).returns(() => []); await executor.executeFile(file); - terminalService.verify(async t => await t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); } test('Ensure we do not set current directory before executing file if file is not in a workspace (non windows)', async () => { await ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileNotInSameDirectory(false); @@ -215,12 +216,12 @@ suite('Terminal Code Execution', () => { await executor.executeFile(file); const expectedPythonPath = isWindows ? pythonPath.replace(/\\/g, '/') : pythonPath; const expectedArgs = terminalArgs.concat(file.fsPath.fileToCommandArgument()); - terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(expectedPythonPath), TypeMoq.It.isValue(expectedArgs)), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendCommand(TypeMoq.It.isValue(expectedPythonPath), TypeMoq.It.isValue(expectedArgs)), TypeMoq.Times.once()); } test('Ensure python file execution script is sent to terminal on windows', async () => { const file = Uri.file(path.join('c', 'path', 'to', 'file with spaces in path', 'one.py')); - await testFileExecution(true, 'python', [], file); + await testFileExecution(true, PYTHON_PATH, [], file); }); test('Ensure python file execution script is sent to terminal on windows with fully qualified python path', async () => { @@ -230,12 +231,12 @@ suite('Terminal Code Execution', () => { test('Ensure python file execution script is not quoted when no spaces in file path', async () => { const file = Uri.file(path.join('c', 'path', 'to', 'file', 'one.py')); - await testFileExecution(true, 'python', [], file); + await testFileExecution(true, PYTHON_PATH, [], file); }); test('Ensure python file execution script supports custom python arguments', async () => { const file = Uri.file(path.join('c', 'path', 'to', 'file', 'one.py')); - await testFileExecution(false, 'python', ['-a', '-b', '-c'], file); + await testFileExecution(false, PYTHON_PATH, ['-a', '-b', '-c'], file); }); function testReplCommandArguments(isWindows: boolean, pythonPath: string, expectedPythonPath: string, terminalArgs: string[]) { @@ -265,7 +266,7 @@ suite('Terminal Code Execution', () => { }); test('Ensure python path is returned as is, when building repl args on Windows', () => { - const pythonPath = 'python'; + const pythonPath = PYTHON_PATH; const terminalArgs = ['-a', 'b', 'c']; testReplCommandArguments(true, pythonPath, pythonPath, terminalArgs); @@ -279,7 +280,7 @@ suite('Terminal Code Execution', () => { }); test('Ensure python path is returned as is, on non Windows', () => { - const pythonPath = 'python'; + const pythonPath = PYTHON_PATH; const terminalArgs = ['-a', 'b', 'c']; testReplCommandArguments(false, pythonPath, pythonPath, terminalArgs); @@ -291,8 +292,8 @@ suite('Terminal Code Execution', () => { // tslint:disable-next-line:no-any await executor.execute(undefined as any as string); - terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never()); - terminalService.verify(async t => await t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => t.sendCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); }); test('Ensure repl is initialized once before sending text to the repl', async () => { @@ -308,7 +309,7 @@ suite('Terminal Code Execution', () => { await executor.execute('cmd3'); const expectedTerminalArgs = isDjangoRepl ? terminalArgs.concat(['manage.py', 'shell']) : terminalArgs; - terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); }); test('Ensure repl is re-initialized when temrinal is closed', async () => { @@ -334,15 +335,15 @@ suite('Terminal Code Execution', () => { const expectedTerminalArgs = isDjangoRepl ? terminalArgs.concat(['manage.py', 'shell']) : terminalArgs; expect(closeTerminalCallback).not.to.be.an('undefined', 'Callback not initialized'); - terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); closeTerminalCallback!.call(terminalService.object); await executor.execute('cmd4'); - terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(2)); + terminalService.verify(async t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(2)); closeTerminalCallback!.call(terminalService.object); await executor.execute('cmd5'); - terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(3)); + terminalService.verify(async t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(3)); }); test('Ensure code is sent to terminal', async () => { @@ -353,10 +354,10 @@ suite('Terminal Code Execution', () => { terminalSettings.setup(t => t.launchArgs).returns(() => terminalArgs); await executor.execute('cmd1'); - terminalService.verify(async t => await t.sendText('cmd1'), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendText('cmd1'), TypeMoq.Times.once()); await executor.execute('cmd2'); - terminalService.verify(async t => await t.sendText('cmd2'), TypeMoq.Times.once()); + terminalService.verify(async t => t.sendText('cmd2'), TypeMoq.Times.once()); }); }); }); From 4366023e42a371a55dc0478f2bfa852f79d8c722 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 19:46:42 -0700 Subject: [PATCH 15/18] revert unnecessary change --- src/test/providers/shebangCodeLenseProvider.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/providers/shebangCodeLenseProvider.test.ts b/src/test/providers/shebangCodeLenseProvider.test.ts index c486c2f55dd0..b1e4a15bd8ae 100644 --- a/src/test/providers/shebangCodeLenseProvider.test.ts +++ b/src/test/providers/shebangCodeLenseProvider.test.ts @@ -5,7 +5,6 @@ import { CancellationTokenSource, TextDocument, workspace } from 'vscode'; import { IS_WINDOWS, PythonSettings } from '../../client/common/configSettings'; import { ShebangCodeLensProvider } from '../../client/interpreter/display/shebangCodeLensProvider'; import { getFirstNonEmptyLineFromMultilineString } from '../../client/interpreter/helpers'; -import { PYTHON_PATH } from '../common'; import { closeActiveWindows, initialize, initializeTest } from '../initialize'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; @@ -48,7 +47,7 @@ suite('Shebang detection', () => { test('Code lens will not appear when sheban python and python in settings are the same', async () => { PythonSettings.dispose(); - const pythonPath = await getFullyQualifiedPathToInterpreter(PYTHON_PATH); + const pythonPath = await getFullyQualifiedPathToInterpreter('python'); const document = await openFile(fileShebang); PythonSettings.getInstance(document.uri).pythonPath = pythonPath!; const codeLenses = await setupCodeLens(document); @@ -76,7 +75,7 @@ suite('Shebang detection', () => { }); test('Code lens will not appear even when shebang python uses env and python settings are the same', async () => { - const pythonPath = await getFullyQualifiedPathToInterpreter(PYTHON_PATH); + const pythonPath = await getFullyQualifiedPathToInterpreter('python'); const document = await openFile(fileShebangEnv); PythonSettings.getInstance(document.uri).pythonPath = pythonPath!; const codeLenses = await setupCodeLens(document); From d539856317cc7c7ed16638dc595d2a49775f57bb Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 20:10:11 -0700 Subject: [PATCH 16/18] :memo: change log [skip ci] --- news/3 Code Health/1318.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/3 Code Health/1318.md diff --git a/news/3 Code Health/1318.md b/news/3 Code Health/1318.md new file mode 100644 index 000000000000..d0f965f5a448 --- /dev/null +++ b/news/3 Code Health/1318.md @@ -0,0 +1 @@ +Ensure all unit tests run on Travis use the right Python interpreter. From 3143b905b038fc5e09981020b2868bf1fb3b9f1b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 20:20:02 -0700 Subject: [PATCH 17/18] hide unwanted folders [skip ci] --- .vscode/settings.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index be66f967c5c4..7ce29c7c0813 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,8 @@ "files.exclude": { "out": true, // set this to true to hide the "out" folder with the compiled JS files "**/*.pyc": true, + "obj": true, + "bin": true, "**/__pycache__": true, "node_modules": true, ".vscode-test": true, @@ -19,4 +21,4 @@ "python.unitTest.promptToConfigure": false, "python.workspaceSymbols.enabled": false, "python.formatting.provider": "none" -} \ No newline at end of file +} From fcd16def1970e4e79b3982c16b061080f043efbd Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 20:30:27 -0700 Subject: [PATCH 18/18] removed unnecessary file --- src/test/debugger/core/capabilities.test.ts | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 src/test/debugger/core/capabilities.test.ts diff --git a/src/test/debugger/core/capabilities.test.ts b/src/test/debugger/core/capabilities.test.ts deleted file mode 100644 index 63bc7314a0e1..000000000000 --- a/src/test/debugger/core/capabilities.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// 1. Ensure the capabilitites of the debugger sent into the response to initialize matches -// that of the underlying (ptvsd) debugger -// I.e. ensure the response sent by us matches the response sent by ptvsd to the initialize request.