-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add test optimizer brick (#639)
- Loading branch information
1 parent
3bef875
commit 3f8434e
Showing
16 changed files
with
441 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
name: test_optimizer_ci | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
on: | ||
push: | ||
paths: | ||
- .github/workflows/test_optimizer.yaml | ||
- bricks/test_optimizer/**" | ||
branches: | ||
- main | ||
pull_request: | ||
paths: | ||
- .github/workflows/test_optimizer.yaml | ||
- bricks/test_optimizer/**" | ||
branches: | ||
- main | ||
|
||
jobs: | ||
build_hooks: | ||
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v1 | ||
with: | ||
dart_sdk: 2.19.0 | ||
working_directory: bricks/test_optimizer/hooks | ||
|
||
verify_bundle: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3.3.0 | ||
|
||
- uses: dart-lang/setup-dart@v1 | ||
|
||
- name: Install mason | ||
run: dart pub global activate mason_cli | ||
|
||
- name: Run bundle generate | ||
run: tool/generate_test_optimizer_bundle.sh | ||
|
||
- name: Check for unbundled changes | ||
run: git diff --exit-code --quiet || { echo "::error::Changes detected on the test_opitimizer brick. Please run tools/generate_test_optimizer_bundle.sh to bundle these changes"; exit 1; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# test_optimizer | ||
|
||
[![Powered by Mason](https://img.shields.io/endpoint?url=https%3A%2F%2Ftinyurl.com%2Fmason-badge)](https://github.com/felangel/mason) | ||
|
||
A brick that generates a single entrypoint for Dart tests. | ||
|
||
_Generated by [mason][1] 🧱_ | ||
|
||
## Getting Started 🚀 | ||
|
||
```sh | ||
mason make test_optimizer --package-root ./path/to/package --on-conflict overwrite | ||
``` | ||
|
||
The above command will generate a `.test_optimizer.dart` in the `test` directory that imports and executes all tests | ||
|
||
```dart | ||
// GENERATED CODE - DO NOT MODIFY BY HAND | ||
// Consider adding this file to your .gitignore. | ||
import 'app/view/app_test.dart' as app_view_app_test_dart; | ||
import 'counter/cubit/counter_cubit_test.dart' as counter_cubit_counter_cubit_test_dart; | ||
import 'counter/view/counter_page_test.dart' as counter_view_counter_page_test_dart; | ||
void main() { | ||
app_view_app_test_dart.main(); | ||
counter_cubit_counter_cubit_test_dart.main(); | ||
counter_view_counter_page_test_dart.main(); | ||
} | ||
``` | ||
|
||
[1]: https://github.com/felangel/mason | ||
|
||
--- | ||
|
||
### Note for maintainers | ||
|
||
After changing this brick, make sure to run `./tools/generate_test_optimizer_bundle.sh` from the root of the repository to update the bundle. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
name: test_optimizer | ||
description: A brick that generates a single entrypoint for Dart tests. | ||
version: 0.1.0+1 | ||
|
||
environment: | ||
mason: ">=0.1.0-dev.41 <0.1.0" | ||
|
||
vars: | ||
package-root: | ||
type: string | ||
default: "." | ||
description: The path to the package root. | ||
prompt: Please enter the path to the package root. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include: package:very_good_analysis/analysis_options.4.0.0.yaml | ||
linter: | ||
rules: | ||
public_member_api_docs: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// ignore_for_file: public_member_api_docs | ||
|
||
import 'dart:io'; | ||
|
||
import 'package:mason/mason.dart'; | ||
import 'package:path/path.dart' as path; | ||
|
||
typedef ExitFn = Never Function(int code); | ||
|
||
ExitFn exitFn = exit; | ||
|
||
Future<void> run(HookContext context) async { | ||
final packageRoot = context.vars['package-root'] as String; | ||
final testDir = Directory(path.join(packageRoot, 'test')); | ||
|
||
if (!testDir.existsSync()) { | ||
context.logger.err('Could not find directory ${testDir.path}'); | ||
exitFn(1); | ||
} | ||
|
||
final pubspec = File(path.join(packageRoot, 'pubspec.yaml')); | ||
if (!pubspec.existsSync()) { | ||
context.logger.err('Could not find pubspec.yaml at ${testDir.path}'); | ||
exitFn(1); | ||
} | ||
|
||
final pubspecContents = await pubspec.readAsString(); | ||
final flutterSdkRegExp = RegExp(r'sdk:\s*flutter$', multiLine: true); | ||
final isFlutter = flutterSdkRegExp.hasMatch(pubspecContents); | ||
|
||
final tests = testDir | ||
.listSync(recursive: true) | ||
.where((entity) => entity.isTest) | ||
.map( | ||
(entity) => path | ||
.relative(entity.path, from: testDir.path) | ||
.replaceAll(r'\', '/'), | ||
) | ||
.toList(); | ||
|
||
context.vars = {'tests': tests, 'isFlutter': isFlutter}; | ||
} | ||
|
||
extension on FileSystemEntity { | ||
bool get isTest { | ||
return this is File && path.basename(this.path).endsWith('_test.dart'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import 'package:mason/mason.dart'; | ||
|
||
import 'lib/pre_gen.dart' as pre_gen; | ||
|
||
Future<void> run(HookContext context) async { | ||
await pre_gen.run(context); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
name: hooks | ||
publish_to: none | ||
|
||
environment: | ||
sdk: ">=2.19.0 <3.0.0" | ||
|
||
dependencies: | ||
mason: ">=0.1.0-dev.41 <0.1.0" | ||
path: ^1.8.1 | ||
|
||
dev_dependencies: | ||
mocktail: ^0.3.0 | ||
test: ^1.22.2 | ||
very_good_analysis: ^4.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:hooks/pre_gen.dart' as pre_gen; | ||
import 'package:mason/mason.dart'; | ||
import 'package:mocktail/mocktail.dart'; | ||
import 'package:path/path.dart' as path; | ||
import 'package:test/test.dart'; | ||
|
||
class MockProgress extends Mock implements Progress {} | ||
|
||
class MockLogger extends Mock implements Logger {} | ||
|
||
class FakeContext extends Fake implements HookContext { | ||
@override | ||
final logger = MockLogger(); | ||
|
||
@override | ||
Map<String, Object?> vars = {}; | ||
} | ||
|
||
void main() { | ||
late HookContext context; | ||
|
||
setUp(() { | ||
context = FakeContext(); | ||
}); | ||
|
||
group('Pre gen hook', () { | ||
group('Completes', () { | ||
test('with test files list', () async { | ||
final packageRoot = | ||
Directory.systemTemp.createTempSync('test_optimizer'); | ||
File(path.join(packageRoot.path, 'pubspec.yaml')).createSync(); | ||
|
||
final testDir = Directory(path.join(packageRoot.path, 'test')) | ||
..createSync(); | ||
File(path.join(testDir.path, 'test1_test.dart')).createSync(); | ||
File(path.join(testDir.path, 'test2_test.dart')).createSync(); | ||
File(path.join(testDir.path, 'no_test_here.dart')).createSync(); | ||
|
||
context.vars['package-root'] = packageRoot.absolute.path; | ||
|
||
await pre_gen.run(context); | ||
|
||
final tests = context.vars['tests'] as List<String>; | ||
|
||
expect( | ||
tests, | ||
containsAll([ | ||
'test2_test.dart', | ||
'test1_test.dart', | ||
]), | ||
); | ||
expect(test, isNot(contains('no_test_here.dart'))); | ||
expect(context.vars['isFlutter'], false); | ||
}); | ||
|
||
test('with proper isFlutter identification', () async { | ||
final packageRoot = | ||
Directory.systemTemp.createTempSync('test_optimizer'); | ||
|
||
File(path.join(packageRoot.path, 'pubspec.yaml')) | ||
..createSync() | ||
..writeAsStringSync(''' | ||
dependencies: | ||
flutter: | ||
sdk: flutter'''); | ||
|
||
Directory(path.join(packageRoot.path, 'test')).createSync(); | ||
|
||
context.vars['package-root'] = packageRoot.absolute.path; | ||
|
||
await pre_gen.run(context); | ||
|
||
expect(context.vars['isFlutter'], true); | ||
}); | ||
}); | ||
group('Fails', () { | ||
setUp(() { | ||
pre_gen.exitFn = (code) { | ||
throw ProcessException('exit', [code.toString()]); | ||
}; | ||
}); | ||
|
||
tearDown(() { | ||
pre_gen.exitFn = exit; | ||
}); | ||
|
||
test('when target test dir does not exist', () async { | ||
final packageRoot = | ||
Directory.systemTemp.createTempSync('test_optimizer'); | ||
File(path.join(packageRoot.path, 'pubspec.yaml')).createSync(); | ||
|
||
final testDir = Directory(path.join(packageRoot.path, 'test')); | ||
|
||
context.vars['package-root'] = packageRoot.absolute.path; | ||
|
||
await expectLater( | ||
() => pre_gen.run(context), | ||
throwsA( | ||
isA<ProcessException>().having( | ||
(ex) => ex.arguments.first, | ||
'error code', | ||
equals('1'), | ||
), | ||
), | ||
); | ||
|
||
verify( | ||
() => context.logger.err('Could not find directory ${testDir.path}'), | ||
).called(1); | ||
|
||
expect(context.vars['tests'], isNull); | ||
expect(context.vars['isFlutter'], isNull); | ||
}); | ||
test('when target dir does not contain a pubspec.yaml', () async { | ||
final packageRoot = | ||
Directory.systemTemp.createTempSync('test_optimizer'); | ||
|
||
final testDir = Directory(path.join(packageRoot.path, 'test')) | ||
..createSync(); | ||
File(path.join(testDir.path, 'test1_test.dart')).createSync(); | ||
File(path.join(testDir.path, 'test2_test.dart')).createSync(); | ||
File(path.join(testDir.path, 'no_test_here.dart')).createSync(); | ||
|
||
context.vars['package-root'] = packageRoot.absolute.path; | ||
|
||
await expectLater( | ||
() => pre_gen.run(context), | ||
throwsA( | ||
isA<ProcessException>().having( | ||
(ex) => ex.arguments.first, | ||
'error code', | ||
equals('1'), | ||
), | ||
), | ||
); | ||
|
||
verify( | ||
() => context.logger.err( | ||
'Could not find pubspec.yaml at ${testDir.path}', | ||
), | ||
).called(1); | ||
|
||
expect(context.vars['tests'], isNull); | ||
expect(context.vars['isFlutter'], isNull); | ||
}); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.