| import assert = require('assert'); |
| import path = require('path'); |
| import sinon = require('sinon'); |
| import { Uri, workspace } from 'vscode'; |
| import * as testUtils from '../../src/testUtils'; |
| import { forceDidOpenTextDocument } from './goTest.utils'; |
| import { GoTestExplorer } from '../../src/goTest/explore'; |
| import { MockExtensionContext } from '../mocks/MockContext'; |
| import { GoTest } from '../../src/goTest/utils'; |
| |
| suite('Go Test Runner', () => { |
| const fixtureDir = path.join(__dirname, '..', '..', '..', 'test', 'testdata'); |
| |
| let testExplorer: GoTestExplorer; |
| |
| suite('Profile', () => { |
| const sandbox = sinon.createSandbox(); |
| const ctx = MockExtensionContext.new(); |
| |
| let uri: Uri; |
| let stub: sinon.SinonStub<[testUtils.TestConfig], Promise<boolean>>; |
| |
| suiteSetup(async () => { |
| testExplorer = GoTestExplorer.setup(ctx, {}); |
| |
| uri = Uri.file(path.join(fixtureDir, 'codelens', 'codelens2_test.go')); |
| await forceDidOpenTextDocument(workspace, testExplorer, uri); |
| }); |
| |
| setup(() => { |
| stub = sandbox.stub(testUtils, 'goTest'); |
| stub.callsFake((cfg) => { |
| const send = cfg.goTestOutputConsumer; |
| if (send && cfg.functions instanceof Array) { |
| cfg.functions.forEach((name) => send({ Test: name, Action: 'run' })); |
| cfg.functions.forEach((name) => send({ Test: name, Action: 'pass' })); |
| } |
| return Promise.resolve(true); |
| }); |
| }); |
| |
| teardown(() => { |
| sandbox.restore(); |
| }); |
| |
| suiteTeardown(() => { |
| ctx.teardown(); |
| }); |
| |
| test('creates a profile', async () => { |
| const test = Array.from(testExplorer.resolver.allItems).filter((x) => GoTest.parseId(x.id).name)[0]; |
| assert(test, 'No tests found'); |
| |
| assert( |
| await testExplorer.runner.run( |
| { |
| include: [test], |
| exclude: undefined, |
| profile: undefined |
| }, |
| undefined, |
| { kind: 'cpu' } |
| ), |
| 'Failed to execute `go test`' |
| ); |
| assert.strictEqual(stub.callCount, 1, 'expected one call to goTest'); |
| assert(stub.lastCall.args[0].flags.some((x) => x === '--cpuprofile')); |
| assert(testExplorer.profiler.hasProfileFor(test.id), 'Did not create profile for test'); |
| }); |
| |
| test('tests are run together when not profiling', async () => { |
| const tests = Array.from(testExplorer.resolver.allItems).filter((x) => GoTest.parseId(x.id).name); |
| assert(tests, 'No tests found'); |
| |
| assert( |
| await testExplorer.runner.run({ |
| include: tests, |
| exclude: undefined, |
| profile: undefined |
| }), |
| 'Failed to execute `go test`' |
| ); |
| assert.strictEqual(stub.callCount, 1, 'expected one call to goTest'); |
| assert.deepStrictEqual( |
| stub.lastCall.args[0].functions, |
| tests.map((x) => GoTest.parseId(x.id).name) |
| ); |
| }); |
| |
| test('tests are run individually when profiling', async () => { |
| const tests = Array.from(testExplorer.resolver.allItems).filter((x) => GoTest.parseId(x.id).name); |
| assert(tests, 'No tests found'); |
| |
| console.log(`running ${tests.length} tests`); |
| |
| assert( |
| await testExplorer.runner.run( |
| { |
| include: tests, |
| exclude: undefined, |
| profile: undefined |
| }, |
| undefined, |
| { kind: 'cpu' } |
| ), |
| 'Failed to execute `go test`' |
| ); |
| console.log('verify we got expected calls'); |
| const calls = await stub.getCalls(); |
| assert.strictEqual(calls.length, tests.length, 'expected one call to goTest per test'); |
| calls.forEach((call, i) => |
| assert.deepStrictEqual(call.args[0].functions, [GoTest.parseId(tests[i].id).name]) |
| ); |
| tests.forEach((test) => |
| assert(testExplorer.profiler.hasProfileFor(test.id), `Missing profile for ${test.id}`) |
| ); |
| }); |
| }); |
| |
| suite('Subtest', () => { |
| const sandbox = sinon.createSandbox(); |
| const subTestDir = path.join(fixtureDir, 'subTest'); |
| const ctx = MockExtensionContext.new(); |
| |
| let uri: Uri; |
| let spy: sinon.SinonSpy<[testUtils.TestConfig], Promise<boolean>>; |
| |
| suiteSetup(async () => { |
| testExplorer = GoTestExplorer.setup(ctx, {}); |
| |
| uri = Uri.file(path.join(subTestDir, 'sub_test.go')); |
| await forceDidOpenTextDocument(workspace, testExplorer, uri); |
| |
| spy = sandbox.spy(testUtils, 'goTest'); |
| }); |
| |
| suiteTeardown(() => { |
| ctx.teardown(); |
| sandbox.restore(); |
| }); |
| |
| test('discover and run', async () => { |
| console.log('discover and run'); |
| // Locate TestMain and TestOther |
| const tests = testExplorer.resolver.find(uri).filter((x) => GoTest.parseId(x.id).kind === 'test'); |
| tests.sort((a, b) => a.label.localeCompare(b.label)); |
| assert.deepStrictEqual( |
| tests.map((x) => x.label), |
| ['TestMain', 'TestOther'] |
| ); |
| const [tMain, tOther] = tests; |
| |
| // Run TestMain |
| console.log('Run TestMain'); |
| assert( |
| await testExplorer.runner.run({ |
| include: [tMain], |
| exclude: undefined, |
| profile: undefined |
| }), |
| 'Failed to execute `go test`' |
| ); |
| assert.strictEqual(spy.callCount, 1, 'expected one call to goTest'); |
| |
| // Verify TestMain was run |
| console.log('Verify TestMain was run'); |
| let call = spy.lastCall.args[0]; |
| assert.strictEqual(call.dir, subTestDir); |
| assert.deepStrictEqual(call.functions, ['TestMain']); |
| spy.resetHistory(); |
| |
| // Locate subtest |
| console.log('Locate subtest'); |
| const tSub = tMain.children.get(GoTest.id(uri, 'test', 'TestMain/Sub')); |
| assert(tSub, 'Subtest was not created'); |
| |
| console.log('Locate subtests with conflicting names'); |
| const tSub2 = tMain.children.get(GoTest.id(uri, 'test', 'TestMain/Sub#01')); |
| assert(tSub2, 'Subtest #01 was not created'); |
| const tSub3 = tMain.children.get(GoTest.id(uri, 'test', 'TestMain/Sub#01#01')); |
| assert(tSub3, 'Subtest #01#01 was not created'); |
| |
| // Run subtest by itself |
| console.log('Run subtest by itself'); |
| assert( |
| await testExplorer.runner.run({ |
| include: [tSub], |
| exclude: undefined, |
| profile: undefined |
| }), |
| 'Failed to execute `go test`' |
| ); |
| assert.strictEqual(spy.callCount, 1, 'expected one call to goTest'); |
| |
| // Verify TestMain/Sub was run |
| console.log('Verify TestMain/Sub was run'); |
| call = spy.lastCall.args[0]; |
| assert.strictEqual(call.dir, subTestDir); |
| assert.deepStrictEqual(call.functions, ['TestMain/Sub']); |
| spy.resetHistory(); |
| |
| // Ensure the subtest hasn't been disposed |
| console.log('Ensure the subtest has not been disposed'); |
| assert(tSub.parent, 'Subtest was disposed'); |
| |
| // Attempt to run subtest and other test - should not work |
| console.log('Attempt to run subtest and other test'); |
| assert( |
| await testExplorer.runner.run({ |
| include: [tSub, tOther], |
| exclude: undefined, |
| profile: undefined |
| }), |
| 'Failed to execute `go test`' |
| ); |
| assert.strictEqual(spy.callCount, 0, 'expected no calls to goTest'); |
| }).timeout(4000); |
| }); |
| }); |