You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As a developer of a large app project, I want to have confidence fast that my changes are working and then know exactly which changes have failed.
With Dart workspaces projects may look like the following:
app/
pubspec.yaml
test/
packages/
core/
core_library_1/
pubspec.yaml
test/
core_library_2/
pubspec.yaml
test/
features/
feature_a/
pubspec.yaml → depends only on core_library_1 (via `path: ../../core/core_libary_1` import)
test/
feature_b/
pubspec.yaml → depends only on core_library_2 (via `path: ../../core/core_libary_2` import)
test/
A typical, simple way to run those test would be by simply calling:
very_good_cli:very_good test --recursive --coverage from within the app/ folder to run all tests.
There are several issues with this:
It runs all tests, all the time.
When it runs all tests, the test results are all appended one after the other. This can lead to weird situations where the check fails, but it says 00:51 +224: All tests passed! at the end, because the last test suite passed, while some earlier test suite failed.
It runs all test one after another, instead of parallelising them on different machines.
Now imagine the following developer experience:
You open a PR making changes only within the core_library_2 package.
very_good_cli detects that changes were only done within core_library_2 and it detects that feature_b depends on core_library_2 → so it will test both core_library_2 and feature_b
It spins out a test matrix, starting two GitHub Action checks for core_library_2 and feature_b
Each package test run in isolation, get their own success/fail status and dedicated logs
Each package reports their own coverage, coverage from untested packages are carried forward
Once all packages checks are finished a check combining all test results is created with a failed status when at least one package failed
This is how an example GitHub Action workflow could look like:
GitHub Action - very_good_cli Test Matrix
name: CIon:
pull_request:
branches: [main]push:
branches: [main]jobs:
detect-affected:
runs-on: ubuntu-latestoutputs:
matrix: ${{ steps.affected.outputs.matrix }}has_affected: ${{ steps.affected.outputs.has_affected }}steps:
- uses: actions/checkout@v4with:
fetch-depth: 0# Requires full history to diff against target branch
- uses: subosito/flutter-action@v2with:
channel: 'stable'
- name: Install Very Good CLIrun: dart pub global activate very_good_cli
- name: Detect Affected Workspace Packagesid: affectedrun: | # Hypothetical CLI command: inspects Git diff against target branch, # maps workspace dependencies, and outputs JSON array of targets: # [{"name": "core_library_2", "path": "packages/core/core_library_2"}, ...] MATRIX_JSON=$(very_good workspace matrix --base origin/${{ github.base_ref || 'main' }}) echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT if [ "$MATRIX_JSON" = "[]" ]; then echo "has_affected=false" >> $GITHUB_OUTPUT else echo "has_affected=true" >> $GITHUB_OUTPUT fitest:
needs: detect-affectedif: ${{ needs.detect-affected.outputs.has_affected == 'true' }}runs-on: ubuntu-lateststrategy:
fail-fast: false # Allows all matrix jobs to complete so developers see all failuresmatrix:
package: ${{ fromJson(needs.detect-affected.outputs.matrix) }}steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2with:
channel: 'stable'
- name: Install Very Good CLIrun: dart pub global activate very_good_cli
- name: unit tests - ${{ matrix.package.name }}working-directory: ${{ matrix.package.path }}run: | very_good test --coverage
- name: Upload Coverage to Codecovuses: codecov/codecov-action@v4working-directory: ${{ matrix.package.path }}with:
files: ${{ matrix.package.path }}/coverage/lcov.infoflags: ${{ matrix.package.name }} # Essential for Codecov Carryforward Flagstoken: ${{ secrets.CODECOV_TOKEN }}ci-status:
name: unit testsneeds: [detect-affected, test]if: always()runs-on: ubuntu-lateststeps:
- name: Evaluate Aggregate Matrix Statusrun: | if [ "${{ needs.test.result }}" == "failure" ] || [ "${{ needs.detect-affected.result }}" == "failure" ]; then echo "One or more package checks failed." exit 1 fi echo "All affected package tests passed successfully!"
To enable this only one new command would have to be added:
The command accepts a --base argument allowing it to diff the changes between the base ref and the current state.
The command returns a JSON list of affected projects (all projects whose tests need to re-run).
The returned JSON list contains the name (from the pubspec.yaml) and the path (relative to the current directory) of the project.
The affected projects are determined based on whether changes have been done within the project compared to --base <ref> or whether another projects has been changed the project depends on via a path: ../other_package dependency.
Both dependencies and dev_dependencies are considered for the dependency.
Additional Context
This is what tests look like currently for us ...
They run for 20 minutes and emit > 6000 log lines, while not showcasing the test failures at the very end:
Description
Note
As a developer of a large app project, I want to have confidence fast that my changes are working and then know exactly which changes have failed.
With Dart workspaces projects may look like the following:
A typical, simple way to run those test would be by simply calling:
very_good_cli:very_good test --recursive --coveragefrom within theapp/folder to run all tests.There are several issues with this:
00:51 +224: All tests passed!at the end, because the last test suite passed, while some earlier test suite failed.Now imagine the following developer experience:
core_library_2package.core_library_2and it detects thatfeature_bdepends oncore_library_2→ so it will test bothcore_library_2andfeature_bcore_library_2andfeature_bThis is how an example GitHub Action workflow could look like:
GitHub Action - very_good_cli Test Matrix
To enable this only one new command would have to be added:
returning the following information:
Requirements
very_good workspace matrix.--baseargument allowing it to diff the changes between the base ref and the current state.name(from the pubspec.yaml) and thepath(relative to the current directory) of the project.--base <ref>or whether another projects has been changed the project depends on via apath: ../other_packagedependency.dependenciesanddev_dependenciesare considered for the dependency.Additional Context
This is what tests look like currently for us ...
They run for 20 minutes and emit > 6000 log lines, while not showcasing the test failures at the very end:
