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
Refactor the Bazel Test configuration to support running tests on a single file or a single test #2960
Conversation
@@ -686,7 +686,9 @@ | |||
<programRunner implementation="io.flutter.run.bazel.BazelRunner"/> | |||
|
|||
<configurationType implementation="io.flutter.run.bazelTest.FlutterBazelTestConfigurationType"/> | |||
<runConfigurationProducer implementation="io.flutter.run.bazelTest.BazelTestConfigProducer"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line will get deleted during the build unless it is added to the template. This may be the cause of the travis failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, you'll want to contribute the change to resources/META-INF/plugin_template.xml, and then run ./bin/plugin generate
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
We do have an 'experimental' section in our preferences dialog; those normally start out as opt-in. You can see the options from the |
DBC: can you attach a screen shot for the UI changes? (FlutterBazelTestConfigurationEditorForm.form) |
return true; | ||
} | ||
|
||
private VirtualFile verifyFlutterTestFile(BazelTestConfig config, ConfigurationContext context, DartFile file) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible follow up: @Nullable
and @NotNull
propagation in IntelliJ can help prevents NPEs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
public static final String WIDGET_TEST_FUNCTION = "testWidgets"; | ||
|
||
public static boolean isFlutterTest(DartFile file) { | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a TODO in this method??? If not, perhaps a comment as to why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wasn't complete; I've gone back and finished this code. PTAL.
For this section, it was definitely worth fixing instead of leaving it as a TODO.
fields.setBazelTarget(StringUtil.nullize(myBuildTarget.getText().trim(), true)); | ||
fields.setLaunchingScript(StringUtil.nullize(FileUtil.toSystemIndependentName(myLaunchingScript.getText().trim()), true)); | ||
final String testName = StringUtil.nullize(this.myTestName.getText().trim(), true); | ||
final String entryFile = StringUtil.nullize(FileUtil.toSystemIndependentName(myEntryFile.getText().trim()), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call wrapping this with FileUtil.toSystemIndependentName()
, when we have Windows behaving differently is is typically because I forgot to wrap with this method.
fields.setEntryFile(StringUtil.nullize(FileUtil.toSystemIndependentName(myEntryFile.getText().trim()), true)); | ||
fields.setBazelTarget(StringUtil.nullize(myBuildTarget.getText().trim(), true)); | ||
fields.setLaunchingScript(StringUtil.nullize(FileUtil.toSystemIndependentName(myLaunchingScript.getText().trim()), true)); | ||
final String testName = StringUtil.nullize(this.myTestName.getText().trim(), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the nullize be called on this.myTestName
, if myTestName
is null, trim would throw a NPE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Nullize is the opposite of notNullize: it makes empty strings null.
The text fields, so far as I understand, have @NotNull text fields.
fields.setLaunchingScript(StringUtil.nullize(FileUtil.toSystemIndependentName(myLaunchingScript.getText().trim()), true)); | ||
final String testName = StringUtil.nullize(this.myTestName.getText().trim(), true); | ||
final String entryFile = StringUtil.nullize(FileUtil.toSystemIndependentName(myEntryFile.getText().trim()), true); | ||
final String bazelTarget = StringUtil.nullize(myBuildTarget.getText().trim(), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, shouldn't nullize()
be called on the next before trim()
is called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
I've refactored this out into a helper method so that the behavior is easier to keep consistent.
} | ||
else if (next != Scope.TARGET_PATTERN) { | ||
if (myEntryFile.getText().isEmpty()) { | ||
myEntryFile.setText(myBuildTarget.getText().replace("//", "")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need a call to StringUtil.nullize() like you have in line 84?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary, but it's a good idea.
This if statement should semantically mean that the text in myEntryFile will be the same as passing a null value. To achieve this, it's best to use the same logic for determining its value as we were using in the other line.
@@ -34,7 +34,7 @@ | |||
@Nullable | |||
public static TestType asTestCall(@NotNull PsiElement element) { | |||
final DartFile file = FlutterUtils.getDartFile(element); | |||
if (FlutterUtils.isInTestDir(file) && FlutterUtils.isInFlutterProject(element)) { | |||
if (FlutterUtils.isInTestDir(file)/* && FlutterUtils.isInFlutterProject(element)*/) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove commented out code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@DaveShuckerow LGTM On your questions:
|
…, it always counts as the script being disabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added in tests for the command line calls getting generated by the flutter test script; this will help us prevent regressions against the g3 tooling it invokes.
These changes reflect answers to my three questions from the beginning of the PR.
- Tests for the linecontributor are manual for now 😢
- I added in an experiment to turn on the new bazel test runner.
- Pub and bazel logic is different enough that I feel more comfortable separating the utilities than sharing them. I did refactor out some common logic, like the run configuration serialization.
@@ -686,7 +686,9 @@ | |||
<programRunner implementation="io.flutter.run.bazel.BazelRunner"/> | |||
|
|||
<configurationType implementation="io.flutter.run.bazelTest.FlutterBazelTestConfigurationType"/> | |||
<runConfigurationProducer implementation="io.flutter.run.bazelTest.BazelTestConfigProducer"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
fields.setEntryFile(StringUtil.nullize(FileUtil.toSystemIndependentName(myEntryFile.getText().trim()), true)); | ||
fields.setBazelTarget(StringUtil.nullize(myBuildTarget.getText().trim(), true)); | ||
fields.setLaunchingScript(StringUtil.nullize(FileUtil.toSystemIndependentName(myLaunchingScript.getText().trim()), true)); | ||
final String testName = StringUtil.nullize(this.myTestName.getText().trim(), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Nullize is the opposite of notNullize: it makes empty strings null.
The text fields, so far as I understand, have @NotNull text fields.
fields.setLaunchingScript(StringUtil.nullize(FileUtil.toSystemIndependentName(myLaunchingScript.getText().trim()), true)); | ||
final String testName = StringUtil.nullize(this.myTestName.getText().trim(), true); | ||
final String entryFile = StringUtil.nullize(FileUtil.toSystemIndependentName(myEntryFile.getText().trim()), true); | ||
final String bazelTarget = StringUtil.nullize(myBuildTarget.getText().trim(), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
I've refactored this out into a helper method so that the behavior is easier to keep consistent.
} | ||
else if (next != Scope.TARGET_PATTERN) { | ||
if (myEntryFile.getText().isEmpty()) { | ||
myEntryFile.setText(myBuildTarget.getText().replace("//", "")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary, but it's a good idea.
This if statement should semantically mean that the text in myEntryFile will be the same as passing a null value. To achieve this, it's best to use the same logic for determining its value as we were using in the other line.
@@ -34,7 +34,7 @@ | |||
@Nullable | |||
public static TestType asTestCall(@NotNull PsiElement element) { | |||
final DartFile file = FlutterUtils.getDartFile(element); | |||
if (FlutterUtils.isInTestDir(file) && FlutterUtils.isInFlutterProject(element)) { | |||
if (FlutterUtils.isInTestDir(file)/* && FlutterUtils.isInFlutterProject(element)*/) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
public static final String WIDGET_TEST_FUNCTION = "testWidgets"; | ||
|
||
public static boolean isFlutterTest(DartFile file) { | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wasn't complete; I've gone back and finished this code. PTAL.
For this section, it was definitely worth fixing instead of leaving it as a TODO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DaveShuckerow, I made a bunch of drive-by comments.
@Nullable String launchScript, | ||
@Nullable String testScript | ||
) { | ||
final Fields fields = new Fields(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add an additional ctor to Fields
here? It would mean less assignment below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class BazelTestConfigUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DaveShuckerow, how much of this code is from TestConfigUtils
? Can we share more here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot is shared. I've refactored these to have a common abstract superclass.
} | ||
|
||
// The value to use for the bazel test runner setting if no FlutterSettings are available. | ||
// TODO: set up a FlutterSettings implementation that we can use in tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use TODO(username):
here, so people will know who to ask for context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -1,94 +1,119 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you attach a screen shot for this UI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I shared a screenshot for this internally.
import java.util.Map; | ||
|
||
|
||
public class FlutterBazelTestLineMarkerContributor extends RunLineMarkerContributor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How much of this can we share with FlutterTestLineMarkerContributor
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of it 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
// The order we do the checks here determines priority. | ||
|
||
final DartSdk sdk = DartPlugin.getDartSdk(project); | ||
if (sdk == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need a call to sdk.getVersion().flutterTestSupportsFiltering(); here as well, like above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, and for two reasons:
- bazel test filtering is managed separately from the Flutter SDK AFAIK. Test filtering support was added at a later change in g3 than when it was added to the Flutter SDK.
- when the test runner is not available, all test configurations will use the legacy behavior, which doesn't attempt to filter targets.
final int lineNumber = document.getLineNumber(textOffset); | ||
|
||
// e.g., dart_location:///Users/pq/IdeaProjects/untitled1298891289891/test/unit_test.dart,3,2,["my first unit test"] | ||
final String path = containingFile.getVirtualFile().getPath(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Paths should be processed through FileUtil.toSystemIndependentName(). If such a call breaks some string assumption here, document the reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -0,0 +1,41 @@ | |||
/* | |||
* Copyright 2018 The Chromium Authors. All rights reserved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: copyrights can be 2019 now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update all files or just newly added ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From discussion, it looks like we leave copyrights on files as the year the file was created, so new files will be copyright 2019, files I created in 2018 will be copyright 2018, and other files should have their copyrights untouched.
…ular and bazel-flavored tests
We need to leave a warning when the bazel test runner experiment is turned on and the test runner is not available so that users can sync their clients. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe I've responded to all the comments.
Please take another look.
} | ||
|
||
// The value to use for the bazel test runner setting if no FlutterSettings are available. | ||
// TODO: set up a FlutterSettings implementation that we can use in tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class BazelTestConfigUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot is shared. I've refactored these to have a common abstract superclass.
return true; | ||
} | ||
|
||
private VirtualFile verifyFlutterTestFile(BazelTestConfig config, ConfigurationContext context, DartFile file) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
import java.util.Map; | ||
|
||
|
||
public class FlutterBazelTestLineMarkerContributor extends RunLineMarkerContributor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of it 😄
final int lineNumber = document.getLineNumber(textOffset); | ||
|
||
// e.g., dart_location:///Users/pq/IdeaProjects/untitled1298891289891/test/unit_test.dart,3,2,["my first unit test"] | ||
final String path = containingFile.getVirtualFile().getPath(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -1,94 +1,119 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I shared a screenshot for this internally.
I have a few questions I need to answer and fixes I need to make before submitting this:
I would like an initial review and some thoughts on the 3 questions I have left. Thanks!