Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new r.packageTestExplorer command #6419

Merged
merged 8 commits into from
Feb 26, 2025
Merged

Conversation

juliasilge
Copy link
Contributor

@juliasilge juliasilge commented Feb 21, 2025

Addresses #6265

This PR adds a new, additional command for running R package tests in the Test Explorer UI, and maps the existing keybinding (from RStudio) to the new command:

Screenshot 2025-02-20 at 7 31 44 PM

@:r-pkg-development

Release Notes

New Features

Bug Fixes

  • N/A

QA Notes

  • In an R package, the existing keybinding Cmd+Shift+T should now pop up the Test Explorer UI and run tests there.
  • Both the old and new commands should be runnable from the command palette.
  • Both the old and new commands should be runnable multiple times in a row.
  • Let's also check the command's behavior is sensible if you open and close the workspace.

Copy link

github-actions bot commented Feb 21, 2025

E2E Tests 🚀
This PR will run tests tagged with: @:critical @:r-pkg-development

readme  valid tags

Comment on lines 131 to 132
// Wait for the test explorer to set up before running tests
await delay(500);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It takes a little while for the Test Explorer to set up; without any delay, the tests do not run. I did not see a way to check whether the Test Explorer is done setting up; see docs at https://code.visualstudio.com/docs/editor/testing and https://code.visualstudio.com/api/extension-guides/testing. I'm guessing a bit at the delay here but have tested with some real packages and this seems good for an initial go, to get this in front of people for real work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented the delay out, because I wanted to experience what you describe. When I do so, I see this:

Screenshot 2025-02-24 at 12 24 35 PM

It feels like it's attempting to run Python tests and then determines that no Python test framework is configured.

It's true that the delay results in better behaviour, but it feels like we're papering over something for which there might be a better solution.

I believe what's happening is that workbench.view.testing.focus is causing this first run of controller.resolveHandler:

// The first time this is called, `test` is undefined, therefore we do full file discovery and
// set up file watchers for the future.
// In subsequent calls, `test` will refer to a test file.
controller.resolveHandler = async (test) => {
if (test) {
await loadTestsFromFile(testingTools, test);
} else {
await discoverTestFiles(testingTools);
const watchers = await createTestthatWatchers(testingTools);
for (const watcher of watchers) {
context.subscriptions.push(watcher);
}
LOGGER.info('Testthat file watchers are in place.');
}
};

Specifically, we enter the else branch in which test files get discovered. The time this takes will vary, so a fixed delay doesn't feel great. It feels like we should instrument that in some way that we could determine if it has been completed at least once. I think this is only an issue if the first "touch" of the test explorer comes via the command.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I just did an experiment where (1) I've removed the delay and (2) I click on the test explorer beaker before I do my first run of Cmd + Shift + T (i.e. executing r.packageTestExplorer). When I do actually execute r.packageTestExplorer, it executes normally. Presumably because the initial run of controller.resolveHandler() has already completed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that is exactly what we are dealing with and you are definitely right that the delay wasn't ideal. I did a little more thinking and added an explicit event to listen for, before kicking off the command to run tests.

vscode.commands.executeCommand('workbench.view.testing.focus');
// Wait for the test explorer to set up before running tests
await delay(500);
vscode.commands.executeCommand('testing.runAll');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • We don't need to check if R is up, devtools is installed, etc, because the R extension's Test Explorer support already does this.
  • I did not map straight from the keybinding to 'testing.runAll' because it doesn't focus the Test Explorer and needs to have the Test Explorer already set up.
  • This will not respect TESTTHAT_MAX_FAILS (i.e. related to testthat::set_max_fails() not working anymore #2723) because these tests are run in separate processes IIUC; it wouldn't do us any good to pass this env var through to the test runner. We would need to follow up with additional work to have this approach for running tests respect TESTTHAT_MAX_FAILS.

@juliasilge juliasilge marked this pull request as ready for review February 21, 2025 14:31
@juliasilge juliasilge requested a review from jennybc February 21, 2025 14:54
Copy link
Member

@jennybc jennybc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It definitely works, but I've made a comment about that fixed delay. It feels like we could/should find a solution that's more correct by definition, i.e. knows we're potentially waiting for test file discovery.

Comment on lines 131 to 132
// Wait for the test explorer to set up before running tests
await delay(500);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented the delay out, because I wanted to experience what you describe. When I do so, I see this:

Screenshot 2025-02-24 at 12 24 35 PM

It feels like it's attempting to run Python tests and then determines that no Python test framework is configured.

It's true that the delay results in better behaviour, but it feels like we're papering over something for which there might be a better solution.

I believe what's happening is that workbench.view.testing.focus is causing this first run of controller.resolveHandler:

// The first time this is called, `test` is undefined, therefore we do full file discovery and
// set up file watchers for the future.
// In subsequent calls, `test` will refer to a test file.
controller.resolveHandler = async (test) => {
if (test) {
await loadTestsFromFile(testingTools, test);
} else {
await discoverTestFiles(testingTools);
const watchers = await createTestthatWatchers(testingTools);
for (const watcher of watchers) {
context.subscriptions.push(watcher);
}
LOGGER.info('Testthat file watchers are in place.');
}
};

Specifically, we enter the else branch in which test files get discovered. The time this takes will vary, so a fixed delay doesn't feel great. It feels like we should instrument that in some way that we could determine if it has been completed at least once. I think this is only an issue if the first "touch" of the test explorer comes via the command.

@juliasilge juliasilge requested a review from jennybc February 25, 2025 16:47
@jennybc
Copy link
Member

jennybc commented Feb 25, 2025

This definitely feels like the right path. But tests no longer seem to run if the test explorer has already been stood up. Presumably because _onDidDiscoverTestFiles.fire() does not fire. We somehow need to rig this to "have we ever discovered test files" vs. "did we just finish discovering test files".

You can experience what I'm talking about in a few ways, but the easiest is probably just to try to use the command / keyboard shortcut a second time. You can make it really clear the tests are not re-running by changing/adding one or clearing all results (behind the ... in the test explorer view).

@juliasilge
Copy link
Contributor Author

Oh gosh, thank you for noticing that! I was tricked last night by a quirk of one of the test packages I was looking at. I don't believe there is a way to both wait for discovery and check if discovery has happened in one step so in f6c0c1b I set this up so:

  • a listener waits for the test discovery setup event to fire
  • workspace state tracks whether we have done so already

I tested how this behaves when we close/reopen workspaces and it looks good to me.

jennybc
jennybc previously approved these changes Feb 25, 2025
Copy link
Member

@jennybc jennybc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current state is working as expected for me ✅ I made 2 last comments/suggestions.

export async function setupTestExplorer(context: vscode.ExtensionContext) {
context.workspaceState.update('testExplorerSetUp', false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a global workspace state, should we somehow namespace this to positron-r? In Positron Assistant, I see a key like this: 'positron-assistant.recentFiles'.

Co-authored-by: Jennifer (Jenny) Bryan <jenny.f.bryan@gmail.com>
Signed-off-by: Julia Silge <julia.silge@gmail.com>
@juliasilge juliasilge merged commit 888f756 into main Feb 26, 2025
8 checks passed
@juliasilge juliasilge deleted the switch-r-pkg-testing-shortcut branch February 26, 2025 14:14
@github-actions github-actions bot locked and limited conversation to collaborators Feb 26, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants