Reputation: 85
Using the deno vscode extension works fine for running tests, but there doesn't seem to be an option to debug a test.
Note that I can debug deno code in vscode no problem. It's the debugging tests that's the problem.
Upvotes: 5
Views: 2063
Reputation: 33748
I'll provide some steps and some example files to help you reproduce success.
Before getting started, here are the relevant manual pages which are required reading:
You'll also need to be sure of the following:
PATH
. What I mean by this is that — in your VS Code terminal — you can type the command below and see version information:> deno --version
deno 1.25.0 (release, x86_64-apple-darwin)
v8 10.6.194.5
typescript 4.7.4
vscode_deno
extension is installed and enabled for your workspace. You should see a .vscode/settings.json
file like this:{
"deno.enable": true
}
Now you can proceed:
For clarity: here are the software versions I'm using as I write this:
% deno --version
deno 1.25.0 (release, x86_64-apple-darwin)
v8 10.6.194.5
typescript 4.7.4
% code --version
1.70.2
e4503b30fc78200f846c62cf8091b76ff5547662
x64
% code --list-extensions --show-versions | grep "deno"
[email protected]
Before a
.vscode/launch.json
file is created, VS Code offers you the ability to generate one from a provider template. If you have already created the file at.vscode/launch.json
, you will not have this option, so you'll need to move/delete your existing launch config file if you already created one.
.vscode/launch.json
file in your workspace, you'll see the default start view:.vscode/launch.json
:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"request": "launch",
/* modified: descriptive name */
"name": "Debug tests",
/* modified: was generated as "pwa-node", but VS Code shows me
a diagnostic warning for that value: "Please use type node instead(2)" */
"type": "node",
/* disabled specific entrypoint */
// "program": "${workspaceFolder}/main.ts",
"cwd": "${workspaceFolder}",
/* modified: using deno process name from my PATH */
"runtimeExecutable": "deno",
"runtimeArgs": [
/* modified: was generated as "run", but you asked about testing */
"test",
/* modified: was generated as "--inspect", but using this option
causes an initial break to wait for the debugger to attach */
"--inspect-brk"
/* disabled: allowing all permissions is unsafe: only allow
the specific permissions that your scripts need */
// "--allow-all"
],
"attachSimplePort": 9229
}
]
}
That alone should allow you to debug the tests in your workspace which don't need specific permissions. (If they do, you'll need to include them as additional runtime arguments in place of "--allow-all"
.)
Note that this configuration is equivalent to the following terminal command when the current working directory is your workspace:
deno test --inspect-brk
I'll provide an example TypeScript module and test module below so that this is a complete example (Note that I just wrote these to have an example for this answer — they're not necessarily the pinnacle of sound logic and excellent style):
mod.ts
:
/**
* Capitalizes the first letter of every word preceded by whitespace or a hyphen
* (including articles, prepositions, etc.) — see
* [Title case on Wikipedia](https://en.wikipedia.org/wiki/Title_case).
*/
export function getSimpleTitleCase(input: string): string {
const delimiterRegexp = /[\s-]/;
let result = "";
let ready = true;
for (const str of input) {
const isDelimiter = delimiterRegexp.test(str);
if (isDelimiter) {
ready = true;
result += str;
continue;
} else if (ready) {
result += str.toUpperCase();
ready = false;
continue;
}
result += str.toLowerCase();
}
return result;
}
test.ts
:
import { assertStrictEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
import { getSimpleTitleCase } from "./mod.ts";
const { test } = Deno;
test("getSimpleTitleCase: smoke test", async ({ step }) => {
const testData: Record<"expected" | "input", string>[] = [
{
expected: "The Last Jedi",
input: "the last jedi",
},
{
expected: "My Old-Fashioned Grandparents",
input: "my oLd-fAShiOned graNdPAreNTs",
},
{
expected: "Html + Css + Js",
input: "HTML + CSS + JS",
},
];
for (const { expected, input } of testData) {
await step(`correctly transforms "${expected}"`, () => {
const actual = getSimpleTitleCase(input);
assertStrictEquals(actual, expected);
});
}
});
Now that you have a complete example, you can run it:
Back in the Run and Debug view, you should see the "Debug tests" configuration available:
Note that I've also added a breakpoint to line 25
in the test.ts
module so that you can inspect the test program state in that module before the assertStrictEquals
statement, in order to visually confirm that the assertion should succeed before it is executed.
Clicking the green triangle icon by the configuration name "Debug tests" begins the debug session and starts the Deno test runner. The test runner stops at an initial breakpoint (because the argument --inspect-brk
was used) and waits for the debugger to attach — after a short duration, the debugger attaches, and we see the initial breakpoint:
We see that the breakpoint is on the first line of a module called colors.ts
— the reason why this is the initial breakpoint is that it's the first line of execution in the module graph. In the local test.ts
module, the first import is from https://deno.land/[email protected]/testing/asserts.ts
. On line 11
of that module, you can see that it also imports another module: https://deno.land/[email protected]/fmt/colors.ts
. That module has no imports, and the first line of execution in that module is line 22
, which is the location of the initial breakpoint we see.
Selecting Continue (the blue triangle icon at the left of the group of icons at the top center of the window) continues to the next manually set breakpoint (line 25
in test.ts
):
From here, you can use the debugger as you normally would — we see variables, call stack, etc.
We can see the state of the variables in the first loop iteration before the call to assertStrictEquals
and visually verify that the invocation should succeed:
{
"Local": {
"actual": "The Last Jedi",
"this": undefined
},
"Block": {
"expected": "The Last Jedi",
"input": "the last jedi"
}
}
Continuing execution breaks again at the next loop iteration and we see new variables:
{
"Local": {
"actual": "My Old-Fashioned Grandparents",
"this": undefined
},
"Block": {
"expected": "My Old-Fashioned Grandparents",
"input": "my oLd-fAShiOned graNdPAreNTs"
}
}
One final time shows the last test data case variables:
{
"Local": {
"actual": "Html + Css + Js",
"this": undefined
},
"Block": {
"expected": "Html + Css + Js",
"input": "HTML + CSS + JS"
}
}
Clicking continue at this point finishes execution of the test runner because that was the only breakpoint and it was also the final loop iteration. The debugger detaches after the test runner finishes and the window is back to the state it was in before starting:
For those interested, the ID of the VS Code theme in use in the screenshots above is
hedinne.popping-and-locking-vscode
and the font is Fira Code.
Upvotes: 9