Why such an awkward title for this post? It is the kind of search I was doing the other day when I found no hits. I'm writing this in hopes that I can save someone else the trouble I faced when the solution is, in fact, quite simple.
My Dart project contains many unit tests, but many of them use helper methods rather than calling test directly. Unfortunately, I was deep into this approach when I realized that these tests were not showing up in Android Studio's Structure view, which is otherwise a good way to navigate files.
Here is an example to illustrate the problem. Notice that the call to test is nested within the helper function, testExample.
import 'package:test/test.dart';
class Example {
bool isEven(int value) => value % 2 == 0;
}
void main() {
final example = Example();
void testExample(
String description, {
required int value,
required Function(bool) verify,
}) {
final result = example.isEven(value);
test(description, verify(result));
}
group('Example.isEven', () {
testExample(
'2 is even',
value: 2,
verify: (result) => expect(result, isTrue),
);
});
}
When this is opened in Android Studio, the Structure view looks like this:
Notice how the group is empty.
The other day, I tried different searches to find an answer. It seemed to me that there had to be some way that unit testing libraries communicated their structure to JetBrains IDEs; it could not be the case that the JetBrains engineers were doing simple string matching in source files. Yet, I had no luck. In my confusion, I even turned to ChatGPT, which confidently told me that the only way to do it would be to refactor all of my tests into (yet more) higher-order functions so that I was calling the standard test function at the top level. I asked it for a reference, hoping to find the documentation I had unsuccessfully been searching for, and it unhelpfully pointed me toward two web sites that don't address this issue. Still, I put a potential refactoring into my project plan, although with over a hundred tests and counting, and with a rather eloquent current solution, this would have been both tedious and disheartening.
One of the reasons I started writing helper methods in this particular style—that is, by sending named functions as parameters—was because this is how the bloc_test package handles testing. A day or two after having tried to search for a solution to my problem, I was in a test file and noticed that all my blocTest calls did show up in the Structure view. How was that possible? Thanks to the MIT license of bloc_test, I checked the implementation and found the @isTest annotation, which comes from the meta library. Quickly reviewing its documentation, this was clearly exactly what I needed. I included this little annotation to my project.
import 'package:meta/meta.dart';
import 'package:test/test.dart';
class Example {
bool isEven(int value) => value % 2 == 0;
}
void main() {
final example = Example();
@isTest
void testExample(
String description, {
required int value,
required Function(bool) verify,
}) {
final result = example.isEven(value);
test(description, verify(result));
}
group('Example.isEven', () {
testExample(
'2 is even',
value: 2,
verify: (result) => expect(result, isTrue),
);
});
}
The result was that my Structure view looked exactly how I wanted it.
There you go: the solution in Dart is to annotate the helper method with @isTest. The documentation of that annotation make it clear that it solves my problem, but I must not have hit the right keywords with my original search. I hope that this post helps anyone else who is caught by this issue.
No comments:
Post a Comment