From 329ff79b2f5dd286e1bde047490c71509ec890fe Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 13:51:53 +0100 Subject: [PATCH 01/10] WIP: Support parallel rspec tests --- .devcontainer/devcontainer.json | 22 +++++++++++++ package.json | 12 +++++++ src/rspecTests.ts | 6 ++++ src/tests.ts | 10 ++++++ test/fixtures/parallel_tests/Gemfile | 5 +++ test/fixtures/parallel_tests/Gemfile.lock | 32 +++++++++++++++++++ test/fixtures/parallel_tests/Rakefile | 0 test/fixtures/parallel_tests/lib/abs.rb | 10 ++++++ test/fixtures/parallel_tests/lib/square.rb | 5 +++ test/fixtures/parallel_tests/spec/abs_spec.rb | 17 ++++++++++ .../parallel_tests/spec/square_spec.rb | 12 +++++++ .../parallel_tests/spec/test_helper.rb | 5 +++ 12 files changed, 136 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 test/fixtures/parallel_tests/Gemfile create mode 100644 test/fixtures/parallel_tests/Gemfile.lock create mode 100644 test/fixtures/parallel_tests/Rakefile create mode 100644 test/fixtures/parallel_tests/lib/abs.rb create mode 100644 test/fixtures/parallel_tests/lib/square.rb create mode 100644 test/fixtures/parallel_tests/spec/abs_spec.rb create mode 100644 test/fixtures/parallel_tests/spec/square_spec.rb create mode 100644 test/fixtures/parallel_tests/spec/test_helper.rb diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..9662c3e --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node +{ + "name": "Node.js & TypeScript", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/typescript-node:0-20" + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "yarn install", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/package.json b/package.json index b7fa0d4..9e4e00f 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,18 @@ "type": "string", "scope": "resource" }, + "rubyTestExplorer.useParallelRspec": { + "markdownDescription": "Use parallel rspec to run tests.", + "default": false, + "type": "boolean", + "scope": "resource" + }, + "rubyTestExplorer.parallelRspecCommand": { + "markdownDescription": "Define the command to run parallel rspec tests with, for example `bundle exec parallel_rspec`.", + "default": "bundle exec parallel_rspec", + "type": "string", + "scope": "resource" + }, "rubyTestExplorer.rspecDirectory": { "markdownDescription": "The location of your RSpec directory relative to the root of the workspace.", "default": "./spec/", diff --git a/src/rspecTests.ts b/src/rspecTests.ts index 12217ca..9a9ee8d 100644 --- a/src/rspecTests.ts +++ b/src/rspecTests.ts @@ -79,6 +79,9 @@ export class RspecTests extends Tests { */ protected getTestCommand(): string { let command: string = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecCommand') as string); + if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { + command = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('parallelRspecCommand') as string) + } return command || `bundle exec rspec` } @@ -137,6 +140,9 @@ export class RspecTests extends Tests { */ protected testCommandWithFormatterAndDebugger(debuggerConfig?: vscode.DebugConfiguration): string { let args = `--require ${this.getCustomFormatterLocation()} --format CustomFormatter` + if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { + args = `--test-options "${args}"` + } let cmd = `${this.getTestCommand()} ${args}` if (debuggerConfig) { cmd = this.getDebugCommand(debuggerConfig, args); diff --git a/src/tests.ts b/src/tests.ts index ce29bd3..2ecbfaf 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -355,11 +355,15 @@ export abstract class Tests { */ handleChildProcess = async (process: childProcess.ChildProcess) => new Promise((resolve, reject) => { this.currentChildProcess = process; + let joinedJsonData = { examples: [] }; this.currentChildProcess.on('exit', () => { this.log.info('Child process has exited. Sending test run finish event.'); this.currentChildProcess = undefined; this.testStatesEmitter.fire({ type: 'finished' }); + if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { + resolve('START_OF_TEST_JSON' + JSON.stringify(joinedJsonData) + 'END_OF_TEST_JSON'); + } resolve('{}'); }); @@ -371,6 +375,7 @@ export abstract class Tests { } }); + this.currentChildProcess.stdout!.pipe(split2()).on('data', (data) => { data = data.toString(); this.log.debug(`[CHILD PROCESS OUTPUT] ${data}`); @@ -388,6 +393,11 @@ export abstract class Tests { this.testStatesEmitter.fire({ type: 'test', test: data, state: 'skipped' }); } if (data.includes('START_OF_TEST_JSON')) { + if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { + let parsedJson = JSON.parse(Tests.getJsonFromOutput(data)); + joinedJsonData.examples = joinedJsonData.examples.concat(parsedJson.examples); + return; + } resolve(data); } }); diff --git a/test/fixtures/parallel_tests/Gemfile b/test/fixtures/parallel_tests/Gemfile new file mode 100644 index 0000000..8fad101 --- /dev/null +++ b/test/fixtures/parallel_tests/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem "rspec" +gem "rake" +gem "parallel_tests" diff --git a/test/fixtures/parallel_tests/Gemfile.lock b/test/fixtures/parallel_tests/Gemfile.lock new file mode 100644 index 0000000..0c73383 --- /dev/null +++ b/test/fixtures/parallel_tests/Gemfile.lock @@ -0,0 +1,32 @@ +GEM + remote: https://rubygems.org/ + specs: + diff-lcs (1.4.4) + parallel (1.23.0) + parallel_tests (4.2.1) + parallel + rake (13.0.3) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.2) + +PLATFORMS + ruby + +DEPENDENCIES + parallel_tests + rake + rspec + +BUNDLED WITH + 2.4.13 diff --git a/test/fixtures/parallel_tests/Rakefile b/test/fixtures/parallel_tests/Rakefile new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/parallel_tests/lib/abs.rb b/test/fixtures/parallel_tests/lib/abs.rb new file mode 100644 index 0000000..d0e6c04 --- /dev/null +++ b/test/fixtures/parallel_tests/lib/abs.rb @@ -0,0 +1,10 @@ +class Abs + def apply(n) + case + when n > 0 + n + when n == 0 + raise "Abs for zero is not supported" + end + end +end diff --git a/test/fixtures/parallel_tests/lib/square.rb b/test/fixtures/parallel_tests/lib/square.rb new file mode 100644 index 0000000..0fc34ea --- /dev/null +++ b/test/fixtures/parallel_tests/lib/square.rb @@ -0,0 +1,5 @@ +class Square + def apply(n) + n + n + end +end diff --git a/test/fixtures/parallel_tests/spec/abs_spec.rb b/test/fixtures/parallel_tests/spec/abs_spec.rb new file mode 100644 index 0000000..34ce80c --- /dev/null +++ b/test/fixtures/parallel_tests/spec/abs_spec.rb @@ -0,0 +1,17 @@ +require "test_helper" + +describe Abs do + it "finds the absolute value of 1" do + expect(Abs.new.apply(1)).to eq(1) + end + + it "finds the absolute value of 0" do + expect(Abs.new.apply(0)).to eq(0) + end + + it "finds the absolute value of -1" do + skip + expect(Abs.new.apply(-1)).to eq(1) + end +end + diff --git a/test/fixtures/parallel_tests/spec/square_spec.rb b/test/fixtures/parallel_tests/spec/square_spec.rb new file mode 100644 index 0000000..bd77935 --- /dev/null +++ b/test/fixtures/parallel_tests/spec/square_spec.rb @@ -0,0 +1,12 @@ +require "test_helper" + +describe Square do + it "finds the square of 2" do + expect(Square.new.apply(2)).to eq(4) + end + + it "finds the square of 3" do + expect(Square.new.apply(3)).to eq(9) + end +end + diff --git a/test/fixtures/parallel_tests/spec/test_helper.rb b/test/fixtures/parallel_tests/spec/test_helper.rb new file mode 100644 index 0000000..9bff9d6 --- /dev/null +++ b/test/fixtures/parallel_tests/spec/test_helper.rb @@ -0,0 +1,5 @@ +$LOAD_PATH << File.join(__dir__, "../lib") + +require "abs" +require "square" +require "rspec" From 4035eeb01b66e47d10837a56da2799a3297d22bb Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 12:57:10 +0000 Subject: [PATCH 02/10] Create test for parallel_tests --- test/runParallelTestTests.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 test/runParallelTestTests.ts diff --git a/test/runParallelTestTests.ts b/test/runParallelTestTests.ts new file mode 100644 index 0000000..b7ef2a0 --- /dev/null +++ b/test/runParallelTestTests.ts @@ -0,0 +1,32 @@ +import * as path from 'path'; +import * as cp from 'child_process'; + +import { runTests, downloadAndUnzipVSCode, resolveCliPathFromVSCodeExecutablePath } from 'vscode-test'; + +async function main() { + try { + const extensionDevelopmentPath = path.resolve(__dirname, '../../'); + + const vscodeExecutablePath = await downloadAndUnzipVSCode('stable') + + const cliPath = resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath) + cp.spawnSync(cliPath, ['--install-extension', 'hbenl.vscode-test-explorer'], { + encoding: 'utf-8', + stdio: 'inherit' + }) + + await runTests( + { + extensionDevelopmentPath, + extensionTestsPath: path.resolve(__dirname, './suite/frameworks/rspec/index'), + launchArgs: [path.resolve(extensionDevelopmentPath, 'test/fixtures/parallel_tests')] + } + ); + } catch (err) { + console.error(err); + console.error('Failed to run tests'); + process.exit(1); + } +} + +main(); From 65e76a94380e79cd9bf1d21c3e2b3a67a8cc5d34 Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 12:58:42 +0000 Subject: [PATCH 03/10] Let me manually start the workflow --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f84761..2d01826 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,7 @@ on: branches: - main pull_request: {} + workflow_dispatch: jobs: test: From 61a417499ecf4bfb6b0f3f5e6fb565326b6ae727 Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 14:02:35 +0100 Subject: [PATCH 04/10] Test --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d01826..298e847 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,6 +36,9 @@ jobs: - name: Run rspec tests run: | xvfb-run -a node ./out/test/runRspecTests.js + - name: Run parallel tests + run: | + xvfb-run -a node ./out/test/runParallel_TestTests.js - name: Run Ruby test run: | cd ruby && bundle exec rake From 7af0a7ebb0c2e54747494c5509d0674ae396525d Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 13:10:28 +0000 Subject: [PATCH 05/10] Fix typo --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 298e847..a8cf2ef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ jobs: xvfb-run -a node ./out/test/runRspecTests.js - name: Run parallel tests run: | - xvfb-run -a node ./out/test/runParallel_TestTests.js + xvfb-run -a node ./out/test/runParallelTestTests.js - name: Run Ruby test run: | cd ruby && bundle exec rake From 3820feb25f60bee32f987413b83ba614e129773e Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 16:01:53 +0100 Subject: [PATCH 06/10] Tweak test setup --- .vscode/launch.json | 17 +++++++++++++++-- src/rspecTests.ts | 7 ++++--- .../{parallel_tests => parallel_rspec}/Gemfile | 0 .../Gemfile.lock | 0 .../{parallel_tests => parallel_rspec}/Rakefile | 0 .../lib/abs.rb | 0 .../lib/square.rb | 0 .../spec/abs_spec.rb | 0 .../spec/square_spec.rb | 0 .../spec/test_helper.rb | 0 ...llelTestTests.ts => runParalleRspecTests.ts} | 4 ++-- 11 files changed, 21 insertions(+), 7 deletions(-) rename test/fixtures/{parallel_tests => parallel_rspec}/Gemfile (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/Gemfile.lock (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/Rakefile (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/lib/abs.rb (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/lib/square.rb (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/spec/abs_spec.rb (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/spec/square_spec.rb (100%) rename test/fixtures/{parallel_tests => parallel_rspec}/spec/test_helper.rb (100%) rename test/{runParallelTestTests.ts => runParalleRspecTests.ts} (94%) diff --git a/.vscode/launch.json b/.vscode/launch.json index b7a6aed..cd3324d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,8 +10,9 @@ "--extensionDevelopmentPath=${workspaceFolder}" ], "outFiles": [ - "${workspaceFolder}/out/src" - ] + "${workspaceFolder}/out/**/*.js" + ], + "preLaunchTask": "npm: watch" }, { "name": "Run tests for Minitest", @@ -36,6 +37,18 @@ "${workspaceFolder}/test/fixtures/rspec" ], "outFiles": ["${workspaceFolder}/out/test/**/**/*.js"] + }, + { + "name": "Run tests for Parallel RSpec", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/suite/frameworks/rspec/index", + "${workspaceFolder}/test/fixtures/parallel_rspec" + ], + "outFiles": ["${workspaceFolder}/out/test/**/**/*.js"] } ] } diff --git a/src/rspecTests.ts b/src/rspecTests.ts index 9a9ee8d..1a4f273 100644 --- a/src/rspecTests.ts +++ b/src/rspecTests.ts @@ -79,9 +79,6 @@ export class RspecTests extends Tests { */ protected getTestCommand(): string { let command: string = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecCommand') as string); - if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { - command = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('parallelRspecCommand') as string) - } return command || `bundle exec rspec` } @@ -227,6 +224,10 @@ export class RspecTests extends Tests { }; let testCommand = this.testCommandWithFormatterAndDebugger(debuggerConfig); + if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { + let normalRspecCommand = this.getTestCommand() + testCommand = testCommand.replace(normalRspecCommand, (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('parallelRspecCommand') as string)) + } this.log.info(`Running command: ${testCommand}`); let testProcess = childProcess.spawn( diff --git a/test/fixtures/parallel_tests/Gemfile b/test/fixtures/parallel_rspec/Gemfile similarity index 100% rename from test/fixtures/parallel_tests/Gemfile rename to test/fixtures/parallel_rspec/Gemfile diff --git a/test/fixtures/parallel_tests/Gemfile.lock b/test/fixtures/parallel_rspec/Gemfile.lock similarity index 100% rename from test/fixtures/parallel_tests/Gemfile.lock rename to test/fixtures/parallel_rspec/Gemfile.lock diff --git a/test/fixtures/parallel_tests/Rakefile b/test/fixtures/parallel_rspec/Rakefile similarity index 100% rename from test/fixtures/parallel_tests/Rakefile rename to test/fixtures/parallel_rspec/Rakefile diff --git a/test/fixtures/parallel_tests/lib/abs.rb b/test/fixtures/parallel_rspec/lib/abs.rb similarity index 100% rename from test/fixtures/parallel_tests/lib/abs.rb rename to test/fixtures/parallel_rspec/lib/abs.rb diff --git a/test/fixtures/parallel_tests/lib/square.rb b/test/fixtures/parallel_rspec/lib/square.rb similarity index 100% rename from test/fixtures/parallel_tests/lib/square.rb rename to test/fixtures/parallel_rspec/lib/square.rb diff --git a/test/fixtures/parallel_tests/spec/abs_spec.rb b/test/fixtures/parallel_rspec/spec/abs_spec.rb similarity index 100% rename from test/fixtures/parallel_tests/spec/abs_spec.rb rename to test/fixtures/parallel_rspec/spec/abs_spec.rb diff --git a/test/fixtures/parallel_tests/spec/square_spec.rb b/test/fixtures/parallel_rspec/spec/square_spec.rb similarity index 100% rename from test/fixtures/parallel_tests/spec/square_spec.rb rename to test/fixtures/parallel_rspec/spec/square_spec.rb diff --git a/test/fixtures/parallel_tests/spec/test_helper.rb b/test/fixtures/parallel_rspec/spec/test_helper.rb similarity index 100% rename from test/fixtures/parallel_tests/spec/test_helper.rb rename to test/fixtures/parallel_rspec/spec/test_helper.rb diff --git a/test/runParallelTestTests.ts b/test/runParalleRspecTests.ts similarity index 94% rename from test/runParallelTestTests.ts rename to test/runParalleRspecTests.ts index b7ef2a0..6c8efab 100644 --- a/test/runParallelTestTests.ts +++ b/test/runParalleRspecTests.ts @@ -19,13 +19,13 @@ async function main() { { extensionDevelopmentPath, extensionTestsPath: path.resolve(__dirname, './suite/frameworks/rspec/index'), - launchArgs: [path.resolve(extensionDevelopmentPath, 'test/fixtures/parallel_tests')] + launchArgs: [path.resolve(extensionDevelopmentPath, 'test/fixtures/parallel_rspec')] } ); } catch (err) { console.error(err); console.error('Failed to run tests'); - process.exit(1); + // process.exit(1); } } From c9441cd9e384604178c5cc831922b4317e850187 Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 16:06:29 +0100 Subject: [PATCH 07/10] More typos --- .github/workflows/test.yml | 2 +- test/{runParalleRspecTests.ts => runParallelRspecTests.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{runParalleRspecTests.ts => runParallelRspecTests.ts} (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a8cf2ef..a029691 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ jobs: xvfb-run -a node ./out/test/runRspecTests.js - name: Run parallel tests run: | - xvfb-run -a node ./out/test/runParallelTestTests.js + xvfb-run -a node ./out/test/runParallelRspecTests.js - name: Run Ruby test run: | cd ruby && bundle exec rake diff --git a/test/runParalleRspecTests.ts b/test/runParallelRspecTests.ts similarity index 100% rename from test/runParalleRspecTests.ts rename to test/runParallelRspecTests.ts From 2151803d62ba672a08996ed479b9df58726f256a Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 16:09:41 +0100 Subject: [PATCH 08/10] Ensure gem is run --- bin/setup | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/setup b/bin/setup index 736a08c..2e82ef8 100755 --- a/bin/setup +++ b/bin/setup @@ -6,4 +6,5 @@ set -vx npm install bundle install --gemfile=ruby/Gemfile bundle install --gemfile=test/fixtures/rspec/Gemfile +bundle install --gemfile=test/fixtures/parallel_rspec/Gemfile bundle install --gemfile=test/fixtures/minitest/Gemfile From a0fc44c6e01275ca1e8f61480de564748cd9ec64 Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 16:38:26 +0100 Subject: [PATCH 09/10] More refatoring --- src/rspecTests.ts | 26 ++++++++++++++++++----- test/suite/frameworks/rspec/rspec.test.ts | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/rspecTests.ts b/src/rspecTests.ts index 1a4f273..c72af9b 100644 --- a/src/rspecTests.ts +++ b/src/rspecTests.ts @@ -137,9 +137,6 @@ export class RspecTests extends Tests { */ protected testCommandWithFormatterAndDebugger(debuggerConfig?: vscode.DebugConfiguration): string { let args = `--require ${this.getCustomFormatterLocation()} --format CustomFormatter` - if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { - args = `--test-options "${args}"` - } let cmd = `${this.getTestCommand()} ${args}` if (debuggerConfig) { cmd = this.getDebugCommand(debuggerConfig, args); @@ -147,6 +144,26 @@ export class RspecTests extends Tests { return cmd } + /** + * Get test command with formatter and debugger arguments + * + * @param debuggerConfig A VS Code debugger configuration. + * @return The test command + */ + protected parallelTestCommandWithFormatter(debuggerConfig?: vscode.DebugConfiguration): string { + let args = `--test-options "--require ${this.getCustomFormatterLocation()} --format CustomFormatter"` + return `${this.getParallelTestCommand()} ${args}` + } + /** + * Get the user-configured parallel RSpec command, if there is one. + * + * @return The RSpec command + */ + protected getParallelTestCommand(): string { + let command: string = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('parallelRspecCommand') as string); + return command || `bundle exec parallel_rspec` + } + /** * Get the env vars to run the subprocess with. * @@ -225,8 +242,7 @@ export class RspecTests extends Tests { let testCommand = this.testCommandWithFormatterAndDebugger(debuggerConfig); if (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('useParallelRspec') as boolean) { - let normalRspecCommand = this.getTestCommand() - testCommand = testCommand.replace(normalRspecCommand, (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('parallelRspecCommand') as string)) + testCommand = this.parallelTestCommandWithFormatter(); } this.log.info(`Running command: ${testCommand}`); diff --git a/test/suite/frameworks/rspec/rspec.test.ts b/test/suite/frameworks/rspec/rspec.test.ts index 06344e3..ab635a7 100644 --- a/test/suite/frameworks/rspec/rspec.test.ts +++ b/test/suite/frameworks/rspec/rspec.test.ts @@ -24,7 +24,7 @@ suite('Extension Test for RSpec', () => { { type: 'suite', id: 'root', - label: 'rspec RSpec', + label: 'parallel_rspec RSpec', children: [ { file: path.resolve(dirPath, "spec/abs_spec.rb"), From 0501e6747252b041b3019e7ba5017a5c44ff51b9 Mon Sep 17 00:00:00 2001 From: lawrencegripper Date: Thu, 18 May 2023 16:43:27 +0100 Subject: [PATCH 10/10] Create separate fixture for rspec --- test/runParallelRspecTests.ts | 2 +- test/suite/frameworks/parallel_rspec/index.ts | 34 +++ .../frameworks/parallel_rspec/rspec.test.ts | 193 ++++++++++++++++++ test/suite/frameworks/rspec/rspec.test.ts | 2 +- 4 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 test/suite/frameworks/parallel_rspec/index.ts create mode 100644 test/suite/frameworks/parallel_rspec/rspec.test.ts diff --git a/test/runParallelRspecTests.ts b/test/runParallelRspecTests.ts index 6c8efab..19a9790 100644 --- a/test/runParallelRspecTests.ts +++ b/test/runParallelRspecTests.ts @@ -18,7 +18,7 @@ async function main() { await runTests( { extensionDevelopmentPath, - extensionTestsPath: path.resolve(__dirname, './suite/frameworks/rspec/index'), + extensionTestsPath: path.resolve(__dirname, './suite/frameworks/parallel_rspec/index'), launchArgs: [path.resolve(extensionDevelopmentPath, 'test/fixtures/parallel_rspec')] } ); diff --git a/test/suite/frameworks/parallel_rspec/index.ts b/test/suite/frameworks/parallel_rspec/index.ts new file mode 100644 index 0000000..7768839 --- /dev/null +++ b/test/suite/frameworks/parallel_rspec/index.ts @@ -0,0 +1,34 @@ +import * as path from 'path'; +import * as Mocha from 'mocha'; +import * as glob from 'glob'; + +export function run(): Promise { + // Create the mocha test + const mocha = new Mocha({ + ui: 'tdd' + }); + + return new Promise((c, e) => { + glob('**.test.js', { cwd: __dirname }, (err, files) => { + if (err) { + return e(err); + } + + // Add files to the test suite + files.forEach(f => mocha.addFile(path.resolve(__dirname, f))); + + try { + // Run the mocha test + mocha.run(failures => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + e(err); + } + }); + }); +} diff --git a/test/suite/frameworks/parallel_rspec/rspec.test.ts b/test/suite/frameworks/parallel_rspec/rspec.test.ts new file mode 100644 index 0000000..ab635a7 --- /dev/null +++ b/test/suite/frameworks/parallel_rspec/rspec.test.ts @@ -0,0 +1,193 @@ +import * as assert from 'assert'; +import * as path from 'path'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import { testExplorerExtensionId, TestHub, TestSuiteInfo } from 'vscode-test-adapter-api'; +import { DummyController } from '../../DummyController'; + +suite('Extension Test for RSpec', () => { + test('Load all tests', async () => { + const controller = new DummyController() + const dirPath = vscode.workspace.workspaceFolders![0].uri.path + + const testExplorerExtension = vscode.extensions.getExtension(testExplorerExtensionId)!; + const testHub = testExplorerExtension.exports; + + testHub.registerTestController(controller); + + await controller.load() + + assert.deepStrictEqual( + controller.suite, + { + type: 'suite', + id: 'root', + label: 'parallel_rspec RSpec', + children: [ + { + file: path.resolve(dirPath, "spec/abs_spec.rb"), + id: "./spec/abs_spec.rb", + label: "abs_spec.rb", + type: "suite", + children: [ + { + file: path.resolve(dirPath, "spec/abs_spec.rb"), + id: "./spec/abs_spec.rb[1:1]", + label: "finds the absolute value of 1", + line: 3, + type: "test" + }, + { + file: path.resolve(dirPath, "spec/abs_spec.rb"), + id: "./spec/abs_spec.rb[1:2]", + label: "finds the absolute value of 0", + line: 7, + type: "test" + }, + { + file: path.resolve(dirPath, "spec/abs_spec.rb"), + id: "./spec/abs_spec.rb[1:3]", + label: "finds the absolute value of -1", + line: 11, + type: "test" + } + ] + }, + { + file: path.resolve(dirPath, "spec/square_spec.rb"), + id: "./spec/square_spec.rb", + label: "square_spec.rb", + type: "suite", + children: [ + { + file: path.resolve(dirPath, "spec/square_spec.rb"), + id: "./spec/square_spec.rb[1:1]", + label: "finds the square of 2", + line: 3, + type: "test" + }, + { + file: path.resolve(dirPath, "spec/square_spec.rb"), + id: "./spec/square_spec.rb[1:2]", + label: "finds the square of 3", + line: 7, + type: "test" + } + ] + } + ] + } as TestSuiteInfo + ) + }) + + test('run test success', async () => { + const controller = new DummyController() + + const testExplorerExtension = vscode.extensions.getExtension(testExplorerExtensionId)!; + const testHub = testExplorerExtension.exports; + + testHub.registerTestController(controller); + + await controller.load() + await controller.runTest('./spec/square_spec.rb') + + assert.deepStrictEqual( + controller.testEvents['./spec/square_spec.rb[1:1]'], + [ + { state: "passed", test: "./spec/square_spec.rb[1:1]", type: "test" }, + { state: "passed", test: "./spec/square_spec.rb[1:1]", type: "test" } + ] + ) + }) + + test('run test failure', async () => { + const controller = new DummyController() + + const testExplorerExtension = vscode.extensions.getExtension(testExplorerExtensionId)!; + const testHub = testExplorerExtension.exports; + + testHub.registerTestController(controller); + + await controller.load() + await controller.runTest('./spec/square_spec.rb') + + assert.deepStrictEqual( + controller.testEvents['./spec/square_spec.rb[1:2]'][0], + { state: "failed", test: "./spec/square_spec.rb[1:2]", type: "test" } + ) + + const lastEvent = controller.testEvents['./spec/square_spec.rb[1:2]'][1] + assert.strictEqual(lastEvent.state, "failed") + assert.strictEqual(lastEvent.line, undefined) + assert.strictEqual(lastEvent.tooltip, undefined) + assert.strictEqual(lastEvent.description, undefined) + assert.ok(lastEvent.message?.startsWith("RSpec::Expectations::ExpectationNotMetError:\n expected: 9\n got: 6\n")) + + assert.strictEqual(lastEvent.decorations!.length, 1) + const decoration = lastEvent.decorations![0] + assert.strictEqual(decoration.line, 8) + assert.strictEqual(decoration.file, undefined) + assert.strictEqual(decoration.hover, undefined) + assert.strictEqual(decoration.message, " expected: 9\n got: 6\n\n(compared using ==)\n") + }) + + test('run test error', async () => { + const controller = new DummyController() + + const testExplorerExtension = vscode.extensions.getExtension(testExplorerExtensionId)!; + const testHub = testExplorerExtension.exports; + + testHub.registerTestController(controller); + + await controller.load() + await controller.runTest('./spec/abs_spec.rb[1:2]') + + assert.deepStrictEqual( + controller.testEvents['./spec/abs_spec.rb[1:2]'][0], + { state: "running", test: "./spec/abs_spec.rb[1:2]", type: "test" } + ) + + assert.deepStrictEqual( + controller.testEvents['./spec/abs_spec.rb[1:2]'][1], + { state: "failed", test: "./spec/abs_spec.rb[1:2]", type: "test" } + ) + + const lastEvent = controller.testEvents['./spec/abs_spec.rb[1:2]'][2] + assert.strictEqual(lastEvent.state, "failed") + assert.strictEqual(lastEvent.line, undefined) + assert.strictEqual(lastEvent.tooltip, undefined) + assert.strictEqual(lastEvent.description, undefined) + assert.ok(lastEvent.message?.startsWith("RuntimeError:\nAbs for zero is not supported")) + + assert.strictEqual(lastEvent.decorations!.length, 1) + const decoration = lastEvent.decorations![0] + assert.strictEqual(decoration.line, 8) + assert.strictEqual(decoration.file, undefined) + assert.strictEqual(decoration.hover, undefined) + assert.ok(decoration.message?.startsWith("Abs for zero is not supported")) + }) + + test('run test skip', async () => { + const controller = new DummyController() + + const testExplorerExtension = vscode.extensions.getExtension(testExplorerExtensionId)!; + const testHub = testExplorerExtension.exports; + + testHub.registerTestController(controller); + + await controller.load() + await controller.runTest('./spec/abs_spec.rb[1:3]') + + assert.deepStrictEqual( + controller.testEvents['./spec/abs_spec.rb[1:3]'][0], + { state: "running", test: "./spec/abs_spec.rb[1:3]", type: "test" } + ) + + assert.deepStrictEqual( + controller.testEvents['./spec/abs_spec.rb[1:3]'][1], + { state: "skipped", test: "./spec/abs_spec.rb[1:3]", type: "test" } + ) + }) +}); diff --git a/test/suite/frameworks/rspec/rspec.test.ts b/test/suite/frameworks/rspec/rspec.test.ts index ab635a7..06344e3 100644 --- a/test/suite/frameworks/rspec/rspec.test.ts +++ b/test/suite/frameworks/rspec/rspec.test.ts @@ -24,7 +24,7 @@ suite('Extension Test for RSpec', () => { { type: 'suite', id: 'root', - label: 'parallel_rspec RSpec', + label: 'rspec RSpec', children: [ { file: path.resolve(dirPath, "spec/abs_spec.rb"),