いよいよPuppeteerを使う理由がなくなってきた

空き時間を活用しつつ、 puppeteer-rubyplaywright-ruby-client という2つのOSSを育てている。puppeteer-rubyGoogle Chromeチームによる元祖Puppeteer をまるっとRubyで再実装したライブラリで、playwright-ruby-clientは PuppeteerからフォークしてMicrosoft(のなかの元Chromeチームメンバー)が育てているPlaywright のクライアントAPIRubyで実装したライブラリだ。

yusukeiwaki.hatenablog.com

この記事を書いたときには、「Playwrightは自身が起動したブラウザしか自動操作できない」という大きな欠点を挙げていた。

しかし、その数週間後、Playwright 1.9.0で browserType.connectOverCDP というAPIが追加されて、こいつがまさに puppeteer.connect 相当のことをやってくれるようになった。

github.com

つまり、「Seleniumの補強として使う」ということが、PuppeteerのみならずPlaywrightでもできてしまうようになった。

f:id:YusukeIwaki:20210419135049p:plain

現在はpuppeteer-rubyとplaywright-ruby-clientの2つのOSSを現在育てているけど、今後は本格的にplaywright-ruby-clientのほうを注力していくことになるかもしれない。

スキマ時間は意外とある

昨年の暮れに12インチMacbookを入手してからというもの、肌身離さず12インチMacbookを持ち歩くようになった。

yusukeiwaki.hatenablog.com

こいつはとても優秀で、本当にどこにいてもコーディングが可能なのだ。スタバでドヤるという意味ではなく、エレベータの待ち時間とか、横断歩道の長い信号待ちとか、車の渋滞で停車中とか。

puppeteer-rubyやplaywright-ruby-clientの開発が少しずつながら確実に進捗している。

訳あって、3月に入ってからは本当にまとまった時間がとれないので、スキマ時間を積極的に活用している。1つ1つは10秒から1分程度だが、その間に1つでも2つでも単体試験を書けば、OSS開発はかなり捗る。

今後も(物理的に)事故らない程度に続けていこう。

第13回フクオカRuby大賞で入賞!その振り返り。

第13回フクオカruby大賞っていう、Rubyをネタにしたビジネスコンテストてきなものに参加した。

www.digitalfukuoka.jp

まだどこにも公表されていないし、開催から数日が経過して自分でも忘れつつあるんだけどw 、優秀賞とマネーフォワード賞の2つをいただけた。(わーい!)

(2021.02.09 公開されました!! <結果発表>「第13回フクオカRuby大賞」審査結果 - 福岡県Ruby・コンテンツビジネス振興会議 )

なぜ参加した?

puppeteer-ruby を趣味の開発でかれこれ半年以上かけてつくっていたけど、一発どこかで披露したいなと思ったのが事の発端。

puppeteer-rubyはビジネス価値を求めて作っていたわけでは全くないのだが、いっぽうで自動試験の運用を段階的に変えていける可能性があるとも思っていた。

ちょうど会社でも自動試験の担当者が運用で苦しんでいて、空き時間で自動試験の段階移行をするための試作も重ねていたし、puppeteer-rubyがPoC(proof of concept)としては十分すぎるレベルに達している自覚はあった。

また、フクオカRuby大賞はビジネスコンテストな側面もありつつ、過去の入賞作品を見ると、

「falcon」 Samuel Williams(海外:ニュージーランド

とても見覚えのあるものがあった。(puppeteer-rubyの開発初期に、非同期処理をどうするか悩んでたときに見た socketry/async の作者!)

falconが世の中で使われているのは正直みたことはないのだけどw、それでも入賞しているというところでピンときた。

要は、作ったもの単体が価値があるものであるというよりも、その周辺技術や取り組みなどふくめて評価されているんじゃないかと。だとすると、puppeteer-rubyもそれ単体は試作+αくらいのレベルだが、総合力でいいところまでいけるんじゃないか?と。

ともあれ、目的意識としては「puppeteer-rubyを知ってもらえるだけでもいいな」くらいで気楽に参加することにした。

puppeteer-rubyの優位性は何か?

一応はビジネスコンテストっぽい感じなので、ビジネス価値を落ち着いて考えることにした。

  • Capybaraとの共存
  • Rubyでブラウザの自動操作をしようとしたときに、気軽に(Seleniumみたいにドライバーを別途用意するなど煩わしい手順なく)遊べる
  • RubyからCDP(Chrome DevTools)を使ってブラウザを自動操作できるライブラリはFerrumなどがあるが、それらはみなChromeしか自動操作できない。Firefoxも自動操作できるのは世界でpuppeteer-rubyだけ

候補はこのあたりだ。今回は 周辺技術も含めてしっかり価値が伝わるか? がポイントなので、もうすこし深堀りして考えた。

Capybaraとの共存

そもそもRubyRailsで自動試験を運用してる人はおるんか?という問い。

  • てすらぼってイベントに参加していろいろ聞いたが、Railsの関係者はおそらくいなかった。
    • ただSeleniumでしんどい思いをしていた人は結構いた。
  • そもそもE2Eテストは単体テストありきでオマケであるべき。
    • これからRailsで新規にサービス作る人がE2Eで苦しむことはほぼない。
  • RailsにSystemTestCase(実際にブラウザを動かすテスト)が導入されたのは5.1なので割と最近。これはなんのためのものだったんだろう?
    • 従来よりあったFeature specはそもそもCapybaraベースなので、Flakyテストしんどい問題を抱えていたはず。
      • 従来のFeature specでは、ActiveRecordのコネクション共有がされていないため、特定の状況を作り出すことができない。つまり、テストの単位を小さくすることが難しい。
      • SystemTestCaseであればFactoryBotを使って特定の状況を作り出すことは簡単。テストの単位を細かくすることで、Flakyテストが仮に発生しても単純リトライすればいいだけになる。
    • おそらくSystemTestCaseは、受け入れテストを書きたい人ではなく、すでに大規模なサービスを作ってしまった組織をメインターゲットにしていそう。

→puppeteer-rubyも、ターゲットを「すでに(あまり単体テストを書かないまま)大規模サービスを作ってしまった組織が、E2Eテストを運用している」前提にすることにした。そうすれば、従来の仕組みでは、Capybaraで苦しむかJSベースのテストフレームワークに載せ替えるかの2択しかない。それに対して、puppeteer-rubyは"補強・段階移行"を可能にする第三の選択肢を与えることができる。

気軽に遊べる

「ブラウザオートメーションで業務効率化♪」「R!P!A!」みたいな人は居るには居るかもしれない。ただ、そこについてビジネス価値創出は・・・あまりなさそう。

そもそも単発で適当に動けばいいレベルなら、Ferrumがすでにある。また、もしも"Puppeteerを使って"遊びたいのだとすると、それはRubyじゃなくてJavaScriptを選択したほうが賢明だ。

つまり、この点においてはpuppeteer-rubyの優位性はおそらく無い。

RubyからCDPでFirefoxを操作できる世界で唯一のライブラリ

「世界で唯一の」という文言はとても見栄えする。ただ、「Chromeで動かなくてFirefoxでは動く」みたいな謎めいたWebサービスでも扱わない限り、その優位性はない。

ちょうど2020年の春にIEサヨナラ&ChromiumベースEdgeが出て、今後ほとんどのサイトはChromeで動くことが必須になるだろう。そう考えると、「Firefoxを動かせる」ことは主張として弱い。

とりあえず応募してから考えることにした

応募文面としては、RubyRailsのE2Eテストの改善というところになるべく絞って書いた。

f:id:YusukeIwaki:20210124152130p:plain f:id:YusukeIwaki:20210124152200p:plain f:id:YusukeIwaki:20210124152233p:plain


ちなみに、この応募はWebのフォームではなく、Wordファイルを編集してメールで送る 必要がある。運営の方々に頑張っていただいているところ申し訳ないのだけど、これは言わずにはいられなかったw↓

ちなみに、応募後のやりとりもメールベースで、重要なファイルはPPAP(パスワードはあとでおくりますプロトコル)でやりとりされる。そこそこちゃんと届くメールアドレスが必須だ。

この時点では、プレゼン資料は未作成。puppeteer-rubyが実は動かない状態だったとしても、ただただ理想的なストーリーを書いて出すだけである。(「実は動かない状態だった」というのはマジな話で、プレゼン資料を作るときに気づいて直した↓)

本審査への招待がきたが、プレゼン資料は締切の2日前から作り始めた

12/21にこんなメールが来た。

f:id:YusukeIwaki:20210124152918p:plain f:id:YusukeIwaki:20210124153012p:plain

今年は新型コロナウィルス感染拡大防止のため、オンライン開催。プレゼン資料は年末年始をはさんで1/12までに作ってね、と。

メールを受け取ったときには、年末年始でプレゼン資料を作るつもりでいたが、実際にはそんなことはなく、締切2日前から焦って作った。年末年始は何をしていたかといえば、読書だw

yusukeiwaki.hatenablog.com

自分は、楽しいことは楽しいと思えるときにやらないと、一生やらない性格なので、こういう気に入ったの本は一気に読まないとだめなのだ。

そして読書が終わり、プレゼン資料を作るのかと思いきや、こんどは playwrightの仕組みを調べたくなって、Rubyクライアントを作ったりしていたw

yusukeiwaki.hatenablog.com

とことん遊び呆けた結果、プレゼン資料を作り始めたのが1/10だった、と。

かなりアホではあるけど、これはこれで有意義だったところもある。学習する組織の最初の方にある"システム思考"というのを使って、レガシー開発におけるE2Eテストの効果/レバレッジをシステム思考で考えてみることはできたし、playwright-ruby-clientを作る過程でPlaywrightの中身をソースコードレベルで深く読んだおかげで、PuppeteerとPlaywrightがそれぞれどういう強みを持っているか理解することができた。単純にpuppeteer-rubyのスライドを唸りながら作るのに比べて、周辺技術や背景をしっかり理解してストーリーを作ることができたと思う。

スライドはGoogle Slideで作った。これは本当に大失敗

Keynoteで作ると、スマホで移動中に編集することができないし」と思ってGoogle Slideでプレゼン資料を作った。

f:id:YusukeIwaki:20210124154053p:plain

が、結果的にはこれは大失敗だった。

  • プレゼン資料の提出がメールベースなので、PDFに変換する必要があるのだが、PDF変換するとレイアウト崩れを起こす
  • 本番はMicrosoft Teamsでのオンライン会議だったが、 Microsoft TeamsはGoogle Slideの発表画面を共有することができない (これが致命的)
  • 発表後にSpeakerDeckなどに資料を上げるにも、PDF変換すると(以下略...

そもそも「外出中に編集できるように」なんて考える必要はなかった。自分はショッピングモールの出口の渋滞中にもRSpecを書いてるくらい、どこにでも12インチMacbookを持ち歩いている。外出中にKeynoteを編集することくらい余裕だったはずだ。

今後はやはりKeynoteにしようと思う。

ちなみに、Google Slideをなるべくレイアウト崩れせずにSpeakerDeckに上げることは一応できた。Google SlideをMicrosoft PowerPoint(.pptx)でエクスポートして、それをPDF変換するといい。一部のフォントは変わってしまっているが、レイアウト崩れまでは起きなかった。

speakerdeck.com

発表練習しまくった

フクオカRuby大賞は過去にどんな作品が入賞しているのかは書いてあるが、どんな発表をしたのかという情報が一切ない。

エンジニア相手の勉強会のように、前提知識もりもりで気楽に話せる感じではないとして、一体どのくらいまで前提知識を期待してよいものか?

とりあえずよくわからないかったので、1から10まで説明する感じのプレゼンをまずは作ってみた。

発表時間10分に対して、22分10秒wwww

少し中身を削って発表すると・・・?

発表時間10分に対して、10分15秒wwwwww

・・・とはいえ、早口で話すのは非常に苦手なので、最終的には 重点的に説明するスライドを5つだけに絞って、あとはさらさらっと流す って感じにした。

練習は、Microsoft Teamsの会議録音機能を使って、自分で発表したのを自分で見返して文句をつける感じでブラッシュアップした。

f:id:YusukeIwaki:20210124155906p:plain

いざ本番

Teamsオンライン会議は、会社で使って慣れていたので、操作に手間取ることはなく、内容の説明も割とリラックスして発表できたかなと思う。

TeamsはZOOMと違って、プレゼン(画面共有)中に他の人の反応を一切見ることができないので、ひたすら画面を見てしゃべり続けることになる。時間計測用のタイマー(スマホのアラームアプリ)をパソコンの横において、時間どおりに発表できているかというところだけ注意して発表を進めた。(たぶん発表時間は少しオーバーしてる)

入賞!

審査結果発表は、おもいっきり業務時間中の夕方に行われる。今回は趣味のプロダクト開発で出ているので、業務中に参加するのも気が引けて、とりあえずiPadからTemas会議に入って、様子は見つつも仕事をしていた。(ごめんなさい)

ただ、なんかpuppeteer-rubyってのが聞こえた気が?!ってなって、急遽、上司に事情を話して、パソコンからTeamsに入り審査会に参加。(TeamsはiPadで入っている会議にそのままPCからもサラッと主催者/参加者に気づかれず入れるのは便利ねw)

マネーフォワードの方からのありがたいコメントを頂戴し、その後の優秀賞の発表後のコメントも、かなりアセアセしながら応えたw

持続可能な開発をしていかないと〜

今回、まさか入賞するなんて思っていなかったので、実はpuppeteer-rubyは手を抜き始めていた。

ただ、今回の発表で改めて感じたのは、自分がやってきた開発は思ったよりも需要はありそうで、もっと広めていくべきだということ。そうなると、趣味で1人で開発していくのには限界があって、 コミュニティとして開発できるようにpuppeteer-rubyを育てていかないといけない

まだ全然知名度はないと思うので、今後しばらくはpuppeteer-rubyだったりplaywright-ruby-clientだったりを作りつつも、Rubyでのブラウザオートメーションの布教活動っぽいことをやっていこうかなと思う。

(蛇足)みんなPuppeteerとPlaywrightを同一視しているけど・・・

PuppeteerとPlaywrightをどちらもソースコード読んだ身として、一言いっておこう。

  • Puppeteerは、すでに起動済みのChromeに対してアタッチする Puppeteer#connect というメソッドがある。
  • Playwrightは、Puppeteerから分化した直後はその機能があったが、サーバー・クライアントアーキテクチャが採用されたあたりで、その機能が完全になくなった(ref: feat(launch): introduce client, server & persistent launch modes (1) by pavelfeldman · Pull Request #838 · microsoft/playwright · GitHub )。Playwrightは、自身が起動したブラウザを操作することだけできる。
    • サーバークライアントモデルなので、「リモートサーバーにPlaywrightサーバーを立てて、そこあるブラウザをPlaywrightクライアントから操作する」みたいなことはおそらくできるが、 Playwright以外によって起動されたブラウザを操作することができない という意味。

Puppeteerは単純にCDPを使うことに特化したツールキットなのに対し、Playwrightはブラウザオートメーションのオールインワンツールキットという感じだ。

ほとんどのケースではPlaywrightのほうが有力なのは間違いない。しかし、今回のpuppeteer-rubyが対象としたような「すでにCapybaraでテストケースを運用していて、共存・段階移行したい」というケースでは、Capybaraが起動したブラウザにアタッチできるPuppeteerが必要である。Playwrightではこれができない。

なので、playwright-ruby-clientを作っているから、puppeteer-rubyはもうオワコン?とはならない。用途が全然違う。

playwright-ruby-clientはどちらかというと、Ferrumに近い位置づけで、今後はCupriteのようなCapybaraドライバを作ったり、Vesselのようなクローラー書く仕組みを作ったり、みたいな方向性で成長させていく必要がある。

puppeteer-rubyはあくまでCapybaraとの「共存」ができることを強みに、(本家Puppeteerがなくならない限りはw)育てていくだろう。