どうも、「zenncast」パーソナリティのマイクです。
七月八日、水曜日の朝七時を回りました。みなさんおはようございます。今日もこの時間は、技術記事の投稿プラットフォーム Zenn から、いまトレンドになっている記事をピックアップしてご紹介していきます。通勤・通学のお供に、コーヒー片手に、ゆるっと聞いていってください。

今日はお便りの紹介はお休みで、そのぶんガッツリ記事を追いかけていきたいと思います。

さて、きょうご紹介する記事は、ぜんぶで五本です。インフラ寄りの話からテスト戦略、JavaScript のパフォーマンス、オンチェーン決済のプライバシー、そしてフロントエンドのビジュアルリグレッションテストまで、かなりバラエティ豊かなラインナップになっています。それぞれ丁寧に追っていきましょう。

まず一本目。
一つ目は、「AI エージェントに安心して長時間作業させるための、案件ごと使い捨て開発環境の作り方」というテーマの記事です。

ここで使われているのが、Proxmox の上に立てた LXC コンテナです。LXC は、ホストのカーネルを共有するタイプの軽いコンテナで、「一台の Linux マシン」のように扱えるのが特徴ですね。テンプレートからリンククローンで一瞬で複製できて、それぞれに別々の IP アドレスが振られます。なので、Docker をさらにその中で動かしても「Docker の入れ子問題」が起きづらい、というのがポイントになっています。

運用としては、まず Debian の CT テンプレートをベースに、最低限のツールと Docker、それから一般ユーザーと SSH 鍵などを仕込んだ「元コンテナ」をひとつ用意します。このとき、sshd の鍵が自動で再生成されないように条件を外しておいて、その状態でテンプレート化しておく。
あとは Proxmox の `pct clone` コマンドで、案件ごとにコンテナをポコポコ増やしていくスタイルです。使い終わったら `pct destroy` でさっと破棄。スナップショットやバックアップも簡単に取れるので、AI エージェントに好きに触らせても「最悪壊れたら捨てればいいや」と割り切れる環境になっています。

ネットワークまわりも工夫されていて、各コンテナごとに IP 管理したり、Tailscale を入れたりするのは面倒ですよね。この記事では、Proxmox ホストを踏み台にする SSH 設定を工夫していて、たとえば `ssh dev-三二二` みたいなホスト名から VMID を抜き出して、その番号を使って `pct exec` と `nc` を組み合わせることで、コンテナの二十二番ポートに直結できるようにしています。
これによって、Tailscale は Proxmox ホストにだけ入れておけばよくて、VSCode や Zed の SSH Remote からも、ホスト名ベースでスッと入れるようになる、というわけですね。

ランタイムや各種ツールは、テンプレートの中に固定では埋め込まず、コンテナごとに mise や Docker を使って入れていきます。AI エージェントが自由に触れる部分はそのコンテナの中に閉じ込めておいて、ユーザーには sudo 権限は与えず、通常ユーザー+ docker グループの範囲にとどめておく。
「環境を汚されても、案件単位で丸ごと捨てられる」という前提で、安全側に切り分ける発想です。案件ごとに VM を完全に分けることで、認証情報や設定ファイルが混ざらないようにできますし、サプライチェーン攻撃への備えとしても、ひとつの案件の被害を他に波及させにくいという一定の効果がある、とまとめています。
AI エージェントに作業を任せたい人、あるいは検証環境をたくさん作る方にはかなり刺さる内容だと思います。

。。。。

続いて二本目。
二本目は、自動テストが増えてきたときにかならず出てくる「CI が遅い問題」とか、「偽陽性・偽陰性が増えて信頼しづらい問題」にどう向き合うか、というテスト戦略の記事です。

この記事の軸になっている考え方は、「コード変更への不安をどれだけ減らせるか」と「実行時間」のバランスをコンパスにする、というものです。テストを書く目的は、最終的には安心してリリースすることですけれど、その安心をどのテストでどれくらい買いにいくのか、という視点ですね。

筆者は「よいテスト」を二つの条件で定義しています。
ひとつ目は、テストが通れば開発者が安心してリリースボタンを押せること。
ふたつ目は、設計やリファクタリングに対して良い影響を与えること。
この二つを満たすテストを増やしていこう、というスタンスです。

ただし、テストには粒度があります。単体テスト、結合テスト、エンドツーエンドテスト。粒度が上がるほど、実行時間は長くなりがちで、テストの安定性も落ちやすい。一方で、カバーできる範囲は広くなりますよね。この記事では、プロジェクトの「ホットスポット」、つまり頻繁に変更されるところやバグが多いところを見ながら、この粒度の配分を調整し続ける必要があると述べています。

その議論のために持ち込んでいるのが、Google 流の「テストサイズ」という共通言語です。Small、Medium、Large という三つのサイズで、テストが必要とするリソースの量で機械的に分類してしまう、という提案ですね。
たとえば、単一プロセスで完結するものは Small、ローカルマシン内のリソースまで使うのが Medium、外部サービスや本物の DB まで触りにいくのが Large、というイメージです。
こうすることで、「テストピラミッドがどう」といった抽象的な流派の話ではなく、「うちのプロジェクトでは Small を厚めにするのか、Medium を増やすのか」といった具体的な戦略の話がしやすくなります。

実務でどうするか、というところでは、レイヤードアーキテクチャを前提に、各レイヤーごとに「テストで何を保証するか」をはっきり決めるやり方が紹介されています。
同じ種類のバグしか検出しないテストがレイヤーをまたいで重複していると、実行時間ばかり増えてしまいますよね。そこで、DB や外部サービスをモックにしてテストサイズを落とすとか、型でドメイン制約を表現してテストケース自体を減らすとか、そういった工夫で「より速くて有益なテスト」に寄せていく実例が出てきます。

具体例としては、REST API を題材にしています。プレゼンテーション層、ユースケース層、ドメイン層、リポジトリ層、外部サービスとの連携、フロントエンドまで含めた結合、といったレイヤーそれぞれについて、「ここは Small の単体テストでどこまで見るのか」「ここは Medium にして動作確認をどれくらい網羅するか」といった戦略案が示されています。
そして、テストカバレッジと実行時間を継続的に計測しておいて、「実行時間を削って CI を速くするのか」「安心を増やすためにあえて時間をかけるのか」を判断しながら、テストを間引いたりサイズを変えたりする運用の重要性が強調されています。
テストが増えすぎてしんどいチームにとっては、考え方の整理にとても良い記事ですね。

。。。。

三本目。
三つ目は、JavaScript のメソッドチェインがなぜ遅いのかを、Rust と比較しながらベンチマークで分析している記事です。

Rust の `Iterator` って、`map` と `for_each` をつないでも、実際には一要素ずつ「取り出す → map で変換する → for_each で処理する」という流れをパイプラインのように流していく、遅延評価の仕組みになっています。そのため、中間配列をまったく作りません。結果として、メモリ効率もよく、とても高速に動くんですね。

一方で、従来の JavaScript の `Array.map().forEach()` だと、まず `map` が全要素を変換して、新しい配列に全部ため込みます。そのあとで、その新しい配列に対して `forEach` を回す、という二段階になってしまう。
この構造の違いから、メモリも多く使うし、処理時間も余計にかかる、というのがこの記事が示しているポイントです。

じゃあ、ES 二千二十五年以降に入ってくる Iterator Helpers を使えば、JavaScript でも Rust っぽい遅延評価の書き方ができて速くなるんじゃないか、という期待がありますよね。
この記事では、まさにそこをベンチマークしていて、Iterator を一件ずつ取り出すオーバーヘッドが意外と大きくて、結局 Array 版より速くならない、という結果が示されています。

さらに比較対象として、RxJS や IxJS、lodash、それから素の `for` ループなんかも試しています。結果としては、lodash や手書きの `for` ループはけっこう健闘していて、状況によってはかなり速い。ただ、仕様に依存してしまったり、コードがやや書きづらくなったりするので、「とりあえずこれを常用しておけば安心」という存在にはなりきれていない。
そういう意味で、「現時点では、安心して常用できる、標準的で高速な遅延ストリーム実装はまだ存在しない」という結論になっています。
パフォーマンスを気にするフロントエンドや Node.js エンジニアには、具体的な数字と一緒にイメージがつかめるおもしろい内容でした。

。。。。

四本目。
四つ目は、AI エージェントがオンチェーン決済を使って API を呼ぶときの、プライバシー問題に切り込んだ記事です。

普通にブロックチェーン上で決済すると、「誰がどの API に、いくら払ったか」が全部チェーン上に残ってしまいます。そうなると、AI エージェントの行動パターンも丸見えですし、特定の provider がどれだけ売り上げているかも推測されてしまう。
この記事では、この「誰が誰に払ったか」という対応関係だけを消すための仕組みとして、x四〇二 の決済部分を、プライバシートークン zERC二〇 の burn と mint に置き換える PoC、「SubEtha」を紹介しています。

SubEtha では、支払い先として provider の固定アドレスは出しません。代わりに、支払いごとに新しく作る「正体の分からない burn アドレス」を提示します。エージェントは、その burn アドレスに zERC二〇 を送金するだけです。
provider 側は、後からゼロ知識証明を使うことで、その burn の合計額だけを自分のウォレットに mint できます。ただし、どの burn から来たか、という対応関係は公開されません。
結果として、オンチェーンに残るのは、「payer から謎アドレスへの送金」と、「treasury からの受け取り」の記録だけ。payer と provider のペアリングが切り離されているので、挙動の追跡がかなりしづらくなる、という設計です。

さらに、AI エージェントにガス代まで負担させないための工夫として、permit と、専用のコントラクト PermitBurner を組み合わせた gasless 送金も実装されています。ユーザーは署名だけして、実際の送金トランザクションは別のエンティティが負担するイメージですね。
ただし、決済の匿名性そのものは、あくまで burn と mint の構造で担保していて、「誰が誰に払ったか」を隠すところが本丸になっています。

また、複数回の支払いをまとめて一回の mint にする「バッチ処理」を入れることで、「一回の burn に対して一回の mint・金額も同じ」という分かりやすい規則性を崩しています。これによって、金額ベースで burn と mint を突き合わせて追跡するのを、より難しくしている。
とはいえ、金額そのものは隠さないなど、どこまで守れてどこからは守れないのか、という限界もちゃんと明示されています。
オンチェーンでの AI エージェント決済が当たり前になったときに、プライバシーどうするの、という問いに対して、かなり具体的なアプローチを示してくれている記事でした。

。。。。

そして最後、五本目。
五つ目は、フロントエンド開発者に嬉しい話題で、Vitest 四点ゼロの Browser Mode に入った VRT、いわゆるビジュアルリグレッションテスト機能と GitHub Actions を組み合わせて、「外部サービスなしでシンプルな見た目の自動テストを回す」という記事です。

ここで紹介されているフローは、まず手動あるいはスケジュール実行で、コンポーネントのスクリーンショットを撮ります。そこから、既存のベース画像との差分をチェックして、差分があれば、自動的にベース画像更新用のプルリクエストを作ってくれる。
人間は GitHub 上でそのプルリクの差分画像を確認して、問題なければマージ、という運用ですね。いわゆる「Screenshot as Code」的な感じで、外部の VRT サービスに頼らなくていいのが魅力になっています。

実装面では、`@vitest/browser` と、Playwright 系のパッケージ、それから `vitest-browser-react` をインストールして、Browser Mode 用の project を定義します。ブラウザは Chromium、ビューポートは固定サイズで走らせることで、環境によるブレを減らしている。
さらに、テストのセットアップでアニメーションを無効化して、ホバーやフェードインの揺らぎがスクリーンショットに乗らないようにしたり、`allowedMismatchedPixelRatio` という設定で、許容できるピクセル差分の割合を少し持たせたりして、誤検知を減らす工夫が詳しく紹介されています。

CI では、`vitest --project vrt` と `vitest --project vrt --update` を npm スクリプトにしておいて、GitHub Actions からその二つを呼び分けます。テストが失敗した場合には、画像を更新してプルリクエストを自動作成。レビュアーは GitHub の Files changed の画像比較 UI を使って、スワイプ表示などで差分を目視確認する、という想定の運用です。

さらに一歩踏み込んで、Custom Reporter を使って flaky テストの検出も行っています。再実行して通ったテストだけを拾って、GitHub のコメントや Slack 通知で「このテスト怪しいよ」と知らせる仕組みですね。
それに加えて、Playwright Trace Viewer と連携して、Browser Mode のテスト実行を丸ごと録画し、ステップごとの動きを後から追いながらデバッグする方法も紹介されています。
「とりあえず VRT やりたいけど、専用の SaaS はちょっと…」というチームにとって、かなり即戦力になりそうな内容でした。

。。。。

というわけで、きょうの「zenncast」は、
一つ目に Proxmox 上の LXC コンテナを案件ごとに量産して、AI エージェントに安心して触らせられる使い捨て開発環境の話。
二つ目に、「コード変更への不安」と「実行時間」のバランスで考える、自動テスト戦略とテストサイズの話。
三つ目に、Rust と比較しながら見ていく、JavaScript のメソッドチェインと遅延評価のパフォーマンスの話。
四つ目に、x四〇二 決済を zERC二〇 の burn と mint に差し替えることで、オンチェーン決済の「誰が誰に払ったか」を見えにくくする SubEtha の話。
そして五つ目に、Vitest 四点ゼロの Browser Mode と GitHub Actions を使って、外部サービスなしで回すビジュアルリグレッションテストの話。
この五本を駆け足でご紹介しました。

気になる記事があった方は、詳しい内容やキーワードをショーノートにまとめてありますので、あとでぜひチェックしてみてください。
番組への感想や、「こんなテーマを取り上げてほしい」といったリクエストも、いつでもお待ちしています。

それでは、きょうも良い一日をお過ごしください。
お相手はマイクでした。また次回の「zenncast」でお会いしましょう。

Related episodes

内容の近いエピソードを推薦しています