# Ash Test Base テストフレームワークを考えるために情報収集。 ## 概要 [AshTestBase](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=88;drc=c00c8c446476d8e93acd49ba100468221de3b163)は`/ash`にあるテスト群のベースクラスで、[ash::Shell](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=304;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)を用意するがbrowser processなしで走る。 TaskEnvironmentTraitsを好きに指定する、あるいはTaskEnvironmentそのものを指定できる。 TaskEnvironmentTraitsとは例えば[MOCK_TIME](https://source.chromium.org/chromium/chromium/src/+/main:base/test/task_environment.h;l=121;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)や、[MainThreadTypeをUIスレッドにする](https://source.chromium.org/chromium/chromium/src/+/main:base/test/task_environment.h;l=134;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)など。 testing::Testのoverrideメソッドとして[SetUp](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=109;drc=c00c8c446476d8e93acd49ba100468221de3b163)があるが、それとは別に[TestShellDelegateを指定できるSetUp](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=110;drc=c00c8c446476d8e93acd49ba100468221de3b163)が定義されている。 [TestShellDelegate](https://source.chromium.org/chromium/chromium/src/+/main:ash/test_shell_delegate.h;l=23;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)はテスト用の[ShellDelegate](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell_delegate.h;l=56;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)インターフェースの実装で、例えば[GetBrowserWebUITabStripHeight](https://source.chromium.org/chromium/chromium/src/+/main:ash/test_shell_delegate.cc;l=125;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)のような関数のFakeを用意している。 ### ash::Shellとは? [ash::Shell](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=304;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)はAshに存在するシングルトンで、RootWindowのインターフェースを実装したグローバルにアクセス可能なAPI群。 [様々なsingleton](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=978-1267;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)を一括管理しており、controller系のものにだいたいアクセスできる。 例えば[DisplayManager](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=1172;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)、[FocusController](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=1148;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)、[AshDBusServices](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=1012;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)、[InputDeviceTracker](https://source.chromium.org/chromium/chromium/src/+/main:ash/shell.h;l=988;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)。 一意に定まりそうなやつはだいたいここ。 このセットアップは結構大変。 ## AshTestBase の API Ash用のセットアップをしてくれるだけでなく、テスト用のAPIを用意してくれている。 [CreateTestWidget](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=140;drc=c00c8c446476d8e93acd49ba100468221de3b163)はwidgetを作ってshowする。 ここでは`bounds`と`show`するかと`container_id`を指定できる。 また偽Widgetをinjectできるように[WidgetDelegate](https://source.chromium.org/chromium/chromium/src/+/main:ui/views/widget/widget_delegate.h;l=35;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)も指定できるようになっている。 作ったWindowはPrimaryRootWindowのdirect childとしてattachされる。 実際にWidgetを作ってくれるのは[TestWidgetBuilder](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.h;l=24;drc=06cdbd2560e60577f26a75b4f80a67d43471f2fd)さん。次のセクションでみる。 似たAPIとして[CreateFramelessTestWidget](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=147;drc=c00c8c446476d8e93acd49ba100468221de3b163)、[CreateAppWindow](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=158;drc=c00c8c446476d8e93acd49ba100468221de3b163)、[CreateToplevelTestWindow](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=177;drc=c00c8c446476d8e93acd49ba100468221de3b163)などがあるが、どれもちょっとずつプロパティの違ったWindow creator。 他には[PressAndReleaseKey](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=223;drc=c00c8c446476d8e93acd49ba100468221de3b163)という`key_code`を指定してタイプイベントを送るAPIもある。これはEventGeneratorにパスするだけ。 似たものに[Left/RightClickOn](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=227-231;drc=c00c8c446476d8e93acd49ba100468221de3b163)という、指定した`view`の上にクリックイベントを飛ばすものがある。これは、viewの真ん中に当たるポイントまでまず[MoveMouseTo](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.cc;l=557;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)してからClickするという優れもの。 [GestureTapOn](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.cc;l=568;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)も同じやつのTouchイベント版。 キーボードは、[SetVirtualKeyboardEnabled](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=369;drc=c00c8c446476d8e93acd49ba100468221de3b163)でバーチャルも対応している。 virtual keyboardはShellに存在する[KeyboardController](https://source.chromium.org/chromium/chromium/src/+/main:ash/public/cpp/keyboard/keyboard_controller.h;l=33;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)によって管理されており、そこのflagをset/unsetするだけでvirtual keyboardのサポートを切り替えられる。 [Enter/ExitOverview](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=237-241;drc=c00c8c446476d8e93acd49ba100468221de3b163)はoverview modeを出入りする。 UI以外にも、[Session ManagerやLogin系のAPIたち](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=316-365;drc=c00c8c446476d8e93acd49ba100468221de3b163)が用意されている。 ちなみにこのSession系がない[NoSessionAshTestBase](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/ash_test_base.h;l=422;drc=c00c8c446476d8e93acd49ba100468221de3b163)も用意されている。 ## TestWidgetBuilder [TestWidgetBuilder](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.h;l=24;drc=06cdbd2560e60577f26a75b4f80a67d43471f2fd)は指定された[Widget::InitParams](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.h;l=91;drc=06cdbd2560e60577f26a75b4f80a67d43471f2fd)を元にWidgetを作ってくれるテスト用のビルダー。 2つの作り方がある。 [BuildOwnedByNativeWidget](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.h;l=79;drc=06cdbd2560e60577f26a75b4f80a67d43471f2fd)はnative window (Ashではaura::Window)によって管理されるraw pointer。 [BuildOwnsNativeWidget](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.h;l=88;drc=06cdbd2560e60577f26a75b4f80a67d43471f2fd)は逆にownershipも持てるwidgetでaura::Windowをownする。返り値はWidgetのunique ptr。 実際の挙動と同じなのは前者だが、後者もテスト側で管理したい際には良い。 TestWidgetBuilderには[SetBounds](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.cc;l=65;drc=7ea982dd12065683edd7eb7fccb482928b0e0296)などの各種セッターがあり、init_paramsを指定できる。 これで出来上がったinit_paramsを元にwidgetを[Init](https://source.chromium.org/chromium/chromium/src/+/main:ui/views/widget/widget.cc;l=382;drc=7c06a7a69d82892b8cd7446ed04e200dfed9eeae)し、必要なら[Show](https://source.chromium.org/chromium/chromium/src/+/main:ash/test/test_widget_builder.cc;l=135-136;drc=7ea982dd12065683edd7eb7fccb482928b0e0296)もする。 ## Note このTestWidgetBuilderがWidget作るパートとして独立しているので、ここに他ルールのWidget builderをinjectすると、他のタイプのwidgetに対してテストできそう? Input eventなどは基本Ashのものがそのままクライアントでも使えるので良さそう。 ただ、LeftClickOnのような`view`を指定するAPIは、Exoで`view`がないため場所指定にしてあげないとまずそう。