Create test_common package (#1945)

* Validate only needed summaries in expression_compiler_service

* Move shared test functionality into test_common package

* Rebase on master

* Fix bad merge

* Add comments

* Run expression compiler service test with sound null safety
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
index 70e0a5a..00dd079 100644
--- a/.github/workflows/dart.yml
+++ b/.github/workflows/dart.yml
@@ -1,4 +1,4 @@
-# Created with package:mono_repo v6.5.0
+# Created with package:mono_repo v6.4.3
 name: Dart CI
 on:
   push:
@@ -22,7 +22,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable"
@@ -30,14 +30,14 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: stable
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - name: mono_repo self validate
-        run: dart pub global activate mono_repo 6.5.0
+        run: dart pub global activate mono_repo 6.4.3
       - name: mono_repo self validate
         run: dart pub global run mono_repo generate --validate
   job_002:
@@ -45,7 +45,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:format-analyze_0-test_0"
@@ -55,12 +55,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -79,26 +79,26 @@
         if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
         working-directory: dwds
   job_003:
-    name: "analyzer_and_format; linux; Dart dev; PKGS: example, fixtures/_webdevSoundSmoke, frontend_server_client, frontend_server_common; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
+    name: "analyzer_and_format; linux; Dart dev; PKGS: example, fixtures/_webdevSoundSmoke, frontend_server_client, frontend_server_common, test_common; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:example-fixtures/_webdevSoundSmoke-frontend_server_client-frontend_server_common;commands:format-analyze_0"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:example-fixtures/_webdevSoundSmoke-frontend_server_client-frontend_server_common-test_common;commands:format-analyze_0"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:example-fixtures/_webdevSoundSmoke-frontend_server_client-frontend_server_common
+            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:example-fixtures/_webdevSoundSmoke-frontend_server_client-frontend_server_common-test_common
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: example_pub_upgrade
         name: example; dart pub upgrade
         run: dart pub upgrade
@@ -151,27 +151,40 @@
         run: dart analyze --fatal-infos .
         if: "always() && steps.frontend_server_common_pub_upgrade.conclusion == 'success'"
         working-directory: frontend_server_common
+      - id: test_common_pub_upgrade
+        name: test_common; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: test_common
+      - name: "test_common; dart format --output=none --set-exit-if-changed ."
+        run: "dart format --output=none --set-exit-if-changed ."
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+      - name: "test_common; dart analyze --fatal-infos ."
+        run: dart analyze --fatal-infos .
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
   job_004:
     name: "analyzer_and_format; linux; Dart dev; PKG: webdev; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`, `dart test test/build/ensure_build_test.dart`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev;commands:format-analyze_0-test_6"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev;commands:format-analyze_0-test_7"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -194,7 +207,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:command-test_1"
@@ -204,12 +217,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -233,7 +246,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:test_2"
@@ -243,12 +256,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -268,7 +281,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:test_3"
@@ -278,12 +291,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -303,7 +316,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:test_4"
@@ -313,12 +326,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -338,7 +351,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:frontend_server_client;commands:test_5"
@@ -348,12 +361,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: frontend_server_client_pub_upgrade
         name: frontend_server_client; dart pub upgrade
         run: dart pub upgrade
@@ -369,11 +382,50 @@
       - job_003
       - job_004
   job_010:
+    name: "unit_test; linux; Dart dev; PKG: test_common; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:test_common;commands:command-test_6"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:test_common
+            os:ubuntu-latest;pub-cache-hosted;sdk:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: dev
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: test_common_pub_upgrade
+        name: test_common; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: test_common
+      - name: "test_common; Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &"
+        run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &"
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+      - name: test_common; dart test
+        run: dart test
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_011:
     name: "unit_test; linux; Dart dev; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev;commands:command-test_5"
@@ -383,12 +435,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -407,12 +459,12 @@
       - job_002
       - job_003
       - job_004
-  job_011:
+  job_012:
     name: "unit_test; linux; Dart main; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test --tags=extension`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:dwds;commands:command-test_1"
@@ -422,12 +474,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -446,12 +498,12 @@
       - job_002
       - job_003
       - job_004
-  job_012:
+  job_013:
     name: "unit_test; linux; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:dwds;commands:test_2"
@@ -461,12 +513,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -481,12 +533,12 @@
       - job_002
       - job_003
       - job_004
-  job_013:
+  job_014:
     name: "unit_test; linux; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:dwds;commands:test_3"
@@ -496,12 +548,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -516,12 +568,12 @@
       - job_002
       - job_003
       - job_004
-  job_014:
+  job_015:
     name: "unit_test; linux; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:dwds;commands:test_4"
@@ -531,12 +583,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -551,12 +603,12 @@
       - job_002
       - job_003
       - job_004
-  job_015:
+  job_016:
     name: "unit_test; linux; Dart main; PKG: frontend_server_client; `dart test -j 1`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:frontend_server_client;commands:test_5"
@@ -566,12 +618,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: frontend_server_client_pub_upgrade
         name: frontend_server_client; dart pub upgrade
         run: dart pub upgrade
@@ -586,12 +638,51 @@
       - job_002
       - job_003
       - job_004
-  job_016:
+  job_017:
+    name: "unit_test; linux; Dart main; PKG: test_common; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:test_common;commands:command-test_6"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:test_common
+            os:ubuntu-latest;pub-cache-hosted;sdk:main
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: test_common_pub_upgrade
+        name: test_common; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: test_common
+      - name: "test_common; Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &"
+        run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &"
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+      - name: test_common; dart test
+        run: dart test
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_018:
     name: "unit_test; linux; Dart main; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:webdev;commands:command-test_5"
@@ -601,12 +692,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -625,17 +716,17 @@
       - job_002
       - job_003
       - job_004
-  job_017:
+  job_019:
     name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --tags=extension`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -650,167 +741,17 @@
       - job_002
       - job_003
       - job_004
-  job_018:
-    name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: dev
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: dwds_pub_upgrade
-        name: dwds; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: dwds
-      - name: "dwds; dart test --total-shards 3 --shard-index 0 --exclude-tags=extension"
-        run: "dart test --total-shards 3 --shard-index 0 --exclude-tags=extension"
-        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
-        working-directory: dwds
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-  job_019:
-    name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: dev
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: dwds_pub_upgrade
-        name: dwds; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: dwds
-      - name: "dwds; dart test --total-shards 3 --shard-index 1 --exclude-tags=extension"
-        run: "dart test --total-shards 3 --shard-index 1 --exclude-tags=extension"
-        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
-        working-directory: dwds
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
   job_020:
-    name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`"
+    name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: dwds_pub_upgrade
-        name: dwds; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: dwds
-      - name: "dwds; dart test --total-shards 3 --shard-index 2 --exclude-tags=extension"
-        run: "dart test --total-shards 3 --shard-index 2 --exclude-tags=extension"
-        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
-        working-directory: dwds
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-  job_021:
-    name: "unit_test; windows; Dart dev; PKG: frontend_server_client; `dart test -j 1`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: dev
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: frontend_server_client_pub_upgrade
-        name: frontend_server_client; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: frontend_server_client
-      - name: "frontend_server_client; dart test -j 1"
-        run: dart test -j 1
-        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
-        working-directory: frontend_server_client
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-  job_022:
-    name: "unit_test; windows; Dart dev; PKG: webdev; `dart test -j 1`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: dev
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: webdev_pub_upgrade
-        name: webdev; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: webdev
-      - name: "webdev; dart test -j 1"
-        run: dart test -j 1
-        if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'"
-        working-directory: webdev
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-  job_023:
-    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --tags=extension`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: main
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: dwds_pub_upgrade
-        name: dwds; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: dwds
-      - name: "dwds; dart test --tags=extension"
-        run: "dart test --tags=extension"
-        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
-        working-directory: dwds
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-  job_024:
-    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: main
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -825,17 +766,17 @@
       - job_002
       - job_003
       - job_004
-  job_025:
-    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`"
+  job_021:
+    name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
-          sdk: main
+          sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -850,17 +791,17 @@
       - job_002
       - job_003
       - job_004
-  job_026:
-    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`"
+  job_022:
+    name: "unit_test; windows; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
-          sdk: main
+          sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -875,17 +816,17 @@
       - job_002
       - job_003
       - job_004
-  job_027:
-    name: "unit_test; windows; Dart main; PKG: frontend_server_client; `dart test -j 1`"
+  job_023:
+    name: "unit_test; windows; Dart dev; PKG: frontend_server_client; `dart test -j 1`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
-          sdk: main
+          sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: frontend_server_client_pub_upgrade
         name: frontend_server_client; dart pub upgrade
         run: dart pub upgrade
@@ -900,17 +841,17 @@
       - job_002
       - job_003
       - job_004
-  job_028:
-    name: "unit_test; windows; Dart main; PKG: webdev; `dart test -j 1`"
+  job_024:
+    name: "unit_test; windows; Dart dev; PKG: webdev; `dart test -j 1`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
-          sdk: main
+          sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -925,13 +866,213 @@
       - job_002
       - job_003
       - job_004
+  job_025:
+    name: "unit_test; windows; Dart dev; PKG: test_common; `dart test`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: dev
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: test_common_pub_upgrade
+        name: test_common; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: test_common
+      - name: test_common; dart test
+        run: dart test
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_026:
+    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --tags=extension`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: dwds_pub_upgrade
+        name: dwds; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: dwds
+      - name: "dwds; dart test --tags=extension"
+        run: "dart test --tags=extension"
+        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
+        working-directory: dwds
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_027:
+    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: dwds_pub_upgrade
+        name: dwds; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: dwds
+      - name: "dwds; dart test --total-shards 3 --shard-index 0 --exclude-tags=extension"
+        run: "dart test --total-shards 3 --shard-index 0 --exclude-tags=extension"
+        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
+        working-directory: dwds
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_028:
+    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: dwds_pub_upgrade
+        name: dwds; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: dwds
+      - name: "dwds; dart test --total-shards 3 --shard-index 1 --exclude-tags=extension"
+        run: "dart test --total-shards 3 --shard-index 1 --exclude-tags=extension"
+        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
+        working-directory: dwds
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
   job_029:
+    name: "unit_test; windows; Dart main; PKG: dwds; `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: dwds_pub_upgrade
+        name: dwds; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: dwds
+      - name: "dwds; dart test --total-shards 3 --shard-index 2 --exclude-tags=extension"
+        run: "dart test --total-shards 3 --shard-index 2 --exclude-tags=extension"
+        if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
+        working-directory: dwds
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_030:
+    name: "unit_test; windows; Dart main; PKG: frontend_server_client; `dart test -j 1`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: frontend_server_client_pub_upgrade
+        name: frontend_server_client; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: frontend_server_client
+      - name: "frontend_server_client; dart test -j 1"
+        run: dart test -j 1
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_031:
+    name: "unit_test; windows; Dart main; PKG: webdev; `dart test -j 1`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: webdev_pub_upgrade
+        name: webdev; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: webdev
+      - name: "webdev; dart test -j 1"
+        run: dart test -j 1
+        if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'"
+        working-directory: webdev
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_032:
+    name: "unit_test; windows; Dart main; PKG: test_common; `dart test`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
+      - id: test_common_pub_upgrade
+        name: test_common; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: test_common
+      - name: test_common; dart test
+        run: dart test
+        if: "always() && steps.test_common_pub_upgrade.conclusion == 'success'"
+        working-directory: test_common
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_033:
     name: "beta_cron; linux; Dart beta; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`"
     runs-on: ubuntu-latest
     if: "github.event_name == 'schedule'"
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:dwds;commands:command-test_5"
@@ -941,12 +1082,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: beta
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -989,13 +1130,17 @@
       - job_026
       - job_027
       - job_028
-  job_030:
+      - job_029
+      - job_030
+      - job_031
+      - job_032
+  job_034:
     name: "beta_cron; linux; Dart beta; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`"
     runs-on: ubuntu-latest
     if: "github.event_name == 'schedule'"
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:webdev;commands:command-test_5"
@@ -1005,12 +1150,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: beta
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -1053,13 +1198,17 @@
       - job_026
       - job_027
       - job_028
-  job_031:
+      - job_029
+      - job_030
+      - job_031
+      - job_032
+  job_035:
     name: "beta_cron; linux; Dart beta; PKG: dwds; `dart analyze .`"
     runs-on: ubuntu-latest
     if: "github.event_name == 'schedule'"
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:dwds;commands:analyze_1"
@@ -1069,12 +1218,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: beta
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -1113,13 +1262,17 @@
       - job_026
       - job_027
       - job_028
-  job_032:
+      - job_029
+      - job_030
+      - job_031
+      - job_032
+  job_036:
     name: "beta_cron; linux; Dart beta; PKG: webdev; `dart analyze .`"
     runs-on: ubuntu-latest
     if: "github.event_name == 'schedule'"
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:webdev;commands:analyze_1"
@@ -1129,12 +1282,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: beta
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -1173,18 +1326,22 @@
       - job_026
       - job_027
       - job_028
-  job_033:
+      - job_029
+      - job_030
+      - job_031
+      - job_032
+  job_037:
     name: "beta_cron; windows; Dart beta; PKG: dwds; `dart test -j 1`"
     runs-on: windows-latest
     if: "github.event_name == 'schedule'"
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: beta
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: dwds_pub_upgrade
         name: dwds; dart pub upgrade
         run: dart pub upgrade
@@ -1223,18 +1380,22 @@
       - job_026
       - job_027
       - job_028
-  job_034:
+      - job_029
+      - job_030
+      - job_031
+      - job_032
+  job_038:
     name: "beta_cron; windows; Dart beta; PKG: webdev; `dart test -j 1`"
     runs-on: windows-latest
     if: "github.event_name == 'schedule'"
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
         with:
           sdk: beta
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
       - id: webdev_pub_upgrade
         name: webdev; dart pub upgrade
         run: dart pub upgrade
@@ -1273,7 +1434,11 @@
       - job_026
       - job_027
       - job_028
-  job_035:
+      - job_029
+      - job_030
+      - job_031
+      - job_032
+  job_039:
     name: Notify failure
     runs-on: ubuntu-latest
     if: "(github.event_name == 'push' || github.event_name == 'schedule') && failure()"
@@ -1319,3 +1484,7 @@
       - job_032
       - job_033
       - job_034
+      - job_035
+      - job_036
+      - job_037
+      - job_038
diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md
index 6dcf861..09fb15e 100644
--- a/dwds/CHANGELOG.md
+++ b/dwds/CHANGELOG.md
@@ -10,6 +10,7 @@
   - Fill `BoundField.name` for records.
   - Display records as a container of fields.
 - Remove test-only code from `sdk_configuration.dart`.
+- Move shared test-only code to a new `test_common` package.
 
 **Breaking changes**
 - Require `sdkConfigurationProvider` in `ExpressionCompilerService`
diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml
index 43119a1..af0f93e 100644
--- a/dwds/pubspec.yaml
+++ b/dwds/pubspec.yaml
@@ -55,4 +55,6 @@
   puppeteer: ^2.19.0
   stream_channel: ^2.1.0
   test: ^1.21.1
+  test_common:
+    path: ../test_common
   webdriver: ^3.0.0
diff --git a/dwds/test/build_daemon_callstack_test.dart b/dwds/test/build_daemon_callstack_test.dart
index ba4f584..eee6161 100644
--- a/dwds/test/build_daemon_callstack_test.dart
+++ b/dwds/test/build_daemon_callstack_test.dart
@@ -9,11 +9,11 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 class TestSetup {
   static final contextUnsound = TestContext.withWeakNullSafety(
diff --git a/dwds/test/chrome_proxy_service_test.dart b/dwds/test/chrome_proxy_service_test.dart
index ec87588..8ffb75a 100644
--- a/dwds/test/chrome_proxy_service_test.dart
+++ b/dwds/test/chrome_proxy_service_test.dart
@@ -16,11 +16,11 @@
 import 'package:http/http.dart' as http;
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 final context = TestContext.withSoundNullSafety();
 
diff --git a/dwds/test/dart_uri_test.dart b/dwds/test/dart_uri_test.dart
index 91bedf3..5e061bc 100644
--- a/dwds/test/dart_uri_test.dart
+++ b/dwds/test/dart_uri_test.dart
@@ -8,9 +8,9 @@
 import 'package:dwds/src/loaders/strategy.dart';
 import 'package:dwds/src/utilities/dart_uri.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 
 import 'fixtures/fakes.dart';
-import 'fixtures/logging.dart';
 
 class TestStrategy extends FakeStrategy {
   @override
diff --git a/dwds/test/evaluate_circular_common.dart b/dwds/test/evaluate_circular_common.dart
index 87bc973..f7a0a45 100644
--- a/dwds/test/evaluate_circular_common.dart
+++ b/dwds/test/evaluate_circular_common.dart
@@ -9,11 +9,11 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 class TestSetup {
   static TestContext contextUnsound(String index) =>
diff --git a/dwds/test/evaluate_common.dart b/dwds/test/evaluate_common.dart
index 982aaf0..7da5c26 100644
--- a/dwds/test/evaluate_common.dart
+++ b/dwds/test/evaluate_common.dart
@@ -9,11 +9,11 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 class TestSetup {
   static TestContext contextUnsound(String index) =>
diff --git a/dwds/test/events_test.dart b/dwds/test/events_test.dart
index 8e8ad53..4453a24 100644
--- a/dwds/test/events_test.dart
+++ b/dwds/test/events_test.dart
@@ -11,12 +11,12 @@
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:dwds/src/utilities/server.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webdriver/async_core.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 ChromeProxyService get service =>
     fetchChromeProxyService(context.debugConnection);
diff --git a/dwds/test/expression_compiler_service_test.dart b/dwds/test/expression_compiler_service_test.dart
index 75eb4aa..5e0a03b 100644
--- a/dwds/test/expression_compiler_service_test.dart
+++ b/dwds/test/expression_compiler_service_test.dart
@@ -9,14 +9,13 @@
 import 'dart:io';
 
 import 'package:dwds/expression_compiler.dart';
+import 'package:dwds/sdk_configuration.dart';
 import 'package:dwds/src/services/expression_compiler_service.dart';
-import 'package:dwds/src/utilities/sdk_configuration.dart';
 import 'package:dwds/src/utilities/server.dart';
 import 'package:logging/logging.dart';
 import 'package:shelf/shelf.dart';
 import 'package:test/test.dart';
-
-import 'fixtures/logging.dart';
+import 'package:test_common/logging.dart';
 
 ExpressionCompilerService get service => _service!;
 late ExpressionCompilerService? _service;
@@ -47,10 +46,12 @@
       final source = outputDir.uri.resolve('try.dart');
       final packages = outputDir.uri.resolve('package_config.json');
       final kernel = outputDir.uri.resolve('try.full.dill');
+      // Expression compiler service does not need any extra assets
+      // generated in the SDK, so we use the current SDK layout and
+      // configuration.
       final executable = Platform.resolvedExecutable;
       final dartdevc =
           SdkConfiguration.defaultConfiguration.compilerWorkerPath!;
-
       // redirect logs for testing
       _output = StreamController<String>.broadcast();
       output.stream.listen(printOnFailure);
@@ -76,7 +77,7 @@
         sdkConfigurationProvider: DefaultSdkConfigurationProvider(),
       );
 
-      await service.initialize(moduleFormat: 'amd');
+      await service.initialize(moduleFormat: 'amd', soundNullSafety: true);
 
       // setup asset server
       serveHttpRequests(server, assetHandler, (e, s) {
diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart
index 9eca001..3fcd2a8 100644
--- a/dwds/test/fixtures/context.dart
+++ b/dwds/test/fixtures/context.dart
@@ -31,14 +31,14 @@
 import 'package:shelf/shelf.dart';
 import 'package:shelf_proxy/shelf_proxy.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
+import 'package:test_common/test_sdk_configuration.dart';
 import 'package:vm_service/vm_service.dart';
 // ignore: deprecated_member_use
 import 'package:webdriver/io.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
-import 'logging.dart';
 import 'server.dart';
-import 'test_sdk_configuration.dart';
 import 'utilities.dart';
 
 final _exeExt = Platform.isWindows ? '.exe' : '';
@@ -205,6 +205,7 @@
     // Generate missing SDK assets if needed.
     final sdkConfigurationProvider =
         TestSdkConfigurationProvider(verboseCompiler: verboseCompiler);
+    final sdkLayout = sdkConfigurationProvider.sdkLayout;
     final configuration = await sdkConfigurationProvider.configuration;
     configuration.validate();
 
@@ -335,6 +336,7 @@
               soundNullSafety: nullSafety == NullSafety.sound,
               experiments: experiments,
               verbose: verboseCompiler,
+              sdkLayout: sdkLayout,
             );
 
             final assetServerPort = await findUnusedPort();
diff --git a/dwds/test/frontend_server_breakpoint_test.dart b/dwds/test/frontend_server_breakpoint_test.dart
index 4b11784..f9498a3 100644
--- a/dwds/test/frontend_server_breakpoint_test.dart
+++ b/dwds/test/frontend_server_breakpoint_test.dart
@@ -9,11 +9,11 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 final context = TestContext.withWeakNullSafety(
   packageName: '_testPackage',
diff --git a/dwds/test/frontend_server_callstack_test.dart b/dwds/test/frontend_server_callstack_test.dart
index f2f8372..ec6566d 100644
--- a/dwds/test/frontend_server_callstack_test.dart
+++ b/dwds/test/frontend_server_callstack_test.dart
@@ -9,11 +9,11 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 class TestSetup {
   static final contextUnsound = TestContext.withWeakNullSafety(
diff --git a/dwds/test/handlers/asset_handler_test.dart b/dwds/test/handlers/asset_handler_test.dart
index bdb9533..4b6e5d5 100644
--- a/dwds/test/handlers/asset_handler_test.dart
+++ b/dwds/test/handlers/asset_handler_test.dart
@@ -6,9 +6,9 @@
 
 import 'package:shelf/shelf.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 
 import '../fixtures/context.dart';
-import '../fixtures/logging.dart';
 
 void main() {
   group('Asset handler', () {
diff --git a/dwds/test/records_test.dart b/dwds/test/records_test.dart
index cb090b1..57bd2da 100644
--- a/dwds/test/records_test.dart
+++ b/dwds/test/records_test.dart
@@ -8,10 +8,10 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 class TestSetup {
   TestContext context;
diff --git a/dwds/test/reload_test.dart b/dwds/test/reload_test.dart
index 8f8d09d..bffa17e 100644
--- a/dwds/test/reload_test.dart
+++ b/dwds/test/reload_test.dart
@@ -6,10 +6,10 @@
 @Timeout(Duration(minutes: 5))
 import 'package:dwds/src/loaders/strategy.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 import 'fixtures/utilities.dart';
 
 final context = TestContext.withSoundNullSafety(
diff --git a/dwds/test/restore_breakpoints_test.dart b/dwds/test/restore_breakpoints_test.dart
index e21c3e3..d9313ce 100644
--- a/dwds/test/restore_breakpoints_test.dart
+++ b/dwds/test/restore_breakpoints_test.dart
@@ -9,11 +9,11 @@
 import 'package:dwds/src/connections/debug_connection.dart';
 import 'package:dwds/src/services/chrome_proxy_service.dart';
 import 'package:test/test.dart';
+import 'package:test_common/logging.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
 import 'fixtures/context.dart';
-import 'fixtures/logging.dart';
 
 final context = TestContext.withSoundNullSafety();
 ChromeProxyService get service =>
diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart
index fd00c05..9bd7c9c 100644
--- a/frontend_server_common/lib/src/devfs.dart
+++ b/frontend_server_common/lib/src/devfs.dart
@@ -7,13 +7,11 @@
 import 'package:dwds/asset_reader.dart';
 import 'package:file/file.dart';
 import 'package:path/path.dart' as p;
+import 'package:test_common/test_sdk_layout.dart';
 
 import 'asset_server.dart';
 import 'bootstrap.dart';
 import 'frontend_server_client.dart';
-import 'utilities.dart';
-
-final String dartWebSdkPath = p.join(dartSdkPath, 'lib', 'dev_compiler');
 
 class WebDevFS {
   WebDevFS({
@@ -25,6 +23,7 @@
     required this.index,
     required this.soundNullSafety,
     this.urlTunneler,
+    required this.sdkLayout,
   });
 
   final FileSystem fileSystem;
@@ -36,6 +35,7 @@
   final String index;
   final UrlEncoder? urlTunneler;
   final bool soundNullSafety;
+  final TestSdkLayout sdkLayout;
   late final Directory _savedCurrentDirectory;
 
   Future<Uri> create() async {
@@ -85,9 +85,9 @@
 
     assetServer.writeFile('main_module.digests', '{}');
 
-    var sdk = soundNullSafety ? dartSdkSound : dartSdk;
+    var sdk = soundNullSafety ? dartSdk : dartSdkWeak;
     var sdkSourceMap =
-        soundNullSafety ? dartSdkSourcemapSound : dartSdkSourcemap;
+        soundNullSafety ? dartSdkSourcemap : dartSdkSourcemapWeak;
     assetServer.writeFile('dart_sdk.js', sdk.readAsStringSync());
     assetServer.writeFile('dart_sdk.js.map', sdkSourceMap.readAsStringSync());
 
@@ -129,45 +129,12 @@
     )..invalidatedModules = modules;
   }
 
-  File get requireJS => fileSystem.file(fileSystem.path.join(
-        dartWebSdkPath,
-        'amd',
-        'require.js',
-      ));
-
-  File get dartSdk => fileSystem.file(fileSystem.path.join(
-        dartWebSdkPath,
-        'kernel',
-        'amd',
-        'dart_sdk_unsound.js',
-      ));
-
-  File get dartSdkSound => fileSystem.file(fileSystem.path.join(
-        dartWebSdkPath,
-        'kernel',
-        'amd',
-        'dart_sdk.js',
-      ));
-
-  File get dartSdkSourcemap => fileSystem.file(fileSystem.path.join(
-        dartWebSdkPath,
-        'kernel',
-        'amd',
-        'dart_sdk_unsound.js.map',
-      ));
-
-  File get dartSdkSourcemapSound => fileSystem.file(fileSystem.path.join(
-        dartWebSdkPath,
-        'kernel',
-        'amd',
-        'dart_sdk.js.map',
-      ));
-
-  File get stackTraceMapper => fileSystem.file(fileSystem.path.join(
-        dartWebSdkPath,
-        'web',
-        'dart_stack_trace_mapper.js',
-      ));
+  File get requireJS => fileSystem.file(sdkLayout.requireJsPath);
+  File get dartSdkWeak => fileSystem.file(sdkLayout.weakJsPath);
+  File get dartSdk => fileSystem.file(sdkLayout.soundJsPath);
+  File get dartSdkSourcemapWeak => fileSystem.file(sdkLayout.weakJsMapPath);
+  File get dartSdkSourcemap => fileSystem.file(sdkLayout.soundJsMapPath);
+  File get stackTraceMapper => fileSystem.file(sdkLayout.stackTraceMapperPath);
 }
 
 class UpdateFSReport {
diff --git a/frontend_server_common/lib/src/frontend_server_client.dart b/frontend_server_common/lib/src/frontend_server_client.dart
index 9119377..5aa733b 100644
--- a/frontend_server_common/lib/src/frontend_server_client.dart
+++ b/frontend_server_common/lib/src/frontend_server_client.dart
@@ -11,7 +11,7 @@
 import 'package:dwds/expression_compiler.dart';
 import 'package:logging/logging.dart';
 import 'package:package_config/package_config.dart';
-import 'package:path/path.dart' as p;
+import 'package:test_common/test_sdk_layout.dart';
 import 'package:usage/uuid/uuid.dart';
 
 import 'utilities.dart';
@@ -24,9 +24,6 @@
         ? _serverLogger.info(message)
         : _serverLogger.severe(message, null, stackTrace);
 
-String get frontendServerExecutable =>
-    p.join(dartSdkPath, 'bin', 'snapshots', 'frontend_server.dart.snapshot');
-
 typedef CompilerMessageConsumer = void Function(String message,
     {StackTrace stackTrace});
 
@@ -261,6 +258,7 @@
     required this.platformDill,
     required this.soundNullSafety,
     this.experiments = const <String>[],
+    required this.sdkLayout,
     this.verbose = false,
     CompilerMessageConsumer compilerMessageConsumer = defaultConsumer,
   }) : _stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer);
@@ -273,6 +271,7 @@
   final String platformDill;
   final bool soundNullSafety;
   final List<String> experiments;
+  final TestSdkLayout sdkLayout;
   final bool verbose;
 
   /// The path to the root of the Dart SDK used to compile.
@@ -362,7 +361,7 @@
 
   Future<CompilerOutput?> _compile(
       String scriptUri, String outputFilePath) async {
-    var frontendServer = frontendServerExecutable;
+    var frontendServer = sdkLayout.frontendServerSnapshotPath;
     var args = <String>[
       frontendServer,
       '--sdk-root',
diff --git a/frontend_server_common/lib/src/resident_runner.dart b/frontend_server_common/lib/src/resident_runner.dart
index 99b1ed8..1c9af81 100644
--- a/frontend_server_common/lib/src/resident_runner.dart
+++ b/frontend_server_common/lib/src/resident_runner.dart
@@ -11,17 +11,12 @@
 import 'package:dwds/expression_compiler.dart';
 import 'package:file/file.dart';
 import 'package:logging/logging.dart';
-import 'package:path/path.dart' as p;
+import 'package:test_common/test_sdk_layout.dart';
 
 import 'devfs.dart';
 import 'frontend_server_client.dart';
 import 'utilities.dart';
 
-final Uri summaryDillUnsound = Uri.file(
-    p.join(dartSdkPath, 'lib', '_internal', 'ddc_outline_unsound.dill'));
-final Uri summaryDillSound =
-    Uri.file(p.join(dartSdkPath, 'lib', '_internal', 'ddc_outline.dill'));
-
 class ResidentWebRunner {
   final _logger = Logger('ResidentWebRunner');
 
@@ -36,19 +31,24 @@
     required this.outputPath,
     required this.soundNullSafety,
     this.experiments = const <String>[],
+    required this.sdkLayout,
     bool verbose = false,
   }) {
+    final platformDillUri = Uri.file(soundNullSafety
+        ? sdkLayout.soundSummaryPath
+        : sdkLayout.weakSummaryPath);
+
     generator = ResidentCompiler(
       dartSdkPath,
       projectDirectory: projectDirectory,
       packageConfigFile: packageConfigFile,
       useDebuggerModuleNames: packageUriMapper.useDebuggerModuleNames,
-      platformDill:
-          soundNullSafety ? '$summaryDillSound' : '$summaryDillUnsound',
+      platformDill: '$platformDillUri',
       fileSystemRoots: fileSystemRoots,
       fileSystemScheme: fileSystemScheme,
       soundNullSafety: soundNullSafety,
       experiments: experiments,
+      sdkLayout: sdkLayout,
       verbose: verbose,
     );
     expressionCompiler = TestExpressionCompiler(generator);
@@ -64,6 +64,7 @@
   final String fileSystemScheme;
   final bool soundNullSafety;
   final List<String> experiments;
+  final TestSdkLayout sdkLayout;
 
   late ResidentCompiler generator;
   late ExpressionCompiler expressionCompiler;
@@ -82,6 +83,7 @@
       index: index,
       urlTunneler: urlTunneler,
       soundNullSafety: soundNullSafety,
+      sdkLayout: sdkLayout,
     );
     uri = await devFS.create();
 
diff --git a/frontend_server_common/pubspec.yaml b/frontend_server_common/pubspec.yaml
index e410d68..d9ed206 100644
--- a/frontend_server_common/pubspec.yaml
+++ b/frontend_server_common/pubspec.yaml
@@ -16,4 +16,6 @@
   package_config: ^2.0.0
   path: ^1.8.0
   pub_semver: ^2.1.1
+  test_common:
+    path: ../test_common
   usage: ^4.0.0
diff --git a/test_common/analysis_options.yaml b/test_common/analysis_options.yaml
new file mode 100644
index 0000000..64d22c0
--- /dev/null
+++ b/test_common/analysis_options.yaml
@@ -0,0 +1,13 @@
+# This file contains the analysis options used for code in the webdev
+# repository.
+
+include: package:lints/recommended.yaml
+
+analyzer:
+
+linter:
+  rules:
+    - always_use_package_imports
+    - directives_ordering
+    - prefer_final_locals
+    - unawaited_futures
diff --git a/test_common/dart_test.yaml b/test_common/dart_test.yaml
new file mode 100644
index 0000000..94245ee
--- /dev/null
+++ b/test_common/dart_test.yaml
@@ -0,0 +1,3 @@
+concurrency: 1
+retry: 3
+
diff --git a/dwds/test/fixtures/logging.dart b/test_common/lib/logging.dart
similarity index 100%
rename from dwds/test/fixtures/logging.dart
rename to test_common/lib/logging.dart
diff --git a/dwds/test/fixtures/sdk_asset_generator.dart b/test_common/lib/sdk_asset_generator.dart
similarity index 98%
rename from dwds/test/fixtures/sdk_asset_generator.dart
rename to test_common/lib/sdk_asset_generator.dart
index 83f977a..21bcf55 100644
--- a/dwds/test/fixtures/sdk_asset_generator.dart
+++ b/test_common/lib/sdk_asset_generator.dart
@@ -5,8 +5,7 @@
 import 'package:file/local.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart' as p;
-
-import 'test_sdk_layout.dart';
+import 'package:test_common/test_sdk_layout.dart';
 
 /// Generates sdk.js, sdk.map, sdk full dill, and sdk summary files.
 ///
diff --git a/dwds/test/fixtures/test_sdk_configuration.dart b/test_common/lib/test_sdk_configuration.dart
similarity index 90%
rename from dwds/test/fixtures/test_sdk_configuration.dart
rename to test_common/lib/test_sdk_configuration.dart
index 29c35bb..f93fe69 100644
--- a/dwds/test/fixtures/test_sdk_configuration.dart
+++ b/test_common/lib/test_sdk_configuration.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // TODO:(annagrin) Move to a test_common package.
-import 'package:dwds/src/utilities/sdk_configuration.dart';
+import 'package:dwds/sdk_configuration.dart';
 
-import 'sdk_asset_generator.dart';
-import 'test_sdk_layout.dart';
+import 'package:test_common/sdk_asset_generator.dart';
+import 'package:test_common/test_sdk_layout.dart';
 
 /// Implementation for SDK configuration for tests that can generate
 /// missing assets.
diff --git a/test_common/lib/test_sdk_layout.dart b/test_common/lib/test_sdk_layout.dart
new file mode 100644
index 0000000..78a00c1
--- /dev/null
+++ b/test_common/lib/test_sdk_layout.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:dwds/sdk_configuration.dart';
+import 'package:path/path.dart' as p;
+
+/// Test Dart SDK layout.
+///
+/// Contains definition of the default SDK layout required for tests.
+/// We keep all the path constants in one place for ease of update.
+class TestSdkLayout {
+  static final defaultSdkDirectory = SdkLayout.defaultSdkDirectory;
+  static TestSdkLayout defaultSdkLayout =
+      TestSdkLayout.createDefault(defaultSdkDirectory);
+  static SdkConfiguration defaultSdkConfiguration =
+      createConfiguration(defaultSdkLayout);
+
+  factory TestSdkLayout.createDefault(String sdkDirectory) =>
+      TestSdkLayout.createDefaultFromSdkLayout(
+          SdkLayout.createDefault(sdkDirectory));
+
+  factory TestSdkLayout.createDefaultFromSdkLayout(SdkLayout sdkLayout) =>
+      TestSdkLayout(
+        sdkDirectory: sdkLayout.sdkDirectory,
+        soundSummaryPath: sdkLayout.soundSummaryPath,
+        soundFullDillPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          '_internal',
+          'ddc_platform.dill',
+        ),
+        soundJsPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          'dev_compiler',
+          'kernel',
+          'amd',
+          'dart_sdk.js',
+        ),
+        soundJsMapPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          'dev_compiler',
+          'kernel',
+          'amd',
+          'dart_sdk.js.map',
+        ),
+        weakSummaryPath: sdkLayout.weakSummaryPath,
+        weakFullDillPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          '_internal',
+          'ddc_platform_unsound.dill',
+        ),
+        weakJsPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          'dev_compiler',
+          'kernel',
+          'amd',
+          'dart_sdk_unsound.js',
+        ),
+        weakJsMapPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          'dev_compiler',
+          'kernel',
+          'amd',
+          'dart_sdk_unsound.js.map',
+        ),
+        requireJsPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          'dev_compiler',
+          'amd',
+          'require.js',
+        ),
+        stackTraceMapperPath: p.join(
+          sdkLayout.sdkDirectory,
+          'lib',
+          'dev_compiler',
+          'web',
+          'dart_stack_trace_mapper.js',
+        ),
+        dartPath: p.join(sdkLayout.sdkDirectory, 'bin', 'dart'),
+        frontendServerSnapshotPath: p.join(
+          sdkLayout.sdkDirectory,
+          'bin',
+          'snapshots',
+          'frontend_server.dart.snapshot',
+        ),
+        dartdevcSnapshotPath: sdkLayout.dartdevcSnapshotPath,
+        kernelWorkerSnapshotPath: p.join(
+          sdkLayout.sdkDirectory,
+          'bin',
+          'snapshots',
+          'kernel_worker.dart.snapshot',
+        ),
+      );
+
+  final String sdkDirectory;
+
+  String get soundJsFileName => p.basename(soundJsPath);
+  String get soundJsMapFileName => p.basename(soundJsMapPath);
+  String get soundSummaryFileName => p.basename(soundSummaryPath);
+  String get soundFullDillFileName => p.basename(soundFullDillPath);
+
+  final String soundJsPath;
+  final String soundJsMapPath;
+  final String soundSummaryPath;
+  final String soundFullDillPath;
+
+  String get weakJsFileName => p.basename(weakJsPath);
+  String get weakJsMapFileName => p.basename(weakJsMapPath);
+  String get weakSummaryFileName => p.basename(weakSummaryPath);
+  String get weakFullDillFileName => p.basename(weakFullDillPath);
+
+  final String weakJsPath;
+  final String weakJsMapPath;
+  final String weakSummaryPath;
+  final String weakFullDillPath;
+
+  final String requireJsPath;
+  final String stackTraceMapperPath;
+
+  final String dartPath;
+  final String frontendServerSnapshotPath;
+  final String dartdevcSnapshotPath;
+  final String kernelWorkerSnapshotPath;
+
+  const TestSdkLayout({
+    required this.sdkDirectory,
+    required this.soundJsPath,
+    required this.soundJsMapPath,
+    required this.soundSummaryPath,
+    required this.soundFullDillPath,
+    required this.weakJsPath,
+    required this.weakJsMapPath,
+    required this.weakSummaryPath,
+    required this.weakFullDillPath,
+    required this.requireJsPath,
+    required this.stackTraceMapperPath,
+    required this.dartPath,
+    required this.frontendServerSnapshotPath,
+    required this.dartdevcSnapshotPath,
+    required this.kernelWorkerSnapshotPath,
+  });
+
+  /// Creates configuration from sdk layout.
+  static SdkConfiguration createConfiguration(TestSdkLayout sdkLayout) =>
+      SdkConfiguration(
+        sdkDirectory: sdkLayout.sdkDirectory,
+        weakSdkSummaryPath: sdkLayout.weakSummaryPath,
+        soundSdkSummaryPath: sdkLayout.soundSummaryPath,
+        compilerWorkerPath: sdkLayout.dartdevcSnapshotPath,
+      );
+}
diff --git a/test_common/mono_pkg.yaml b/test_common/mono_pkg.yaml
new file mode 100644
index 0000000..6528b90
--- /dev/null
+++ b/test_common/mono_pkg.yaml
@@ -0,0 +1,27 @@
+# See https://pub.dev/packages/mono_repo for details
+stages:
+  - analyzer_and_format:
+    - group:
+      - format
+      - analyze: --fatal-infos .
+      sdk: dev
+  - unit_test:
+    # Linux tests:
+    # Note: `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &` must be
+    # run first for Linux.
+    - group:
+      - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
+      - test:
+      sdk:
+        - dev
+        - main
+      os:
+        - linux
+     # Windows tests:
+    - group:
+      - test:
+      sdk:
+        - dev
+        - main
+      os:
+        - windows
diff --git a/test_common/pubspec.yaml b/test_common/pubspec.yaml
new file mode 100644
index 0000000..adaae0e
--- /dev/null
+++ b/test_common/pubspec.yaml
@@ -0,0 +1,18 @@
+name: test_common
+publish_to: none
+description: >-
+  Common test functionality.
+environment:
+  sdk: ">=3.0.0-134.0.dev <4.0.0"
+
+dependencies:
+  dwds:
+    path: ../dwds
+  file: ^6.1.3
+  logging: ^1.0.1
+  path: ^1.8.1
+  test: ^1.21.1
+
+dev_dependencies:
+  lints: ^2.0.0
+
diff --git a/dwds/test/sdk_asset_generator_test.dart b/test_common/test/sdk_asset_generator_test.dart
similarity index 96%
rename from dwds/test/sdk_asset_generator_test.dart
rename to test_common/test/sdk_asset_generator_test.dart
index 833f9a4..5a7cad7 100644
--- a/dwds/test/sdk_asset_generator_test.dart
+++ b/test_common/test/sdk_asset_generator_test.dart
@@ -9,10 +9,9 @@
 
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
-
-import 'fixtures/logging.dart';
-import 'fixtures/sdk_asset_generator.dart';
-import 'fixtures/test_sdk_layout.dart';
+import 'package:test_common/logging.dart';
+import 'package:test_common/sdk_asset_generator.dart';
+import 'package:test_common/test_sdk_layout.dart';
 
 void main() {
   group('SDK asset generator', () {
diff --git a/tool/ci.sh b/tool/ci.sh
index 9c13f0f..7838823 100755
--- a/tool/ci.sh
+++ b/tool/ci.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Created with package:mono_repo v6.5.0
+# Created with package:mono_repo v6.4.3
 
 # Support built in commands on windows out of the box.
 # When it is a flutter repo (check the pubspec.yaml for "sdk: flutter")
@@ -108,6 +108,10 @@
         dart test -j 1 || EXIT_CODE=$?
         ;;
       test_6)
+        echo 'dart test'
+        dart test || EXIT_CODE=$?
+        ;;
+      test_7)
         echo 'dart test test/build/ensure_build_test.dart'
         dart test test/build/ensure_build_test.dart || EXIT_CODE=$?
         ;;