オイオイオイ書くわアイツ

ほうクソブログですか……たいしたものですね

Cursor、やってみよう

じゃあ何すか、人間くんの書いたコードは無駄だったってことすか

Cursor とは何か

コーディングエージェントを搭載した VS Code 派生のテキストエディタや。
コーディングエージェントに全ベットしよう!という言説がある中、Cursor は生成 AI + テキストエディタなツールとして始めやすく嬉しいね、と言われている。

CLINEに全部賭けろ

ASCII.jp:いま文章を書くのに「CURSOR」を使わないのは損だ

Cursor を実際に使って試そう。

その 1. 明らかに簡単なもの、poor-zundamonizer

最終的に俺がみたい画面

まず、明らかに簡単なものを Cursor と一緒に作り、試す。
最近の俺のわがままとして、「Deep Research の調査結果、なんかいっぱい文字あってしんどい」というのがある。
俺もうダメなんすよ。

近年一番脳に優しい情報提示形式はずんだもん動画っす。
なんで、

  1. 文字まみれの調査結果を何らかの形式に変換させる
  2. 変換結果をずんだもん動画風に閲覧する

ということをしたい。俺はもうダメなので。

ずんだもん動画というのを乱暴に抽象化すると、後ろにプレゼンスライドがあり、前でずんだもんたちが喋っている。
したがって、スライドの内容 + そのスライドの前で喋らせる脚本 をひとまとめにする DSL 的なものがあると良い。

まず、単純にスライドを作成するためのツールを用意したい。
これはすでに世の中にたくさん存在しており、大変良い世の中や。
今回は、他と比べて比較的セットアップが簡単で扱いやすい Marp を利用する。

Marp: Markdown Presentation Ecosystem

Marp は Markdown でスライドを作成できるツールである。
Marp にはスライド内の HTML コメントを presenter note として扱ってくれる機能がある。
こいつをずんだもん用の脚本に利用する。
要するに、以下のようにスライド内に脚本を埋め込みたい:

# Slide 1

- hoge
- fuga

<!-- ずんだもん(neutral): こんにちは、ずんだもんです -->
<!-- 春日部つむぎ(happy): 私は春日部つむぎです -->

---

# Slide 2

- 宿命
- 支配
- そして欺瞞

<!-- ずんだもん(neutral): 鋼の魂奪者なのだ -->
<!-- 春日部つむぎ(neutral): 無窮の闇、滅魂の一撃、不滅の鎧、死の呪縛、死の国 -->

で、この Markdown の中の脚本部分を取り出し、以下のようなデータを作る:

const events =  [
    {
        type: "speak",
        character: "zundamon",
        emotino: "neutral",
        text: "こんにちは、ずんだもんです"
    },
    {
        type: "speak",
        character: "tsumugi",
        emotion: "happy",
        text: "私は春日部つむぎです"
    },
    /**
     * ページ内のコメントを読み上げ終わったら次のページへ移動したい
     */
    {
        type: "nextSlide"
    },
    ...
]

で、このデータを元に音声を作成したりしつつ画像をええ感じにしたりしつつ、スライドショーを再生するための HTML を作る、ということにする。

このようなツールを作るぞということで、まず README を作成した。
して、この README を元に実際に Cursor にやってもらったのは以下:

  • 出力ディレクトリに既存のファイル(俺が前もって用意したずんだもんの画像とか、css とか)をコピーするスクリプトを書く
  • local の VoiceVox サーバーへのリクエストを司るクラスを作ってもらう
  • 最後にコメントを書いてもらう

これらは結構うまく行った。
できたものはこれ:

https://azoson.github.io/poor-zundamonizer/demo-test/zundamonized.html

実際の AI Assistant との会話は ここ に残してある。
基本的には、

  • 実装内容が明確であり、インターフェイスも指定されている
  • そもそも各コンポーネントが小さい
  • しかたなく密結合になる部分は責任者(今回は天然高知能である俺)によって "ちゃんと" 管理されている

というのが効いたんかしらと思う。
しかたなく密結合になる 部分は生成された HTML だったりそこで読み込む pure js だったりする。
ここら辺は天然高知能の私がテキトーに作った。

天然高知能と人工知能の夢の共演で良かったです。
ところで、こんなんは AI 時代のソフトウェア開発 とかそんな話ではなく 、普通にソフトウェア開発する上で気をつけるべきことです。
人間クンたちわかっとるか??

その2. 複数の機能と抽象化、zondamonizer-ai-assistant

上のスライドショー生成くんはやることが明確に決まっており、機能を統合するダルい部分は俺の高知能でなんとかした。
結果、AI と気持ちよく会話できた。
やることがちょっと増えて、俺がサボるとどうなるか。

zudamonizer-ai-assistant では、

  1. Markdown 形式の文章を Marp のスライドにする
  2. Marp のスライドにずんだもん動画風のナレーションを埋め込む

というのを生成 AI 様にやってもらう。
それぞれについて、最初に作ったものを AI に評価させる -> AI による評価を踏まえて AI に改善させる というフィードバックループも実現したい。
したがって、

ということになる。
俺の欲しいもの、わかるよね?
AI くんは俺を気持ちよくできるのか。

Markdown 形式の文章をスライドにするくん

俺が実験がてら作成した以下のファイルを元に、「とりあえず頼む」でお願いしてみる:

  • evaluation.ts : スライドの評価・フィードバックを AI にお願いするくん
  • improve.ts : evaluation.ts で出力されたフィードバックを元にスライドの改善を AI にお願いするくん

お願いしたやりとりはこれ。
AI Assistant くんは元のファイルを参考に、

  • generate.ts : Markdown 形式の文章をスライドにする
  • cli.ts : 上の evaluation.ts / improve.ts / generate.ts を呼び出す用の CLI

を作ってくれた。 一旦ええやんという感じだが、 cli.ts において

  • export / preview / add-meta などの謎のメソッドを勝手に追加している
  • evaluation.ts / improve.ts / generate.ts を呼び出す際に bun run evaluation.ts を子プロセスとして生もうとしている

などしているのは、 ウザい!!!!
前者については、まあ単純に欲しくないんで、俺は。
既存のファイルを確認し、あるとよさそうなファイルを追加したり、既存のファイルを改善したりしてください としか指示していない俺が悪いっスか。

後者はなぜそんな難しいことをする?という感じだ。
各ファイルを bun run で実行できるようにしつつ、便利 entrypoint としての CLI を用意するのは良いと思う。
子プロセスとして呼び出すのはあんまりわからない。
強いて言えば呼び出し自体を抽象化できるなどの良さがありますか。

子プロセスとして呼び出すように作ると、子プロセスの stdout を親プロセスからも出してあげたくなる。
というのも、AI エージェントくんがデバッグする際に bun cli.ts <COMMAND> 実行して親プロセスの出力を見るので。
が、AI エージェントくんが書き散らした子プロセス利用コードを、人間様が(AI 野郎のために)更に修正するのは楽しくないっス。

結局ここらへんで子プロセスを利用 しない 形への書き直しを要求している。
"このリファクタリングにより、コードの品質と保守性が大幅に向上しました" などとうそぶいているが、ほなら最初からやってくださいよ。

スライドにずんだもんたちの会話を埋め込むくん

続いて、上で作った "スライドにするくん" を元に、「スライドの各ページにずんだもん会話を埋め込むくん」も作ってもらう。 その時の対話はここらへん。
「既存のファイルを参考に同じような感じで作ってくれや」という雑な指示で実際に動きそうなものを出してくれており、偉い!

が、(先の子プロセス利用コード同様)「なぜそんなことをする?」的な部分も気になり出す。
会話埋め込みについて色々なオプションを用意してくれたり、こっちでも preview などの謎メソッドを用意してくれたりなどの、AI 特有の余計な気遣いが変。
なんか知らんが春日部つむぎをお嬢様口調で喋らせようとしてくるのも変。

zundamonizer-ai-assistant/.specstory/history/marp-スライドに解説を追加するツール依頼.md at d20486283cbe3334bf0b6a05108d9ebef6254949 · azoson/zundamonizer-ai-assistant · GitHub

「キャラクター名のカスタマイズ」オプションは用意するものの、実際にキャラクターの振る舞いを指示するテンプレートの管理については人間様が指摘するまで整理しない、などのバランスの悪さも気になる。

zundamonizer-ai-assistant/.specstory/history/marp-スライドに解説を追加するツール依頼.md at d20486283cbe3334bf0b6a05108d9ebef6254949 · azoson/zundamonizer-ai-assistant · GitHub

zundamonizer-ai-assistant/.specstory/history/marp-スライドに解説を追加するツール依頼.md at d20486283cbe3334bf0b6a05108d9ebef6254949 · azoson/zundamonizer-ai-assistant · GitHub

上2つを合わせた全体的な開発体験

ややコード内容に気になる点は増えてきたものの、

  • そもそも両者を一旦動くところまで作り上げるのが速い
  • 全部通しで動かすための( marpify/cli.ts と zundamonizer/cli.ts を両方ええ感じに使う) "一気通貫ワークフロー" を作る、などの雑用も素早くやってくれる

zundamonizer-ai-assistant/.specstory/history/marp-スライドに解説を追加するツール依頼.md at d20486283cbe3334bf0b6a05108d9ebef6254949 · azoson/zundamonizer-ai-assistant · GitHub

  • 一気通貫フローを実際に使うための example を追加するのも良い感じにやってくれた

zundamonizer-ai-assistant/.specstory/history/example-directory-structure-proposal.md at d20486283cbe3334bf0b6a05108d9ebef6254949 · azoson/zundamonizer-ai-assistant · GitHub

ということで、実際に動かすまでラクに進んだのはめちゃくちゃ良いと思った。 特に今回のツールについては、いろいろ動かしてみてプロンプト調整するという段も存在したんで、この利点を感じやすかった。

Q. どうだったかな? A. よかったよ

全体として、俺はめっちゃ良いと感じたっス。
とりあえず動くもん作って自分で試して改善してみる、というソフトウェア開発の初期衝動みたいなもんを思い出せた気がする。
作ったもんは以下:

github.com

github.com

poor-zundamonizer のデモスライドはこれ: https://azoson.github.io/poor-zundamonizer/demo-test/zundamonized.html

ちょっと一瞬ポエムを挟みます。
俺はもう7年だか8年だか働いており、ソフトウェア開発を完全に仕事にしてしまった。
結果、最近はくだんねーもんを作らんくなってしまった。
コードを書くということが金銭に結びつきすぎており、趣味のクソ開発中に「じゃあ何すか、俺くんの書いてる趣味コードは無駄ってことすか」みたいなつまらねー考えに囚われる。
自分の人生をつまらなくしてしまっている。

じゃあ何すか、俺くんの書いてる趣味コードは無駄ってことすか

コーディングエージェントは、とにかくものが動くまでをあり得ん速度でやってくれる。
結果、つまんなオジサン人間の俺は、つまらねー考えに囚われる前に「ギャハハ!おたくクンの作ったもん意味ねーじゃん!もっとこうしなよ!」という WANIMA モードになれる。
冷笑の時代は終わり、「やってみよう」の時代が訪れる。
「やってみよう」とかいうの、もうn年前の曲ではありますが。

やってみよう

ポエム じゃない 方の話としては、「コードを生み出すための自然言語(てか要件定義)」に対する能力が今後いっそう重要になってきそうっスね、ソフトウェア開発において。
まあこれ、「そんなん知ってるワイ!」とか言われそうですけど、実際自分でやってみるとおもろいっスね。

また、とにかく実装が早いんで、「作って動かす」行為を要件ブラッシュアップのためのステップにしやすいのもスゲー良いと思った。
人間の主観マシマシのガバ要件を元にコードを書かせ、実際に作らせてみて、 ダメなもんが出てきたらまた要件定義からやり直す みたいなパワー感のある開発を個人レベルでもできる。
ていうか、やった。
今回の記事作成にあたって実装したツール群は、元はWeb アプリケーション上で

  1. ずんだもん立ち絵素材PSD / スライド用Markdown 読み込み
  2. ずんだもん画像 / スライド画像生成
  3. Canvas 上での画像配置
  4. 音声・動画再生

をやろうとしていたが、AI の認知能力と俺の管理能力を超えて破綻した。
破綻したんで、「今すぐ欲しい最終成果物は何か」の見つめ直しに迫られた。
結果、今すぐずんだもん動画風のもんが欲しいっスと思ったんで、上述の構成にした。

æ•… RICH-zundamonizer

個人の体験を膨らませてチーム開発のことを考えると、コーディングエージェントとの対話ログの管理などは生成 AI 時代のチーム開発における関心事になるかも。
commit message とか PR description とかよりも、エージェントとの対話ログが変更の意図を雄弁に語る気がする。
「このコード、俺が何を言ってしまったせいで発生したんや?」というのを対話ログで確認することが何度もあった。
今回俺は SpecStory という拡張を使って対話ログを残したが、対話ログ管理基盤は(今後コーディングエージェントの利用が一般化するにあたって)いろいろ充実してきそうな感じだ。

docs.specstory.com

全体として、コーディングエージェントは楽しいっス最高っスという感じだし、チーム開発……とかいうやつの未来、についてもちょっとした気持ちを得られたのでよかった。 みんなもやってみよう

弊社の謎のチームを紹介するおじさん「弊社の謎のチームを紹介します」

DevPlatform チームをご存じか

俺はちょいちょい「QA やって泣いてます」「絶ッ叫ゥしながらテストコード書いてます」みたいなつまんね~嘘をついているが、弊社には QA チームというのはない。*1
2025 年現在、公式な組織体制上、俺は DevPlatform チーム に属している。
なんで、本記事では DevPlatform チームについて、俺から見てどんな感じか を話します。
あわよくば「へぇ~こういうことやって金貰いたいンゴねぇ」みたいな人が HERP に参画してくれないかと思っています。

DevPlatform チームとは何か

この DevPlatform とかいうのは社内用語らしい。意味はそのまんま「開発基盤」。
デカい意味での開発基盤整備を通じてエンジニアが価値発揮しやすい状況にしましょ〜よ、という目標を掲げているチームである。
要するにエンジニアアゲていけチームや。
かっこいい言葉で言うと、

「エンジニアの生産性とイノベーションを最大化させる」 ことを使命とした部隊です。

これは ChatGPT に考えてもらいました。

具体的な業務例

「デカい意味での」とか「アゲていけ」とかなんやねん、と皆さん気になっていますね。
基本的にはソフトウェアって機能を開発して顧客に提供して(ていうか買ってもらって)初めて "価値" になる*2。
なんで、スムーズな開発・提供という観点から以下のような業務を DevPlatform チームで担当している:

  • 開発環境の設計・運用IDE・コンテナ・仮想環境など開発に必要なツールや環境の整備*3
  • CI/CD パイプラインの構築・運用GitHub Actions ã‚„ Argo CD 自動テスト・自動デプロイの仕組みづくり
  • インフラ構築・サーバー運用AWS・GCP などのクラウド基盤の設計、Kubernetes などのオーケストレーションツールの導入・管理

また、提供した価値を損ねずに提供し続けるという観点から、以下もやっている:

  • DevOps / SRE 文化の推進開発と運用の連携をスムーズにし、サービスの可用性を高める活動をリード
  • ナレッジ共有とガバナンス強化社内向けドキュメントやガイドラインの整備、セキュリティやコンプライアンスのルールづくり

具体的な成果

じゃあ具体的にどんな成果を最近出してるんか、というのも、皆さん気になっていますね。
ここ半年くらいの目立った成果をざっくり紹介するっス。

Kubernetes components のバージョン更新

ここ半年っつーか、ずっとやっている。
上の業務例の インフラ構築・サーバー運用 に該当する。
弊社ではサービスを提供するにあたって Kubernetes を使っており、この中で使っている諸々の部品を適宜最新版に差し替えていく必要がある。
なんとならば古いものを使っているというのはそれだけでセキュリティやらなんやらのリスクを増大させるので。
すでに稼働しているものの部品のアップデートというのは意外に大変なんで、DevPlatform がチームとして音頭を取れるように頑張っています。

インフラコストの調整

最近チーム内で盛り上がったもんとして、AWS reserved instance 購入周りの諸コストおよび要求性能の調査というのがあった。
社としてインフラにどういうもんを必要としており、そこにどれくらいの費用を投じるつもりなんか、という話が(やはり営利企業なんで)大事になる。
なんで、DevPlatform チームが現状のインフラ利用について調査した後、妥当そうな安全マージンも加味してインフラの費用を調整した。
良い意味で調整した、つまり安くなった。
インフラ構築・サーバー運用 とか DevOps / SRE 文化の推進 とかに関係しつつ、具体的な費用という面で成果が出たんで、結構おもろい成果やったと思います。

その他

セキュリティに関する第三者認証を取るための諸対応とか、デプロイ前の QA とかもやっていた。
開発を上手いことやるために最近も頑張っています、という感じデス。

チームの強みとやりがい

業務内容だけ羅列して「ジョイナス!💪😁」つーのも変なんで、チーム自体の良さの話をする。
本質的な良さと、期間限定の良さがある。

本質的な良さ

本質的な良さというのは、「こういう業務をしているのでこういう良さがあります」という話ッス。 本質的な良さは以下の 2 つ:

  • 幅広い領域に挑戦できる インフラ・CI/CD・セキュリティなど、ソフトウェア開発の基盤を総合的に支えるポジションなんで。
    新しめな技術にチャレンジできるし、幅広い領域で経験値を積みやすい。
  • 社内外へのインパクトが大きい 「ソフトウェア開発の基盤」は、社内のあらゆるプロダクトに関わるんで。
    開発の生産性向上は最終的にユーザーの満足度や事業の成長に繋がるわけで、自分のやることの意義を迷わずに済むというのは結構良いと思う。

期間限定の良さ

今んところ、自由度が高い。
今んところ というのは、ぶっちゃけ現状人が足りてない おかげで 何でもチャレンジさせてもらえる、みたいな状況だと思うんで。
俺が結構好き勝手に自動テスト周りの技術選定をできたり、あとそんな詳しくないインフラ周りの業務もやらせてもらえたりする。
猫*4の手も借りたい状況なんで。

俺はどうなのか

俺は DevPlatform チームというのができる前から QA の自動化に取り組んでいた。
ことの発端としては、バカ複雑な要件の機能を俺が実装したことにある。
機能は(当初は)まあなんかちゃんと動いて良い感じだったんですが、要件が複雑すぎるんでデプロイ前のリグレッションテストが大変すぎになった。
なんで「俺が自動化しますッ」と絶ッ叫して切ッ腹し、repo 縛霊となって QA 自動化を頑張っていた。
で、野良の自動テスト執筆ポケモンが暴れているという噂を聞きつけた DevPlatform チーム(当時 "SRE チーム" という名前だったかも)に捕獲された。

捕獲された感想としては、まあ捕獲されてよかったっス。
社内の技術基盤や開発フロー、コンプライアンス意識などを把握できておくと QA 実施・改善の上でも役立つんで。
また、""善く"" 開発するみたいなところの思想について真剣30代しゃべり場発生するのも良い。

チーム(と俺)の今後の展望

今後ますます組織と事業が拡大するにあたって、社内の統制をビシッとしていく必要がある。
で、これを「うーんでも顧客にサクッと機能お試し提供したいっス😄」みたいな話と両立させる必要がある。
統制と機動力の両立はいつでもチャレンジングであり有意義なんで、より一層頑張っていきたい。
特に俺はいまだに切腹執行中QA進行中なんで、 QA 自動化の完遂を持って統制機動2色デッキの実現に貢献していきたい。

この記事で紹介した俺のトレーナー職については以下が公式の求人です:

herp.careers

許さない

は???「SRE_Development」って何??
俺たちは """DevPlatform""" やないんか??
大人を舐めるなよ。求人修正しときます。
俺の方からもよく言って聞かせますんで、ぜひみなさんよろしくお願いします。

*1:QA 関係者でおしゃべりする会合を俺が勝手に開いてはいる。公式な組織体制としては存在しない。

*2:かなしいね

*3:これ、Q課という謎の組織(??)がやっている部分もあるが、簡単のため DevPlatform の業務とする

*4:俺は犬派

AI にブラウザを操作させるの、楽しすぎ!!😄😄😄

はじめに

人工知能に仕事を任せる人のイラスト

「人工知能に仕事を任せる人のイラスト」とかいうドンピシャの画像あってウケました。

人工知能に仕事を任せる人のイラスト | かわいいフリー素材集 いらすとや

AI 様とブラウザ

AI 様がパソコンを操作できると色々自動化できそうッスねという話がある。AGI とかいうカッケー呼び方もされている。
「パソコンを操作」とまでは行かずとも、個別のアプリケーションに対する操作を許されるだけも便利そう。特にブラウザ。
ブラウザ操作できればブラウザの上で動く Web アプリケーションも操作できる。強そうじゃないですか。
で、昨今 AI 様はブラウザを操作できるようになってきている。

browser-use が流行った

AI 様のブラウザ操作として最近(2024年後半くらい)browser-use が話題になった。
こいつは Playwright を基にして AI 様にブラウザ操作能力を与えている。「よしなに」力の高いプロンプトも詰まっている。
Playwright がバカ使いやすい影響もあってか、browser-use も結構イケるらしい。

github.com

browser-use を試す俺の動機

俺は業務で Web アプリケーションを作ったり Playwright を使ったりしている。
趣味で AI 様に LoL の負け試合の責任者を画像判定していただりもしている。
なんで、browser-use のお試しを通して AI 様と Web アプリケーションの関係性に想いを馳せると楽しそう。
そういう謎の自由研究を業務時間でやって良いと俺は思っており、業務時間が楽しいと得なんで、やる。

前提

そもそも browser-use はどのように使うんか

browser-use の利用はメチャ簡単。
Python 環境を用意して、下のようなコードを書くとサクッと動く。

from langchain_aws import ChatBedrock
from browser_use import Agent, Browser
from browser_use.browser.context import BrowserContextConfig
import asyncio


# ここら辺はよしなにやる
llm = ChatBedrock(
    model_id="anthropic.claude-3-sonnet-20240229-v1:0",
    model_kwargs=dict(temperature=0),
    region_name="us-east-1",
)

URL = ""

async def main():
    browser = Browser()
    async with await browser.new_context(
        config=BrowserContextConfig(
            cookies_file="", # 配列形式の JSON ファイルでテスト環境にアクセスするための権限情報を渡している
            browser_window_size={"width": 1920, "height": 1920},
            trace_path="./traces",
        )
    ) as context:
        agent = Agent(
            task = f"""""", # ここで AI 様にお願い申し上げる
            llm=llm,
            browser_context=context,
            use_vision=True,
            save_conversation_path="logs/conversation.json"
        )
        result = await agent.run()
    await browser.close()
    print(result)

asyncio.run(main())

browser-use が使うブラウザに対して認証情報を渡す部分( cookies_file のところ )は browser-use の example に詳しい。
task の中身によって動作が変わるよ、というのが本題。
なんで、以降は基本的に task の中身について言及していく。(つまり、わざわざコード全文を貼りたくない。)

Web アプリケーションの動作確認(俺の普段の業務)を実際に AI 様にお願いしてみる

弊社様のアプリケーションの機能紹介

俺は普段弊社様のアプリケーションをたくさん触る仕事をしている。
browser-use でこの仕事を自動化できないもんかと試したい。
が、弊社様のアプリケーションなんか人々は知らんと思う。「Google 検索を自動化してみましょう😄」とは全然話が違う。
なんで、代表的なアプリケーションである HERP Hire から、使用方法のわかりやすい以下の 2 つの機能を紹介しておく:

  • タイムライン機能
  • 評価依頼機能

採用業務、と聞くと「なんか面接とかしてその結果についてワヤワヤ社内でおしゃべりして是非を決める」みたいなやつが思い浮かぶ。
ざっくりいうと、タイムライン機能は ワヤワヤ社内でおしゃべりする ために、評価依頼機能は 是非を決める ために使う。

タイムライン機能

HERP Hire ではワヤワヤおしゃべりを各応募ごとにまとめられるようになっている。
A さんに関するおしゃべりは B さんの画面では出てこない。
下の画像では vu7or-1 という名前のテスト用の応募者を(テスト環境に)作り*1、その画面をスクショした。
ほんで、ここに「コメント入力」して「送信」すると、文章が永続化され、この画面を閲覧できる人々に内容が共有される。
送信したタイミングでメールなりなんなりで各ユーザーに通知が飛ぶなどの便利もある。
てかまあ Slack のチャンネルみたいなやつが応募者ごとに建てられるということです。

タイムライン機能を用いて応募者への所感を永続化する様子

評価依頼機能

ワヤワヤおしゃべりの後に構造化された方法で応募者に評価を下し、採用・非採用など決めます、というのが一般的な採用の流れっス。
全員が同じ形式で評価を出してくれる方が

  • 採用側は業務を進めやすい
  • 応募者側も公平な評価を受けやすい*2

などの良さがある。
そのような良さを醸すための機能が評価依頼機能や。

下の画像の様に、評価の形式を前もって定めておき(左)、その形式に則って評価を入力し(真ん中)、評価を共有できる(右)。
便利っすね。

評価依頼機能の簡単な利用例

動作確認(の自動化)のつらみ

で、俺は普段「開発中のアプリケーションの新バージョンにおいて "基本的な機能が壊れていないこと" を確かめてください!」などと言われている。
"基本的な機能" とは上の 2 つのような「大多数のユーザーの採用業務に必要な機能」のことで、上の 2 つ以外にもたくさんある。
原始的に "基本的な機能が壊れていないこと" を確かめ るには、ブラウザをポチポチしてアプリケーションを動かしてみると良い。
俺は毎日泣きながらブラウザをポチポチしている。これは嘘で、ブラウザのポチポチを Playwright で自動化する活動をしている。

例えば「HERP Hire の応募詳細画面でタイムライン機能が ちゃんと 動いていることを確かめる」という要求に関する自動化とはどんなもんか。
「HERP Hire の応募詳細画面でタイムライン機能が ちゃんと 動いている」を以下のように(自分用に)言い直す:

- HERP Hire が利用可能である
  - HERP Hire を操作して `自然な動線` で "応募詳細画面" に遷移できる
    - `自然な動線` というのは、HERP Hire のトップページである "応募一覧画面" からの遷移を指す
  - 応募詳細画面で「タイムライン」タブを開ける
    - 「コメントを入力」の placeholder が設定されている input 要素にテキストを入力し "送信ボタン" をクリックすると、テキストを永続化できる
     - 永続化されたコメントは応募詳細画面の「タイムライン」タブに表示される
     - コメントを永続化する際にユーザの設定に応じて"メール通知が行われる"
        - "メール通知が行われる" とは「メール取得に関する認証情報(これは HERP Hire を操作する認証情報とは別)を使ってメールを polling すると少なくとも n 分以内に hoge なる条件を満たすメールが確認できる」ことを指す
     - blurblurblur

このような言い直しの作業は相当キツい。
AI 様のご威光により、人間の愚かな言葉がそのままブラウザの操作になってくれると嬉しい。

雑なタスクで AI 様にお願いする

一旦、メール通知を省いて小さく試してみる。
以下のタスク文で AI 様にお願いしてみよう。

            task = f"""
            {URL} を開く。
            応募者の詳細ページに移動し、タイムライン機能を使用してコメントを投稿する。
            """,

結果としては、以下のような 3 ステップを実行し、見事 失敗 なさる。

人間くん用の指示でお願いした場合の各 step ごとのスクリーンショット

失敗の原因

失敗の原因は左端の画像(番号は2)の Find and click on the candidate ... における "間違った" 場所のクリックにある。
AI 様は紫枠 28 の要素(下に抜粋)をクリックすれば 応募の詳細ページに移動できそうと判断なさった。

AI 様が見事見抜いた詳細ページへの動線

しかし、ここには卑劣な人間の罠が隠されている。
名前枠の中でも特に職種名の部分をクリックすると、「一覧画面のフィルター条件の簡易入力」が行われるのだ。
つまり、AI 様が堂々と紫枠 28 内中心の CSVImport テスト用職種 zi689 の部分をクリックしたところ、requisition: "CSVImport テスト用職種 zi689" が検索条件として入力されてしまった。

AI 様が人間の卑劣な罠に嵌められるシーン

AI 様は完全に錯乱なさり、タイムライン機能らしく見える メモ とやらにありがたいお言葉を書き留めた。
その後、プロセスは身罷られた。

錯乱遊ばされる AI 様のお姿

タスクの改善

このままではイカンので、AI 様に人間くんの秘密のテクを具申する。
詳細ページに移動するには、応募者のアイコン(設定されていない場合は名前の頭文字が出る)をクリックしても良い。
以下が更新版のタスク。

            task = f"""
            {URL} を開く。
            応募者のアイコンをクリックして詳細ページに移動し、タイムライン機能を使用してコメントを投稿する。
            """,

結果、AI 様は見事応募詳細画面を開き、コメントを投稿なさった。

あっぱれ AI 様、見事コメントを投稿なさりました

メールも見てもらう

続いて、最も言い直しの作業がキツい "メール通知が行われる" の部分をやってもらう。 タスク文として最終的に以下を使い、見事 Gmail を通じてメールを確認なさった。
スクリーンショットは省く。

            task = f"""
            {URL} を開く。
            応募者のアイコンをクリックして詳細ページに移動し、タイムライン機能を使用して 'Browser-use による自動コメント:({comment_string})' とコメントを投稿する。
            コメントの投稿に成功した後、 https://mail.google.com/mail/u/0 を開く。
            「メールを検索」(あるいは「スレッドを検索」)の要素にフォーカスし、'{comment_string}'でメールを検索する。
            「タイムラインにコメントが投稿されました」というタイトルのメールを開く。
            """,

browser-use を動作確認に使いたいか?

今の所いいえ。
理由としては、

  • 期待よりも AI による操作が正確でない /タスク文作成が簡単じゃない
  • AI エージェントによる推測に時間がかかる

あたり。

前者について、要はアイコンをクリックして だの 「メールを検索」(あるいは「スレッドを検索」)の要素にフォーカスし だの言いたくない。
これ言わされるなら Playwright 使ってプログラミング言語喋るのと大差ないなと感じてしまう。
ちなみに 「メールを検索」(あるいは「スレッドを検索」)の要素にフォーカスし を言わずに メールを検索する だけいうと、突然 Google 検索を利用し始め、ゲンナリした。

後者については、まあ普通に遅いのが嫌や。
動作確認はとっとと終わって欲しいもんなんで、単純に早い方が良い。
また、操作全体に時間がかかる せい で、 メールを polling すると少なくとも n 分以内に の部分の非機能要件をタスクに組み込みにくい。
メールが届くよりも早く Gmail を開けないんで、操作速度のせいでコメント送信とメール通知(正確にはユーザーによるメールの受信)が同期的な処理に見える。

細かな嫌ポイントとしては、Playwright の trace viewer で病人の操作ログを見るハメになる、というのもある。

browser-use は QA においてまるっきり役立たずか?

これもまたいいえ。言い過ぎ。
動作確認は事前に決められた動作を正確に(できれば高速に)繰り返すものだ。
「事前に決める」で手を抜きたいという俺の目論見はあまり上手く行かなそうだった。

動作確認から QA 全体に視野を広げると、「機能説明がユーザーの一般的な感性に噛み合っているか」をチェックする際に活躍してくれそうと感じた。 要は、上述の人間の卑劣な罠で困るのって AI 様だけではなくないですか。
ユーザーを困らせる前に罠を検査する、というのは有意義かもしれん。

ていうか HERP Hire の操作を browser-use にお願いする

HERP Hire の現状に関する気になり

ところで、AI による操作の正確さ / タスク文作成の簡単さ への期待は動作確認に限った問題ではなくないですか?
ユーザーが browser-use を用いて HERP Hire の利用を効率化したくなったときのことを考えたい。
HERP Hire はユーザーの望む効率化を施せる状況にあるんか?
より大きな話としては、HERP Hire は今後の AI 時代についていけるのか?

(俺が勝手に思う)ユーザーが AI を使ってやりそうなこと

例えば、「面接中のメモの文章を所定の評価形式に変換する際に生成 AI の力を借りたい」というのはありそうな話だと思う。 評価の一貫性を AI 様に多少なりとも担保してもらえると嬉しそう*3。

AI 様にお願いしてみる

このとき、以下のようなタスク文を考える。

            task = f"""
            https://testduxct.v1.haro.careers/ats/p/candidacies を開く。
            ksidu-0 という応募者のアイコンをクリックして、その詳細ページに移動する。
            評価タブを開く。
            評価を記入するをクリックし、評価記入フォームに遷移する。
            以下の私の面接時のメモを元に、評価を記入して投稿してください:
            ```
            これまでのキャリアにおいて、急成長する企業に所属していた期間が長く、チームや事業の構造変化への対応力や当事者意識が強そうだった。
            弊社においても、現在まさに事業の構造変化が起きており、個々人の自律的な活動を求めていることから、文化的側面によくマッチしていると思う。
            技術的な能力については、バックエンド開発の経験しかないものの、当人はフロントエンド開発から SRE まで幅広い興味があると言っていた。
            ```
            """,

また、「評価記入フォーム」として以下のようなページが提供されているとする。

AI 様に使っていただく評価記入フォーム(のプレビュー)

上述タスク文を元に AI 様にお願いすると、評価記入フォームを確認して

I rated the 'Cultural Fit' as 5 (highest) and 'Technical Ability' as 4 based on the provided notes about the candidate's experience at fast-growing companies, ability to adapt to change, technical interests beyond just backend development, and overall cultural fit for the company's current transition phase. Please let me know if you need any other details submitted."

という判断を下す。
文化的側面との相性は 5 で技術パワーは 4 ですね、と言っている。
そして、見事 文化的側面 5 / 技術パワー 5 と記入して投稿なさる。

実際に投稿された評価

思ったこと

結果としては上手くいかなった。 が、 やっていて楽しかった。
まず、「ある文章を所定の形式に変換してもらう」という部分は生成 AI の味が出る行為な気がする。
なんで、この変換を評価業務に組み込んでみること自体にオモシロを感じた。

また、業務における効率化のアイディアを簡単に実装して試せるというのも自己効力感を得られて良い。
ブラウザ操作の自動化ということなんで、普段の業務中にブラウザ見てアイディアを思いつきやすそう。

おわりに

なんだかんだで楽しかった

普段の業務で使うアプリケーションについて、思いついた効率化や AI との協働を簡単に試せるのは楽しい。
browser-use をちょっとお試しした感じ、今後は誰もが自分の業務を自由に 楽しく 自動化する世界になるだろうなと思った。
既存の方法と比べると、自然言語でブラウザを動かすやり口は、多くの人に取って取っ付きやすく楽しいと思う。

弊社のアプリケーション、楽しくなれ

ところで、人間のマル秘テクを伝授する必要があったり、最終的に操作が上手く行かなかったりすると、マジで楽しくない。
今後 AI によるブラウザ操作ひいてはアプリケーションの操作が一般化するにつれて、「AI に操作させた時に気分良い」というのはユーザー体験として重要になりそう。
なんで、弊社のアプリケーションにおいてもそこらへん見据えて置けると良いのかもしれん。
ちなみにこの記事で紹介した人間の罠については、すでに UI 改善が進んでいる。
さすがは人間様や。

さらなる楽しみ

あとは個人的なお気持ちやが、やっぱ Python とかいうもんも別に書きたくない。
対話型の UI で指示して「あれやっといてよ」「おかのした」となるともっと楽しそうだ。

Claude のデスクトップアプリは MCP というプロトコルを使ってブラウザを操作してくれる。
なんで、これもちょろっと試してみた。全然操作できなくて泣いちゃった。

Claude に HERP Hire の操作をお願いした

やはり多くのユーザーが喜ぶのは Claude とか ChatGPT とかで良い感じに操作できるという状況だと思う。
そういうところ目指したいっすね。

俺は普段機能要件を dig ったり DOM 構造を dig ったりして気が狂いそうになっています。
しかし、そういう整備が回り回って未来のユーザーの楽しい自由な業務につながりそう、という気持ちが湧いたんで、良かったス。
browser-use、あるいは AI によるブラウザ操作、あざす。

*1:かつては「無敵院最強ノ助」みたいなふざけた名前でやっていたが、こういうおふざけは万が一本番環境に漏れ出すと良くないので、今は許されていない。

*2:一旦ここでは人間を信じている。

*3:ここでは人間を信じていない。

機能の動作確認をする時に知りたい情報・嬉しいフォーマット

機能開発において、開発チームとは別の人員が動作確認を行う場合、動作確認の担当者に「何を確認して欲しいか」を伝えることになる。
で、ここで合意した内容に基づいて継続的に機能の動作確認が行われるんで、なんかそれなりの内容について合意したい。
それなりの内容ってなんやねん、そういう話になる。

大前提として、株式会社 HERP(以下、"弊社" )の開発プロセスにおいて、"動作確認の担当者" は機能開発自体にはあんま関与していない。
機能があらかたテスト環境で動くようになってから「挙動確かめてクレメンス〜〜」と依頼される。
この依頼に際して、確かめて欲しい挙動というのはなんなのですか、という部分に焦点が当たる。

CR 動作確認

欲しがっている情報というのは単純に "受け入れ条件" であり、以上っす。
その "受け入れ条件" とはなんやねんということについては、 インターネットに詳しく書いてある。
インターネットの例を 1 つ挙げる。

www.atlassian.com

インターネットによると

Acceptance criteria are the conditions that a product, user story, or increment of work must satisfy to be complete.
They’re a set of clear, concise, and testable statements that focus on providing positive customer results.
Acceptance criteria don’t focus on how you reach a solution but rather on the final desired outcome of the task.

ということであり、要は機能開発が終わった時に何がどうなっていて欲しいのか、 a set of clear, concise, and testable statements で表現したものっス。
これを作るために以下気をつけると良いですよ、とある:

How to write acceptance criteria

Crafting well-defined acceptance criteria is essential for successful software development. Here are some key steps and tips for guidance:

  • User story: Refer to the user story connected to the acceptance criteria. This ensures that the criteria tie to the desired functionality.
  • Outcomes: Express the user experience and expected outcomes criteria. What should the feature achieve for the user? Avoid getting bogged down in technical implementation details.
  • Clarity and concision: Strive for clear and concise language everyone can understand. Technical jargon or ambiguous phrasing can lead to confusion.
  • Testability: Ensure each criterion translates into a clear and verifiable test. This allows for an objective evaluation of whether the feature meets the requirements.
  • Measurability: Whenever possible, quantify the criteria using measurable terms. This facilitates a clear pass/fail determination during testing.
  • Independence: Aim for independent criteria that you can test in isolation. This streamlines the testing process and avoids dependencies.
  • User acceptance testing (UAT): Consider incorporating UAT criteria alongside the development team's criteria. UAT criteria focus on ensuring the feature meets expectations from a usability standpoint.
  • Collaboration: Encourage collaboration during the creation process. Involve the product owner, development team, and other relevant stakeholders to ensure a comprehensive set of criteria that reflects all perspectives.
  • Review and refinement: Don't be afraid to revisit and refine the acceptance criteria throughout development. As understanding evolves, consider adjusting the criteria to reflect the latest information.

These steps and tips help develop acceptance criteria that promote clear communication, efficient testing, and a successful project outcome.

たとえば「スレッドにコメントを投稿する機能」について、「ユーザーはコメントを投稿できる」 と書くのではなく、

  • スレッドにアクセス権限を持つユーザー A は "コメント投稿画面" を開ける
    • "コメント投稿画面" にはテキストボックスと submit ボタンが表示されている( enabled である )
    • スレッドのアクセス権限は、
      • 管理者 ロールのユーザーは常に有している
      • ゲスト ロールのユーザーは、管理者ロールのユーザーからスレッドに招待されたユーザーに限り有している
        • スレッドへの招待は、管理者ロールのユーザーが "スレッド詳細画面" を開いて hoge して...
    • テキストボックスに n 文字未満の文字列を入力し、submit ボタンをクリックすると "コメントを投稿" できる
      • 投稿完了トーストが表示された後、"スレッド詳細画面" を開き、投稿した文字列が表示されていることを以て投稿の完了を確認できる
    • ...

など書かれていると Clarity / Testability / Measurability あたりの観点から嬉しい。
また、それのみが書かれている文書に整理し直してもらえると consision 的にも HAPPY。

色々な検討経緯も含めて共有されると(動作確認担当者としては)あんまり嬉しくない

動作確認の担当者 から機能開発チームに向けてのお願い事としてはこんなだが、逆の話も当然ある。
動作確認の担当者 (というか俺)も「受け入れ条件クレメンス」をするにあたり、早めに PO に訊きに行く を気を付けた方が良い。
受け入れ条件は機能開発に全体を考慮して決めるべきであり、少なくとも PO は「全体的な考慮」をできるハズなんで。

して、一旦は「機能開発チームは良い感じに受け入れ条件書いてね」「動作確認の担当者は PO に受け入れ条件のことを訊いてね」ということでやり取りが整理されると嬉しい。
が、根本的には、機能開発チーム / 動作確認の担当者 とかいう謎のくくりがない方が良い。
結局のところ

株式会社 HERP(以下、"弊社" )の開発プロセスにおいて、"動作確認の担当者" は機能開発自体にはあんま関与していない

に大体問題がある。
"動作確認の担当者" が最初からチーム内におり、機能検討の議論に参加できていれば全部話がうまくいくんじゃないですか。
しかし "動作確認の担当者" の数が単純に足りていないので、話がうまくいっていない。

前向きな対処としては、引き続きテスト基盤を整備して E2E テストを機能開発チーム書いてもらえるようにする。
E2E テストを(てか Playwright によるテストのコードを)機能開発のアウトプットとして要求できると、"受け入れ条件" を別途考えてまとめてもらうよりも現状の組織体制に即しているんじゃないですか。
また、それはそれとして、現状の組織体制というやつもなんとかしたくはある。
一旦、俺が頑張るなどして、動作確認担当者間でのコミュニケーションを増やしたい。
更に、QA・テスト に興味関心を持つ人間が弊社に増えると嬉しい。
俺は採用活動の一環として業務時間にこの文章を書いています。よろしくお願いします。

キックオフの後の懇親会で出し物をした

はじめに

以前感想を述べた通り、株式会社 HERP(以下、弊社)では毎四半期の初めに激長いミーティングを開催している。
このミーティングは「構成員間の自律的な協働を促進する」ことを目的のひとつとしている。
会社としての方針を共有すればあとは勝手に動いてくれ〜、と弊社は構成員に期待している。
(あるいは、それを上手くやれる人間を厚遇する会社であろうとしている。)

で、このミーティングの後に希望者のみ参加する懇親会を開催することが多い。
陽社(陽キャの会社版)なんで「親睦を深めたら協働しやすいっしょ🫶😁」という発想がある。
懇親会の企画進行は最近は回り持ちになっており、今回は俺含む複数名のソフトウェアエンジニアが企画進行に関与することになった。
せっかくソフトウェアエンジニアが集まるんだからということで、自社製品にバグを埋め込んでバグ探しみたいなレクリエーションを用意した。

「404ページで例の女性が出てくる」「console 画面に取締役の AA が表示される」などのおもしろいバグ(?)を実装した

お伝えしたい弊社の良いところ

一旦、俺のような問題ありそうな人間も組織運営に協力している会社ですということで、わあそういう良いところ(??)もあるんだねというのを飲み込んでください。
また、このレクリエーションについて、準備から実施まで皆さんかなり真面目に取り組んでくれたんで良かった。
これも一旦弊社の良いところとして飲み込んでください。俺は業務としてこの文章を書いているため。
真面目に取り組んでくれたおかげで、弊社の開発・運用体制に関して

  1. 主要サービスの開発環境がポータブルでない
  2. 各機能の名称や挙動が共有・明文化されていない

などの問題が発見できた。

弊社の良いところの図

発見された課題の詳細

ここをクリックして開発環境のポータビリティに関する話を展開する

まず、現状の機能開発において利用するための動作確認環境は用意されているが、その環境を別途再現する方法が整備されていなかった。
普段の業務においては問題になっていないが、今回のレクリエーションの準備においては急遽動作確認環境の増設をしたくなり、この問題に意識が向いた。
この問題は弊社の開発の巨大化・複雑化に伴いより危険な形で顕在化すると思うので、現段階で謎のルートから発見できたのはおもろいと思った。

ここをクリックして機能使用の明文化に関する話を展開する また、そもそも弊社のサービスのこの機能ってなんて呼ぶんでしたっけ・どういう風に動くんでしたっけ という部分の認識が思ったより揃っていなかったのも面白かった。
恐らく、普段の業務においては "よく話題になる機能" についてその時々で知識を更新したり認知を揃えたりして、その時々で良いユーザー支援を提供しているんだと思う。 今回のレクリエーションにおいては、無作為にいろんな機能を触ってその挙動について報告してもらう機会が生じたんで、結果「うまく言及できない機能」の存在が目立った。
弊社のサービスが多角化していく中で、知識の共有・明文化(そしてそれらの網羅性)の重要性が増すと思うので、現段階で謎ルートから発見できてよかった。

おわりに

再度お話をまとめておくと、弊社においては

  1. 構成員各自が組織運営に自主的に参加しましょうよという風土がある
  2. 1 に関連して、構成員が行う自主的な運営に対してそれぞれが協力的である

などの良い点がある。
このおかげで、俺もレクリエーションとかいうやつを真面目に企画・運営したし、また皆さん真面目に協力・参加してくれた。
結果、普段の業務とは別の角度から開発組織上の問題に気が付く機会を得た。
弊社にはこのような良いところがあります。皆さんいかがですか?

ガチおまけ

以下、俺がおふざけプレゼンを作った話。

弊社の良い点の隠しポインツとして、「発表に対して寛容である」というのがある。と俺は勝手に思っている。
要するに、ちょけたスライド・プレゼンを用意してもあんま怒られない。

俺はたまに大ふざけのプレゼンをやってストレスを発散しており、今回もそれをした。
具体的なふざけとしては、バグ探しというのがやや脱出ゲームやミステリのニュアンスを持つなと思ったんで、雨穴のコスプレをして裏声で喋った。
また、純然たる俺の好みでプレゼン全体の主張をメンズコーチジョージに寄せた。
俺はレクリエーションの準備も全て業務時間に計上しているので、雨穴の仮面工作を業務時間中にやれて気分良かったッス。あざす。

プレゼンをしている俺

雨穴の仮面は扉に吊るして魔除けとして使っている。
弊社にはこのような良いところがあります。皆さんいかがですか?

家のドア

株式会社 HERP 2024Q3キックオフ まとめ・感想

この記事の動機

株式会社 HERP(以下、弊社)では毎四半期の頭にキックオフなる長時間の全社会議を行っている。
会計年度が 4 月開始なんで、9 月からは第 3 四半期である。
第 3 四半期頑張りましょうということで、「2024Q3 キックオフ」なるクソ長い全社会議が開催された。
このクソ長い会議において、俺が最近取り組んでいる諸業務に関するストーリーが整理された。
整理されて気持ちよかったんで、キックオフの内容を自分なりにまとめつつ、感想も書く。
今後の会社関連の発信において本稿を参照するかもしれないし、しないかもしれない。
弊社に興味を持っている人が弊社の雰囲気を掴むのに役に立つこともあるかもしれない。

弊社の現在の事業・思想に関する前提共有

弊社は「採用を変え、日本を強く。」をミッションとして掲げている。
企業と人材がうまいことマッチングして日本全体で最強無敵適材適所状態になれば gg ez みたいな話だ。
最高就職5000兆回即日本勝利。さすがです。

極端に単純化した弊社のミッションのイメージ画像

最高就職実現には主に 採用を行う企業 / 求職者 / 紹介会社 が全員最強である必要がある。 なんで、弊社では

  1. 企業が採用を上手いことやるためのアプリケーション
  2. 求職者が自分に合う求人を見つけるためのアプリケーション
  3. 人材紹介会社が求職者に合った求人を見つけるためのアプリケーション

あたりを作っている。
詳細は カルチャーデック という会社紹介ページで述べられている。

culture.herp.co.jp

キックオフ内容まとめ

これらの事業について「来四半期はこんなふうに頑張っていきましょう」と共有をするのが 2024Q3 キックオフの主な目的であった。
金の話でいうと、現状は 1 の企業向けの採用支援に関するアプリケーションが弊社の大黒柱となっているが、そこだけではキツいんで 2・3 もガンガン進めていきましょうということになる。
特に 2・3 は採用マッチングと呼ばれる市場に関わるものであり、この市場は採用支援よりも大きく、うまくやれると BIG MONEY らしい。
金の話を抜きにしても、企業の最高採用・最高広報による求職者へのアピールだけで最高就職を実現するのは難しい。
他の関係者も巻き込んで総合的に最高就職を支援できた方が良いでしょう。
なんで 2・3 頑張っていこうぜという話だった。

採用マッチングの支援について、弊社としては「追加の工数が発生しない形でマッチングの量・質を増大させる」方針を取るらしい。
要は「普段の業務が良い感じになっていれば採用活動の方も良い感じになります」という話だと思う。
個人的には奇を衒わない実直な方針で良いと思った。

極端に単純化した今後の弊社の事業方針

俺個人の業務との関連

実直な方針で以て 2・3 の開発に臨んでいきたいわけだが、1 のみ利用しているユーザー(採用をする企業)からすると「そういうのええから 1 の開発・運用ちゃんとやれや」ということになる。
企業支援に割く労力の社内的な比率は、事業都合により相対的に小さくなっていくわけだが、そこからくる不便や不安をユーザーに与えるのは良くない。
したがって弊社としては 1 の開発・運用を今より低コストでかつ今より信頼できるものにしていき、ユーザに不便や不安を感じさせることなく多角的な事業展開を実現したい、ということになる。
要するに弊社が最強だったらいろんなことやっても誰も不便ないはずで、最強になりましょうよということだ。
なんで、弊社の開発体制を最強にすべく、俺は現在テストの自動化に専念しているわけです。

極端に単純化した開発効率化業務の動機

キックオフへの文句

ここまで述べたように、俺個人の諸々の業務内容について会社のミッションから繋がる形のストーリーが提示されたという点で、個人的には実りのあるクソ長会議だった。
褒めるだけだと会社からの贈賄を疑われるんで、悪かった点も書いておく。

長すぎ

長い。 ほんまに長すぎ。
3 時間近くあり、単純に無理すぎる。
映画だと「アマデウス」とか「ゴッドファーザー」とかを放映できるくらいの時間を取られている。
言うまでもなく映画よりおもしろくない。
当たり前だが、仕事じゃなかったら観ていない。

発表のまとまりがない

事業ごとに発表が分断されており、結果としてストーリーラインがまとまっていない。
ストーリーラインについて、上では「会で俺の仕事のストーリーが提示されてよかったです」みたいなことを言ったが、実のところ別に提示されていない。
いろんな事業において「新規事業やっていきます」とか「既存サービスの保守運用もちゃんとやっていきます」とか言われまくったんで、背景にはこういうストーリーがあるんだろうなと頑張って聴衆が読み取った。
3 時間に渡ってストーリーが整備されていない話を聞かされるのってかなり厳しい体験なんで、なんとかして貰えると嬉しい。

キックオフに関する個人的な反省

ところで、上記のような発表に関する問題が社内で度々起こることを俺は知っていたので、なんかやっておくべきだった。
過去にちょっとやっていた「ストーリーライン整理活動」を継続できていないのが my bad。
次回のキックオフでは資料作り手伝うか、長い映画観まくって耐性をつけて文句言わないようにします。

おわりに

四半期ごとの長い会議にこんなマジで感想と文句書く人間がいるんやねつって弊社に興味を持つ方がいたら嬉しい。
後日、この会議でやった出し物についても共有するつもりです。
今後とも弊社に関する怪文書をよろしくお願いします。

ブラウザテスト始めたて組織における Playwright の便利さ

はじめに

株式会社 HERP(以下、弊社)では、2023 年末あたりからウェブアプリケーションのリリース前デグレチェック(以下、テストと呼ぶ)の自動化に取り組んでいる。 弊社で行っているテスト業務は以下の 2 つに大別される:

  • 探索的なテスト
    大方実装が済んだ新機能を自由に利用してみて、違和感を覚えないか確かめる。
  • 定型的なテスト
    既に提供済みの機能に「問題がないこと」を、定型化された一連の操作によって確かめる。

特に定型的なテストについては以下の特徴がある:

  • 機能総数の増加に応じて業務量も増えるため手動で実施する場合の負担が大きい
  • 操作が定型化されており、自動化しやすい

なんで、自動化するとお得に幸福を得られそう。 本題は「毎回同じようにブラウザを操作してます助けてください」であり、素直な発想としてはブラウザの操作を自動化できるもんが欲しい。 そういうもんとして Puppeteer / Cypress / Selenium.. など色々ある中、弊社では Playwright を使っている。

playwright.dev

(他のツールとの比較検討も簡単にやりつつ)勢いで Playwright の利用を決定した面もあったが、十分機能していると感じる。 Playwright のツールとしての単純な強さに助けられる場面も多い。 なんで、本稿では

  1. Playwright の単純に強い部分
  2. (Playwright の強さでカバーしきれていない)弊社の "ちゃんとしていない" 点
  3. ちゃんとしていくためにどうする

について述べていく。 Playwright 自体の有用な tips というよりは、テスト自動化を始めるにあたって Playwright に助けられたポイントをまとめる。 これを以て

  • Playwright の便利さ
  • HERP という会社の存在

を曖昧に伝える。

Playwright の単純に強い部分

Playwright を使っていてとりあえず目を引く部分として、

  1. Locator (とその関連の method)が整頓されている
  2. Trace Viewer が便利

というのがある。 この 2 つでもって、

  • (Playwright に自動でブラウザを操作させるための)テストコードをユーザー目線に近い表現で書ける
  • テストの実行によって多くの情報を得る

を両立させているのが強いッスねと感じる。

テストコードをユーザー目線に近い表現で書けると、単純に読みやすくなるんで良い。 また、逆にテストコードが読みにくくなってしまう機能に対して危機感を抱ける。 テストコードを通じてシンプルに機能を表現できるように努力し、機能への理解を深めましょうくらいの話をしている。

一方で、シンプルに機能を表現するにあたって、「一旦脇に置いておきたい事柄」の扱いが面倒になる。 例えば、

  • ある時点での DOM の snapshot
  • アプリケーション操作時の HTTP Request / Response

なんかは、シンプルに機能を表現する際には言及したくない。 が、それはそれとしてデバッグするときなんかには欲しい情報である。 わがままを言うと、シンプルに記述したテストを実施するとシレっと色々な情報も取れていて欲しい。 コードの見通しを良い状態に保てる上に実運用においても便利なんで。 Playwright はそのようなわがままを叶えてくれるということです。

ここをクリックしてLocator の話(テストコードをシンプルに書ける話)を開く

ブラウザを自動で操作するにあたって、「ページ内のこの要素をクリックせよ」という命令を記述していくことになる。 「ページ内のこの要素」を指定するために Playwright は Locator というもんを用意している。

playwright.dev

"recommended built-in locators" とされているものが以下であり、人間に優しいやり方でページ上の要素を指定できる。。

  • page.getByRole() to locate by explicit and implicit accessibility attributes.
  • page.getByText() to locate by text content.
  • page.getByLabel() to locate a form control by associated label's text.
  • page.getByPlaceholder() to locate an input by placeholder.
  • page.getByAltText() to locate an element, usually image, by its text alternative.
  • page.getByTitle() to locate an element by its title attribute.
  • page.getByTestId() to locate an element based on its data-testid attribute (other attributes can be configured).

例えば以下の画像のようなページについて、 ページの構造が良い場合は page.getByLabel("応募者氏名") などと書いて、ハイライトされているフィールドを指定できる。

弊社のアプリケーションのとあるフォーム

このように指定できると、「ユーザーは "応募者氏名" という文字列に対応してそうなフィールドに文字を入力している」という機能の意図をテストコードに反映できるんで嬉しい。

加えて、Playwright では Locator を chain させて「Locator で指定した要素の中で要素を指定」できる。 chain させたくなる例として、以下の画像のようなページについて考える。 以下の画像において、ハイライトされている要素は「メンバーを検索する」フィールドがあるモーダルの中にある。

弊社のアプリケーションのとあるモーダル。社員名や顔写真が露出する部分は灰色に塗りつぶした。

このモーダル内の「あるメンバーを示す要素」について、以下のように モーダルを指定 -> その中のメンバー名を指定 という形で locator を記述できる。

page
  .getByRole("dialog") // 注: dialog とはモーダルのこと
  .getByText("azoson")

これもまた「ユーザーはモーダルを開いたのち、そのモーダルの中から所望のメンバー名を探して操作する」という機能の意図を反映できるんで嬉しい。

ここをクリックして Trace Viewer の話(色々な情報を取れる話)を開く 上の Locator で推しているのは「要素の指定方法がよろしいんでテストコードが機能の意図を反映してくれて嬉しいです」ということだった。 実際のテスト業務としては、テストコード自体の良さとは別の話として、テストの実行結果にさまざまな情報が含まれていると嬉しい。 Playwright では Trace Viewer というツールがそこらへんの要望を満たしてくれている。

playwright.dev

テスト実行時に --trace on のオプションをつけるだけで、ブラウザ上で取得できる様々な情報について記録してくれる。 その後、便利な GUI で表示してくれる。 以下が表示の例。

あるテストケースに関する Trace を閲覧する画面

便利ポインツとして、

  1. ブラウザを操作した各時点での画面を確認できる
  2. ブラウザでのネットワーク利用を確認できる

あたりが目立つ。

Actions タブをリストアイテムをクリックするとその時点での DOM の状態を確認できる。 例として、以下の画像では 職種を選択してください をクリックしようとしているまさにその時の DOM が表示されている。

ある Action 時点での DOM

これは画像 ではなく マジで DOM を確認させてくれている。 具体的には、以下のように iframe で DOM のスナップショットを埋め込んで表示してくれている。

DOM をそのまま iframe で埋め込んでくれている

こんなんは「情報が多いです」というだけで値千金や。 その上、DOM の埋め込みを活かして「ポインターで指定した要素を取得するための Locator を suggest する」機能も Trace Viewer についている。 当然(?)、逆にユーザーが Locator を試す機能もある。

locator の suggest
Locator のお試し

これらの機能は「(DOM が原因で)テストがおおよそ成功するが時たま失敗する」みたいな場合の犯人要素探しに大変役立つ。

また、「テストがおおよそ成功するが時たま失敗する」原因がネットワークに関係する場合もある。 これについても、テスト実行中のネットワーク利用を全て記録してくれているんで、これ見ればなんとかなる。

ネットワークタブ

ネットワーク利用がミスった場合にのみ DOM がおかしくなってしまうのでテストが時たま失敗する、という合わせ技バグも世の中には存在している。 これについても、Trace Viewer が「テスト中の特定期間に発生した Actions / Network をフィルタする」という機能を提供してくれているんでなんとかなる。

期間による Actions / Network のフィルタリング

これらの機能のお陰で、自動テストで見つけた異常な挙動に対する調査がかなり捗る。 あざす。

弊社のちゃんとしていない部分

で、逆にこれだけスゲーやつを使っていてもあんまり綺麗にいかない部分というのは、まあ結構問題があるんじゃないすか流石に。 既に Trace Viewer の Actions 部分の画像で勘付かれているかもしれないが、先述の

テストコードをユーザー目線に近い表現で書ける

について、弊社は上手くやれていない部分が多い。 例えば、 DOM 構造がヤンチャである場合などに、Playwright の力を以てしても上手く書けなくなる.

DOM 構造がヤンチャである例として以下の画像の要素について考える。

問題のヤカラ

このフィールドはどうみても「 応募者氏名 と名付けられている textbox 」だから、以下のように書きたい。

getByRole("textbox", { name: "応募者指名" })

が、実際には以下のような問題が(弊社のフロントエンドに)ある:

  • フォームの一部として「フォームのラベルらしき文字列」と「フォームのフィールド」を与えるコンポーネントが存在している
  • ところで、このコンポーネントは「ラベルらしき文字列」を「(DOM 的な意味での)ラベル」として扱っていない

だから、実際使っている Locator は以下の作りになっている。

// ラベルらしき文字列 の DOM を取得する
getByText('応募者氏名', { exact: true }) 
 // その親が「ラベル + フィールド を持つコンポーネントの入れ物」である。
 //(ここまでを「コンポーネント用の Locator」として切り出している)
    .locator('..')
  // コンポーネントの中から入れ物を取得する
    .getByRole('textbox')

getByPlaceholder すれば良いんじゃないですかという話があるが、

  • "応募者氏名" というのが業務領域上の用語なんでそっちを優先したい
  • 弊社は改行が入ったバカ長い placeholder を使う場合があり、placeholder の作りが悪いせいで getByPlaceholder が効かない時がある

という別の事情があるんで、getByPlaceholder もうまく使えていない。 一応、関数切り出しによって Form("応募者指名").getByRole("textbox") みたいに呼び出せるようにしているが、気分は悪い。

弊社のちゃんとしていない部分の例として DOM 構造を挙げたが、他にも

  • 外部サービスとの依存関係の問題でテスト用の環境を準備しにくい
  • 要件を自動で検査しにくい機能が多い

などの問題がある。

ちゃんとしていくにはどうする

ちゃんとしていない部分というのを「Playwright とかいう強くて便利なもん使っているのに綺麗にテストできない」ことで改めて意識した。 なんで、Playwright を使った時に

  • 整頓された Locator でテストスクリプト自然に表現できる
  • Trace Viewer で十分な情報を確保できる

という状態を実現し、いつでも気持ちよく Playwright を使えるようにしていければ良いと思う。

取り組みやすい改善対象はヤンチャ DOM 問題であり、これについては a11y 改善などで解決していくつもりである。 弊社の使用ライブラリ事情的に Storybook Test Runner を用いた自動 a11y テストを利用することになると思う。 これもまた Storybook に依存している、というシナジーがある。

storybook.js.org

他、アーキテクチャ設計や組織体制など、多角的に取り組んで「気分よくテストを自動化していける組織」にしていきたい。 これらについて逐次報告し、弊社のテスト整備の実情を今後も発信していきたいと思う。 よろしく。