Skip to content

Commit dad28ec

Browse files
committed
fixed test runner
1 parent 12722fd commit dad28ec

6 files changed

Lines changed: 181 additions & 60 deletions

File tree

pythonFiles/PythonTools/visualstudio_py_testlauncher.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,11 @@ def main():
308308
test = ''
309309
)
310310
if opts.uvInt is None:
311-
opts.uvInt = 0
312-
runner = unittest.TextTestRunner(verbosity=opts.uvInt, resultclass=VsTestResult)
311+
opts.uvInt = 0
313312
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)
316316
result = runner.run(tests)
317317
sys.exit(not result.wasSuccessful())
318318
finally:

src/client/unittests/unittest/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ export class TestManager extends BaseTestManager {
2424
return fn.testFunction.status === TestStatus.Error || fn.testFunction.status === TestStatus.Fail;
2525
}).map(fn => fn.testFunction);
2626
}
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);
2828
}
2929
}

src/client/unittests/unittest/runner.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
'use strict';
44
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';
1313

1414
const settings = PythonSettings.getInstance();
1515
interface TestStatusMap {
@@ -30,12 +30,12 @@ interface ITestData {
3030
traceback: string;
3131
}
3232

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> {
3434
tests.summary.errors = 0;
3535
tests.summary.failures = 0;
3636
tests.summary.passed = 0;
3737
tests.summary.skipped = 0;
38-
38+
let failFast = false;
3939
const testLauncherFile = path.join(__dirname, '..', '..', '..', '..', 'pythonFiles', 'PythonTools', 'visualstudio_py_testlauncher.py');
4040
const server = new Server();
4141
server.on('error', (message: string, ...data: string[]) => {
@@ -55,6 +55,10 @@ export function runTest(rootDirectory: string, tests: Tests, args: string[], tes
5555
test.testFunction.message = data.message;
5656
test.testFunction.traceback = data.traceback;
5757
tests.summary[statusDetails.summaryProperty] += 1;
58+
59+
if (failFast && (statusDetails.summaryProperty === 'failures' || statusDetails.summaryProperty === 'errors')) {
60+
testManager.stop();
61+
}
5862
}
5963
});
6064
server.on('socket.disconnected', (data) => {
@@ -69,6 +73,9 @@ export function runTest(rootDirectory: string, tests: Tests, args: string[], tes
6973

7074
function runTest(testFile: string = '', testId: string = '') {
7175
let testArgs = buildTestArgs(args);
76+
failFast = testArgs.indexOf('--uf') >= 0;
77+
testArgs = testArgs.filter(arg=>arg !== '--uf');
78+
7279
testArgs.push(`--result-port=${port}`);
7380
testArgs.push(`--us=${startTestDiscoveryDirectory}`);
7481
if (testId.length > 0) {

src/test/extension.unittests.unittest.test.ts

Lines changed: 148 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ import * as assert from 'assert';
1212
// You can import and use all API from the \'vscode\' module
1313
// as well as import your extension to test it
1414
import * as vscode from 'vscode';
15-
import { TestStatus} from '../client/unittests/common/contracts';
15+
import { TestsToRun } from '../client/unittests/common/contracts';
1616
import * as unittest from '../client/unittests/unittest/main';
1717
import { TestResultDisplay } from '../client/unittests/display/main';
1818

19-
let unittestManager: unittest.TestManager;
20-
let testResultDisplay: TestResultDisplay;
21-
let outChannel: vscode.OutputChannel;
2219

2320
import * as path from 'path';
2421
import * as configSettings from '../client/common/configSettings';
@@ -45,61 +42,167 @@ class MockOutputChannel implements vscode.OutputChannel {
4542
dispose() { }
4643
}
4744

48-
suiteSetup(done => {
49-
initialize().then(() => {
45+
suite('Unit Tests (unittest)', () => {
46+
suiteSetup(done => {
47+
initialize().then(() => {
48+
done();
49+
});
50+
});
51+
suiteTeardown(done => {
5052
done();
5153
});
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;
5670

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);
63131
// });
64132

65-
test('Discover Tests', () => {
66-
const rootDirectory = UNITTEST_TEST_FILES_PATH;
133+
test('Run Failed Tests', done => {
67134
pythonSettings.unitTest.unittestArgs = [
68135
'-s=./tests',
69-
'-p=test_*.py'
136+
'-p=*test*.py'
70137
];
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();
82151
});
83-
}
152+
}).catch(done);
84153
});
85154

86-
test('Discover Tests (pattern = *_test_*.py)', () => {
87-
const rootDirectory = UNITTEST_TEST_FILES_PATH;
155+
test('Run Specific Test File', done => {
88156
pythonSettings.unitTest.unittestArgs = [
89157
'-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'
91195
];
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();
102205
});
103-
}
206+
}).catch(done);
104207
});
105208
});

src/test/pythonFiles/unitests/tests/test_unittest_one.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ def test_A(self):
1010
def test_B(self):
1111
self.assertEqual(1, 1, 'Not equal')
1212

13+
@unittest.skip("demonstrating skipping")
14+
def test_c(self):
15+
self.assertEqual(1, 1, 'Not equal')
16+
1317

1418
if __name__ == '__main__':
1519
unittest.main()

src/test/pythonFiles/unitests/tests/test_unittest_two.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ def test_A2(self):
77
def test_B2(self):
88
self.assertEqual(1,1,'Not equal')
99

10+
def test_C2(self):
11+
self.assertEqual(1,2,'Not equal')
12+
13+
def test_D2(self):
14+
raise ArithmeticError()
15+
pass
16+
1017
class Test_test2a(unittest.TestCase):
1118
def test_222A2(self):
1219
self.fail("Not implemented")

0 commit comments

Comments
 (0)