GeezerVison is showing github.com — fixed test runner · Goom11/vscode-python@dad28ec
File treeExpand file treeCollapse file tree Open diff view settings client/unittests/unittest pythonFiles/unitests/tests
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: pythonFiles/PythonTools/visualstudio_py_testlauncher.py +4-4Lines changed: 4 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -308,11 +308,11 @@ def main(): | 308 | 308 | test = '' | 309 | 309 | ) | 310 | 310 | if opts.uvInt is None: | 311 | | - opts.uvInt = 0 | 312 | | - runner = unittest.TextTestRunner(verbosity=opts.uvInt, resultclass=VsTestResult) | | 311 | + opts.uvInt = 0 | 313 | 312 | if opts.uf is not None: | 314 | | - runner.failfast = 1 | 315 | | - | | 313 | + runner = unittest.TextTestRunner(verbosity=opts.uvInt, resultclass=VsTestResult, failfast=True) | | 314 | + else: | | 315 | + runner = unittest.TextTestRunner(verbosity=opts.uvInt, resultclass=VsTestResult) | 316 | 316 | result = runner.run(tests) | 317 | 317 | sys.exit(not result.wasSuccessful()) | 318 | 318 | finally: | |
Collapse file Copy file name to clipboardExpand all lines: src/client/unittests/unittest/main.ts +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -24,6 +24,6 @@ export class TestManager extends BaseTestManager { | 24 | 24 | return fn.testFunction.status === TestStatus.Error || fn.testFunction.status === TestStatus.Fail; | 25 | 25 | }).map(fn => fn.testFunction); | 26 | 26 | } | 27 | | - return runTest(this.rootDirectory, tests, args, testsToRun, this.cancellationToken, this.outputChannel); | | 27 | + return runTest(this, this.rootDirectory, tests, args, testsToRun, this.cancellationToken, this.outputChannel); | 28 | 28 | } | 29 | 29 | } |
Collapse file Copy file name to clipboardExpand all lines: src/client/unittests/unittest/runner.ts +17-10Lines changed: 17 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | 'use strict'; | 4 | 4 | import * as path from 'path'; | 5 | | -import {createDeferred, createTemporaryFile} from '../../common/helpers'; | 6 | | -import {TestFile, TestsToRun, TestSuite, TestFunction, FlattenedTestFunction, Tests, TestStatus, FlattenedTestSuite} from '../common/contracts'; | 7 | | -import {extractBetweenDelimiters, flattenTestFiles, updateResults, convertFileToPackage} from '../common/testUtils'; | 8 | | -import {BaseTestManager} from '../common/baseTestManager'; | 9 | | -import {CancellationToken, OutputChannel} from 'vscode'; | 10 | | -import {run} from '../common/runner'; | 11 | | -import {Server} from './socketServer'; | 12 | | -import {PythonSettings} from '../../common/configSettings'; | | 5 | +import { createDeferred, createTemporaryFile } from '../../common/helpers'; | | 6 | +import { TestFile, TestsToRun, TestSuite, TestFunction, FlattenedTestFunction, Tests, TestStatus, FlattenedTestSuite } from '../common/contracts'; | | 7 | +import { extractBetweenDelimiters, flattenTestFiles, updateResults, convertFileToPackage } from '../common/testUtils'; | | 8 | +import { BaseTestManager } from '../common/baseTestManager'; | | 9 | +import { CancellationToken, OutputChannel } from 'vscode'; | | 10 | +import { run } from '../common/runner'; | | 11 | +import { Server } from './socketServer'; | | 12 | +import { PythonSettings } from '../../common/configSettings'; | 13 | 13 |
| 14 | 14 | const settings = PythonSettings.getInstance(); | 15 | 15 | interface TestStatusMap { | @@ -30,12 +30,12 @@ interface ITestData { | 30 | 30 | traceback: string; | 31 | 31 | } | 32 | 32 |
| 33 | | -export function runTest(rootDirectory: string, tests: Tests, args: string[], testsToRun?: TestsToRun, token?: CancellationToken, outChannel?: OutputChannel): Promise<Tests> { | | 33 | +export function runTest(testManager: BaseTestManager, rootDirectory: string, tests: Tests, args: string[], testsToRun?: TestsToRun, token?: CancellationToken, outChannel?: OutputChannel): Promise<Tests> { | 34 | 34 | tests.summary.errors = 0; | 35 | 35 | tests.summary.failures = 0; | 36 | 36 | tests.summary.passed = 0; | 37 | 37 | tests.summary.skipped = 0; | 38 | | - | | 38 | + let failFast = false; | 39 | 39 | const testLauncherFile = path.join(__dirname, '..', '..', '..', '..', 'pythonFiles', 'PythonTools', 'visualstudio_py_testlauncher.py'); | 40 | 40 | const server = new Server(); | 41 | 41 | server.on('error', (message: string, ...data: string[]) => { | @@ -55,6 +55,10 @@ export function runTest(rootDirectory: string, tests: Tests, args: string[], tes | 55 | 55 | test.testFunction.message = data.message; | 56 | 56 | test.testFunction.traceback = data.traceback; | 57 | 57 | tests.summary[statusDetails.summaryProperty] += 1; | | 58 | + | | 59 | + if (failFast && (statusDetails.summaryProperty === 'failures' || statusDetails.summaryProperty === 'errors')) { | | 60 | + testManager.stop(); | | 61 | + } | 58 | 62 | } | 59 | 63 | }); | 60 | 64 | server.on('socket.disconnected', (data) => { | @@ -69,6 +73,9 @@ export function runTest(rootDirectory: string, tests: Tests, args: string[], tes | 69 | 73 |
| 70 | 74 | function runTest(testFile: string = '', testId: string = '') { | 71 | 75 | let testArgs = buildTestArgs(args); | | 76 | + failFast = testArgs.indexOf('--uf') >= 0; | | 77 | + testArgs = testArgs.filter(arg=>arg !== '--uf'); | | 78 | + | 72 | 79 | testArgs.push(`--result-port=${port}`); | 73 | 80 | testArgs.push(`--us=${startTestDiscoveryDirectory}`); | 74 | 81 | if (testId.length > 0) { | |
Collapse file Copy file name to clipboardExpand all lines: src/test/extension.unittests.unittest.test.ts +148-45Lines changed: 148 additions & 45 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -12,13 +12,10 @@ import * as assert from 'assert'; | 12 | 12 | // You can import and use all API from the \'vscode\' module | 13 | 13 | // as well as import your extension to test it | 14 | 14 | import * as vscode from 'vscode'; | 15 | | -import { TestStatus} from '../client/unittests/common/contracts'; | | 15 | +import { TestsToRun } from '../client/unittests/common/contracts'; | 16 | 16 | import * as unittest from '../client/unittests/unittest/main'; | 17 | 17 | import { TestResultDisplay } from '../client/unittests/display/main'; | 18 | 18 |
| 19 | | -let unittestManager: unittest.TestManager; | 20 | | -let testResultDisplay: TestResultDisplay; | 21 | | -let outChannel: vscode.OutputChannel; | 22 | 19 |
| 23 | 20 | import * as path from 'path'; | 24 | 21 | import * as configSettings from '../client/common/configSettings'; | @@ -45,61 +42,167 @@ class MockOutputChannel implements vscode.OutputChannel { | 45 | 42 | dispose() { } | 46 | 43 | } | 47 | 44 |
| 48 | | -suiteSetup(done => { | 49 | | - initialize().then(() => { | | 45 | +suite('Unit Tests (unittest)', () => { | | 46 | + suiteSetup(done => { | | 47 | + initialize().then(() => { | | 48 | + done(); | | 49 | + }); | | 50 | + }); | | 51 | + suiteTeardown(done => { | 50 | 52 | done(); | 51 | 53 | }); | 52 | | -}); | 53 | | -suiteTeardown(done => { | 54 | | - done(); | 55 | | -}); | | 54 | + setup(() => { | | 55 | + outChannel = new MockOutputChannel('Python Test Log'); | | 56 | + testResultDisplay = new TestResultDisplay(outChannel); | | 57 | + }); | | 58 | + teardown(() => { | | 59 | + outChannel.dispose(); | | 60 | + testManager.dispose(); | | 61 | + testResultDisplay.dispose(); | | 62 | + }); | | 63 | + function createTestManager() { | | 64 | + testManager = new unittest.TestManager(rootDirectory, outChannel); | | 65 | + } | | 66 | + const rootDirectory = UNITTEST_TEST_FILES_PATH; | | 67 | + let testManager: unittest.TestManager; | | 68 | + let testResultDisplay: TestResultDisplay; | | 69 | + let outChannel: vscode.OutputChannel; | 56 | 70 |
| 57 | | -suite('Unit Tests (unittest)', () => { | 58 | | - // setup(() => { | 59 | | - // pythonSettings.unitTest.unittestEnabled = true; | 60 | | - // pythonSettings.unitTest.nosetestsEnabled = false; | 61 | | - // pythonSettings.unitTest.pyTestEnabled = false; | 62 | | - // outChannel = new MockOutputChannel('Python Test Log'); | | 71 | + test('Discover Tests', done => { | | 72 | + pythonSettings.unitTest.unittestArgs = [ | | 73 | + '-s=./tests', | | 74 | + '-p=test_*.py' | | 75 | + ]; | | 76 | + createTestManager(); | | 77 | + testManager.discoverTests(true, true).then(tests => { | | 78 | + assert.equal(tests.testFiles.length, 2, 'Incorrect number of test files'); | | 79 | + assert.equal(tests.testFunctions.length, 9, 'Incorrect number of test functions'); | | 80 | + assert.equal(tests.testSuits.length, 3, 'Incorrect number of test suites'); | | 81 | + assert.equal(tests.testFiles.some(t => t.name === 'test_unittest_one.py' && t.nameToRun === 'Test_test1.test_A'), true, 'Test File not found'); | | 82 | + assert.equal(tests.testFiles.some(t => t.name === 'test_unittest_two.py' && t.nameToRun === 'Test_test2.test_A2'), true, 'Test File not found'); | | 83 | + done(); | | 84 | + }).catch(done); | | 85 | + }); | | 86 | + | | 87 | + test('Discover Tests (pattern = *_test_*.py)', done => { | | 88 | + pythonSettings.unitTest.unittestArgs = [ | | 89 | + '-s=./tests', | | 90 | + '-p=*_test*.py' | | 91 | + ]; | | 92 | + createTestManager(); | | 93 | + testManager.discoverTests(true, true).then(tests => { | | 94 | + assert.equal(tests.testFiles.length, 1, 'Incorrect number of test files'); | | 95 | + assert.equal(tests.testFunctions.length, 2, 'Incorrect number of test functions'); | | 96 | + assert.equal(tests.testSuits.length, 1, 'Incorrect number of test suites'); | | 97 | + assert.equal(tests.testFiles.some(t => t.name === 'unittest_three_test.py' && t.nameToRun === 'Test_test3.test_A'), true, 'Test File not found'); | | 98 | + done(); | | 99 | + }).catch(done); | | 100 | + }); | | 101 | + | | 102 | + test('Run Tests', done => { | | 103 | + pythonSettings.unitTest.unittestArgs = [ | | 104 | + '-s=./tests', | | 105 | + '-p=*test*.py' | | 106 | + ]; | | 107 | + createTestManager(); | | 108 | + testManager.runTest().then(results => { | | 109 | + assert.equal(results.summary.errors, 1, 'Errors'); | | 110 | + assert.equal(results.summary.failures, 5, 'Failures'); | | 111 | + assert.equal(results.summary.passed, 4, 'Passed'); | | 112 | + assert.equal(results.summary.skipped, 1, 'skipped'); | | 113 | + done(); | | 114 | + }).catch(done); | | 115 | + }); | | 116 | + | | 117 | + // test('Fail Fast', done => { | | 118 | + // pythonSettings.unitTest.unittestArgs = [ | | 119 | + // '-s=./tests', | | 120 | + // '-p=*test*.py', | | 121 | + // '--failfast' | | 122 | + // ]; | | 123 | + // createTestManager(); | | 124 | + // testManager.runTest().then(results => { | | 125 | + // assert.equal(results.summary.errors, 1, 'Errors'); | | 126 | + // assert.equal(results.summary.failures, 5, 'Failures'); | | 127 | + // assert.equal(results.summary.passed, 4, 'Passed'); | | 128 | + // assert.equal(results.summary.skipped, 1, 'skipped'); | | 129 | + // done(); | | 130 | + // }).catch(done); | 63 | 131 | // }); | 64 | 132 |
| 65 | | - test('Discover Tests', () => { | 66 | | - const rootDirectory = UNITTEST_TEST_FILES_PATH; | | 133 | + test('Run Failed Tests', done => { | 67 | 134 | pythonSettings.unitTest.unittestArgs = [ | 68 | 135 | '-s=./tests', | 69 | | - '-p=test_*.py' | | 136 | + '-p=*test*.py' | 70 | 137 | ]; | 71 | | - const testManager = unittestManager ? unittestManager : new unittest.TestManager(rootDirectory, outChannel); | 72 | | - if ((testManager.status !== TestStatus.Discovering && testManager.status !== TestStatus.Running)) { | 73 | | - testResultDisplay = testResultDisplay ? testResultDisplay : new TestResultDisplay(outChannel); | 74 | | - testManager.discoverTests(true, true).then(tests => { | 75 | | - assert.equal(tests.testFiles.length, 2, 'Incorrect number of test files'); | 76 | | - assert.equal(tests.testFunctions.length, 6, 'Incorrect number of test functions'); | 77 | | - assert.equal(tests.testSuits.length, 3, 'Incorrect number of test suites'); | 78 | | - assert.equal(tests.testFiles.some(t=>t.name === 'test_unittest_one.py' && t.nameToRun === 'Test_test1.test_A'), true, 'Test File not found'); | 79 | | - assert.equal(tests.testFiles.some(t=>t.name === 'test_unittest_two.py' && t.nameToRun === 'Test_test2.test_A2'), true, 'Test File not found'); | 80 | | - }).catch(reason => { | 81 | | - assert.fail(reason, null, 'Test Discovery failed', ''); | | 138 | + createTestManager(); | | 139 | + testManager.runTest().then(results => { | | 140 | + assert.equal(results.summary.errors, 1, 'Errors'); | | 141 | + assert.equal(results.summary.failures, 5, 'Failures'); | | 142 | + assert.equal(results.summary.passed, 4, 'Passed'); | | 143 | + assert.equal(results.summary.skipped, 1, 'skipped'); | | 144 | + | | 145 | + return testManager.runTest(true).then(tests => { | | 146 | + assert.equal(results.summary.errors, 1, 'Failed Errors'); | | 147 | + assert.equal(results.summary.failures, 5, 'Failed Failures'); | | 148 | + assert.equal(results.summary.passed, 0, 'Failed Passed'); | | 149 | + assert.equal(results.summary.skipped, 0, 'Failed skipped'); | | 150 | + done(); | 82 | 151 | }); | 83 | | - } | | 152 | + }).catch(done); | 84 | 153 | }); | 85 | 154 |
| 86 | | - test('Discover Tests (pattern = *_test_*.py)', () => { | 87 | | - const rootDirectory = UNITTEST_TEST_FILES_PATH; | | 155 | + test('Run Specific Test File', done => { | 88 | 156 | pythonSettings.unitTest.unittestArgs = [ | 89 | 157 | '-s=./tests', | 90 | | - '-p=*_test*.py' | | 158 | + '-p=*test*.py' | | 159 | + ]; | | 160 | + createTestManager(); | | 161 | + testManager.discoverTests(true, true).then(tests => { | | 162 | + const testFile: TestsToRun = { testFile: [tests.testFiles[0]], testFolder: [], testFunction: [], testSuite: [] }; | | 163 | + return testManager.runTest(testFile).then(tests => { | | 164 | + assert.equal(tests.summary.errors, 0, 'Errors'); | | 165 | + assert.equal(tests.summary.failures, 1, 'Failures'); | | 166 | + assert.equal(tests.summary.passed, 1, 'Passed'); | | 167 | + assert.equal(tests.summary.skipped, 1, 'skipped'); | | 168 | + done(); | | 169 | + }); | | 170 | + }).catch(done); | | 171 | + }); | | 172 | + | | 173 | + test('Run Specific Test Suite', done => { | | 174 | + pythonSettings.unitTest.unittestArgs = [ | | 175 | + '-s=./tests', | | 176 | + '-p=*test*.py' | | 177 | + ]; | | 178 | + createTestManager(); | | 179 | + testManager.discoverTests(true, true).then(tests => { | | 180 | + const testSuite: TestsToRun = { testFile: [], testFolder: [], testFunction: [], testSuite: [tests.testSuits[0].testSuite] }; | | 181 | + return testManager.runTest(testSuite).then(tests => { | | 182 | + assert.equal(tests.summary.errors, 0, 'Errors'); | | 183 | + assert.equal(tests.summary.failures, 1, 'Failures'); | | 184 | + assert.equal(tests.summary.passed, 1, 'Passed'); | | 185 | + assert.equal(tests.summary.skipped, 1, 'skipped'); | | 186 | + done(); | | 187 | + }); | | 188 | + }).catch(done); | | 189 | + }); | | 190 | + | | 191 | + test('Run Specific Test Function', done => { | | 192 | + pythonSettings.unitTest.unittestArgs = [ | | 193 | + '-s=./tests', | | 194 | + '-p=*test*.py' | 91 | 195 | ]; | 92 | | - const testManager = unittestManager ? unittestManager : new unittest.TestManager(rootDirectory, outChannel); | 93 | | - if ((testManager.status !== TestStatus.Discovering && testManager.status !== TestStatus.Running)) { | 94 | | - testResultDisplay = testResultDisplay ? testResultDisplay : new TestResultDisplay(outChannel); | 95 | | - testManager.discoverTests(true, true).then(tests => { | 96 | | - assert.equal(tests.testFiles.length, 1, 'Incorrect number of test files'); | 97 | | - assert.equal(tests.testFunctions.length, 2, 'Incorrect number of test functions'); | 98 | | - assert.equal(tests.testSuits.length, 1, 'Incorrect number of test suites'); | 99 | | - assert.equal(tests.testFiles.some(t=>t.name === 'unittest_three_test.py' && t.nameToRun === 'Test_test3.test_A'), true, 'Test File not found'); | 100 | | - }).catch(reason => { | 101 | | - assert.fail(reason, null, 'Test Discovery failed', ''); | | 196 | + createTestManager(); | | 197 | + testManager.discoverTests(true, true).then(tests => { | | 198 | + const testFn: TestsToRun = { testFile: [], testFolder: [], testFunction: [tests.testFunctions[0].testFunction], testSuite: [] }; | | 199 | + return testManager.runTest(testFn).then(tests => { | | 200 | + assert.equal(tests.summary.errors, 0, 'Errors'); | | 201 | + assert.equal(tests.summary.failures, 1, 'Failures'); | | 202 | + assert.equal(tests.summary.passed, 0, 'Passed'); | | 203 | + assert.equal(tests.summary.skipped, 0, 'skipped'); | | 204 | + done(); | 102 | 205 | }); | 103 | | - } | | 206 | + }).catch(done); | 104 | 207 | }); | 105 | 208 | }); |
Collapse file Copy file name to clipboardExpand all lines: src/test/pythonFiles/unitests/tests/test_unittest_one.py +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,6 +10,10 @@ def test_A(self): | 10 | 10 | def test_B(self): | 11 | 11 | self.assertEqual(1, 1, 'Not equal') | 12 | 12 |
| | 13 | + @unittest.skip("demonstrating skipping") | | 14 | + def test_c(self): | | 15 | + self.assertEqual(1, 1, 'Not equal') | | 16 | + | 13 | 17 |
| 14 | 18 | if __name__ == '__main__': | 15 | 19 | unittest.main() |
Collapse file Copy file name to clipboardExpand all lines: src/test/pythonFiles/unitests/tests/test_unittest_two.py +7Lines changed: 7 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -7,6 +7,13 @@ def test_A2(self): | 7 | 7 | def test_B2(self): | 8 | 8 | self.assertEqual(1,1,'Not equal') | 9 | 9 |
| | 10 | + def test_C2(self): | | 11 | + self.assertEqual(1,2,'Not equal') | | 12 | + | | 13 | + def test_D2(self): | | 14 | + raise ArithmeticError() | | 15 | + pass | | 16 | + | 10 | 17 | class Test_test2a(unittest.TestCase): | 11 | 18 | def test_222A2(self): | 12 | 19 | self.fail("Not implemented") | |
|