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

Test parsing and running upgrades #2796

Merged
merged 18 commits into from
Apr 19, 2024
Merged

Test parsing and running upgrades #2796

merged 18 commits into from
Apr 19, 2024

Conversation

jennybc
Copy link
Member

@jennybc jennybc commented Apr 18, 2024

Intent

QA Notes

In a workspace that is an R package, click on the flask in the activity bar to activate the test explorer. If the package has testthat tests, the relevant test files will appear in a tree view, for navigation, execution, and display of test results.

I have put up a toy R package that can be used to exercise the bug fixes and features in this PR: https://github.com/jennybc/testfun. I would install this with pak::pak("jennybc/testfun"). Another good option is remotes::install_github("jennybc/testfun").

More intelligent handling of quotes inside test desc in R test explorer #2639

Run the entire test suite or just the file test-banana.R or just the individual test 'subtraction `still` "works"'. You can use the ▶️ button in the test explorer tree view or the ▶️ button in the gutter of test file to run a test item (file or test) or the double ▶️ button at the top of the explorer to run all tests.

The test 'subtraction `still` "works"' (and any other tests that have vexing quotes in the description) should run and pass.

Provide more support for describe() tests in the test explorer #2634

Use the test explorer to navigate to test-mathstuff.R and use the expando to reveal all the tests. Clear all test results from the menu accessed via the ... in the upper right corner of the TEST tree view. Here is the expected behaviour:

  • Running the single describe("matrix()", { ... }) should work: it should run, there should be green checks for both of its it()s and for the describe() itself. No other test items in this file should appear as being run; they should still have the grey circle.
  • The single describe("addition()", { ... }) should work if you run it from the gutter. A describe() with exactly 1 it() cannot be run from the explorer's treeview (VS Code tries to run just the child it()) and I'm still analyzing whether this is our problem or a bug in VS Code. This is a known issue; see Account for nested describe() in R test explorer #2805.
  • The nested describe()s and the enclosing describe("top-level describe with describe inside", { ... }) cannot be run individually and this is a known issue. For now, such a structure can only be run when the entire file is run. See Account for nested describe() in R test explorer #2805.

Improved output for skipped tests #1808 (comment)

Run the single test file test-apple-wtf.R. The messages appearing in the TEST OUTPUT tab of the lower panel should appear one to a line and include the test file location where the skip originated.

Good:

Reason: I am a skip message: test-apple-wtf.R:2:3
Reason: I am also a skip message: test-apple-wtf.R:9:3

Bad:

Reason: I am a skip messageReason: I am also a skip message

@@ -152,6 +152,7 @@ module.exports.indentationFilter = [
// --- Start Positron ---
'!**/amalthea/**/*',
'!extensions/positron-r/resources/scripts/*.R',
'!extensions/positron-r/resources/testing/**',
Copy link
Member Author

Choose a reason for hiding this comment

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

The tree-sitter queries are in .scm files and some of the precommit hygiene checks are not appropriate.

That also applies to the embedded R package for test reporting, which also lives here.

Same for the diff just below.

Comment on lines 4 to 7
(namespace_operator
lhs: (identifier)
rhs: (identifier) @parent_function
)
Copy link
Member Author

Choose a reason for hiding this comment

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

In https://github.com/posit-dev/positron/pull/2726/files#r1559866539 I promised to bring back the ability to parse testthat::test_that() and here it is.

@@ -0,0 +1,32 @@
(call
Copy link
Member Author

Choose a reason for hiding this comment

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

Moving these queries into their own files has various advantages:

  • If we want to add queries, we can drop the .scm files here and the test parser will pick them up automatically now. These queries are extremely un-fun to write and are similar to regular expressions in terms of how hard they are to understand later. I suspect it will be easier to handle more styles of usage by adding queries than by making these queries increasingly complicated.
  • Easier to test the queries in https://github.com/DavisVaughan/r-tree-sitter.
  • Easier to maintain the queries and look at diffs, now that they have some reasonable syntax highlighting. Apparently the .scm extension is conventional because it's almost like Scheme.

Comment on lines +143 to +146
* Is this a top-level call in the testthat file? Only top-level tests can be run individually.
* This is really about making sure we can distinguish a top-level `describe()` (individually
* runnable) from a `describe()` that's nested inside another `describe()` call (only runnable
* as part of its enclosing `describe()` or test file).
Copy link
Member Author

@jennybc jennybc Apr 18, 2024

Choose a reason for hiding this comment

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

There is work yet to be done re: nested describe()s. But this is one part of what's needed to determine whether a describe() can be run individually. Not used yet, but will be in future. See #2805.

Comment on lines +95 to +96
const escapedLabel = test?.label.replace(/(['"`])/g, '\\$1');
const descInsert = isSingleTest ? ` desc = '${escapedLabel || '<all tests>'}', ` : '';
Copy link
Member Author

Choose a reason for hiding this comment

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

This is what fixes things for tests where the description contains quotes or backticks.

Copy link
Member Author

Choose a reason for hiding this comment

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

Before, here's what happened when trying to run a test item with ', ", or backtick in its description:

Screen.Recording.2024-04-18.at.8.18.52.AM.mov

After, it works:

Screen.Recording.2024-04-18.at.8.14.20.AM.mov

@@ -158,7 +165,7 @@ export async function runThatTest(
break;
case 'add_result':
if (data.result !== undefined && data.test !== undefined) {
const testItem = isSingleTest
const testItem = testType === ItemType.TestThat
Copy link
Member Author

Choose a reason for hiding this comment

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

You can only assume a test result is for the test item that triggered this test run if you're running a single test_that(). In describe(it())-land, you get results for the individual it() calls, which are not the test item for the test run (although they are children of it).

Copy link
Member Author

@jennybc jennybc Apr 18, 2024

Choose a reason for hiding this comment

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

The recording in https://github.com/posit-dev/positron/pull/2796/files#r1570975865 also covers this, i.e. it's why the it() calls are correctly receiving green checks.

@jennybc jennybc force-pushed the test-parsing-upgrade branch from edfb344 to 2e63fac Compare April 18, 2024 14:46
Comment on lines 58 to 66
// TODO: Should really also require that this is a top-level describe().
case ItemType.Describe: {
const testthatInstalled = await checkInstalled('testthat', '3.2.1');
if (!testthatInstalled) {
return Promise.resolve('testthat >= 3.2.1 is needed to run R a single describe() test.');
}
LOGGER.info('Single describe() test');
break;
}
Copy link
Member Author

@jennybc jennybc Apr 18, 2024

Choose a reason for hiding this comment

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

Running an individual top-level describe() now works, for most usage. Known issues recorded in #2805: nested describe() is not fully accounted for; different behaviour when clicking in test explorer tree view vs. in gutter of test file when the describe() has exactly 1 it().

This recording shows running a single describe(). Note that its it() children correctly receive their result (success) and the other describe()s in the file remain un-executed.

Screen.Recording.2024-04-18.at.8.23.41.AM.mov

Comment on lines +200 to +209
// Currently skip messages leak out to the TEST RESULTS
// area, which is presumably not the long-term plan for
// how we want to use that space.
// But in the meantime, let's at least break lines.
// appendOutput method is documented to need CRLF not LF.
run.appendOutput(
data.message + ': ' + data.location + '\r\n',
undefined,
testItem
);
Copy link
Member Author

Choose a reason for hiding this comment

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

There is clearly much room for improvement re: how we use the TEST RESULTS tab of the panel, but skip message are at least readable/usable now.

Before, where skip messages are smushed together and convey no information about where they originated:
Screenshot 2024-04-18 at 8 30 14 AM

After, where we have one entry per skip and identify the origniating test file location:
Screenshot 2024-04-18 at 8 29 16 AM

@jennybc jennybc mentioned this pull request Apr 19, 2024
12 tasks
@jennybc jennybc marked this pull request as ready for review April 19, 2024 04:57
extensions/positron-r/resources/testing/describe.scm Outdated Show resolved Hide resolved
extensions/positron-r/resources/testing/describe.scm Outdated Show resolved Hide resolved
extensions/positron-r/resources/testing/test_that.scm Outdated Show resolved Hide resolved
extensions/positron-r/src/testing/parser.ts Outdated Show resolved Hide resolved
Comment on lines +222 to +223
// we start at 1 and end at (length - 1) because we don't want the surrounding quotes
desc: captureDesc.node.text.substring(1, captureDesc.node.text.length - 1),
Copy link
Contributor

Choose a reason for hiding this comment

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

There has been a request to expose a node for string_contents which is string without the " or ' quotes in the simple case, and for raw strings it would be without the raw string prefix/suffix, which is otherwise hard to account for.

What you have here won't work for raw strings, but i would not worry about that

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for that heads up. Yeah, I would definitely be a customer for string_contents if it gets added to the grammar. Agree that raw strings aren't super relevant here.

extensions/positron-r/src/testing/runner-testthat.ts Outdated Show resolved Hide resolved
@jennybc
Copy link
Member Author

jennybc commented Apr 19, 2024

I'm now waiting for https://github.com/posit-dev/positron/actions/runs/8756403214 because I want to make sure the .scm queries make it into a release build before I merge instead of my tradition, which is to learn about this after I merge 😬 .

@jennybc jennybc merged commit ffd2b5d into main Apr 19, 2024
15 checks passed
@jennybc jennybc deleted the test-parsing-upgrade branch April 19, 2024 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants