ContractS開発者ブログ

契約マネジメントシステム「ContractS CLM」の開発者ブログです。株式会社HolmesはContractS株式会社に社名変更しました。

RSGT2021参加後、早速実践してみた話

こんにちは。 Holmesでスクラムマスターをしている吾郷です。

先日行われたRSGT2021に参加してきました。
素晴らしい出会いと刺激に恵まれたイベントでした!
今回は参加したセッションの中から振り返りについて、参加後に実践した話と合わせて紹介できたらと思います。 

セッション内容

ふりかえりで参加したセッションは、森さんのふりかえり手法のおもちゃばこでした!
実は、これまで何度か森さんのふりかえり実践会には参加させていただいてます。

retrospective.connpass.com

興味ある方は是非参加してみてください!

スクラムにおけるイベントの一つであるレトロスペクティブは、アジャイルレトロスペクティブズなどの書籍では体系的に学ぶことができます。
今回はとにかく手法を紹介しまくる!というもので、ひたすらいろんな手法を知ることができました。
改めてふりかえりって本当にいろんな方法があって面白いな〜と思いましたね!
いろんな観点からふりかえりを通したチームビルディングができると思います。

簡単にセッション中で紹介されたふりかえり手法を紹介します。

  • 感謝
    • 日頃の感謝を伝える(他の手法と混ぜ合わせる)
  • kudo card
    • カードを用いて感謝を伝える
  • カラーコードドット
    • 感情や熱量が上下したものにドットをつける
  • 喜怒哀
    • 出来事からではなく、感情から思い出す
  • Good&New
    • 場作りで使う
  • フォースフィールドアナリシス
    • 問題分析手法
  • FMEA(Failure Mode and Effect Analysis)
    • Failure→Analysis→Evaluation→Actionの順で整理する
  • 5つのなぜ
    • なぜを5回繰り返す(「なぜ?」の質問だとつらいので、「何がおこったの?」にするとよい)
  • Six Thinking Hats
    • 思考法の一つ。それぞれ役割の異なる帽子を被り替えながら議論を進める
  • 闇鍋
    • テーマを書いた上を箱に集めて引いていく。
  • KPT as ART
    • KPTの色を使い分けて、まばらに貼っていく
  • Blokus
    • 内容を提起したり、リプライしながら自分の陣地を増やしていくゲーム
  • ポジティブふりかえりマッピング
    • 終始ポジティブにふりかえることができる
  • ありたい姿
    • 未来志向のふりかえり。チームの理想とのギャップを埋めていく

各ふりかえりの詳しい手法については、 ふりかえりを拡張する「ふりかえりカタログ」 - Qiita で確認できます。
資料自体もPDFで配布されていますので、ご活用ください。

実践

最近自身が所属するチームの振り返りで、ポジティブなふりかえりが少ないこと、楽しめる要素が少ないことを鑑みて、上記ふりかえり手法のうち早速実践してみたのは以下の手法になります。

ポジティブふりかえりマッピング

まず最初に実行したのは、ポジティブになれるポジティブ振り返りマッピングでした!
終始、全く暗い話が出ず確かにポジティブに振り返る事ができました。
また、実験回数を多くする為に、今回2チームに分けて最後実験アイデアを考えてもらいました!
普段よりもTRYの回数は多くはなりますが、その分たくさんのアイデアを小さく回すことで何か発見につながる可能性が大きいと感じます。

f:id:seiseiholmes:20210129153824j:plain

また、ふりかえりの冒頭で紹介した、NormKerthの言葉は振り返りのFBでも非常に好評でした。

どんな道をだどったにせよ、当時の知識・技術・能力・利用可能なリソース・状況の中で、みんなができる限り最高の仕事をしたはずです。それを心から信じます。

自身も実際に感じたのは、このポジティブふりかえりマッピングに限らず、様々な振り返りで有効だろうということです。
少しの時間でみんなで方向を一つにして振り返りできるので非常におすすめです!

Blokus + ドット投票

続いて試したのはゲーム感覚で楽しめるBlokusです。
はじめにトラブル*1が起きましたが、その後は基本的にスムーズに行けました。
とはいえこちらは、自分自身の振り返りの準備不足ですね・・・!新しい取り組みをする際には注意したいところです。

f:id:seiseiholmes:20210129153837j:plain

集計で思ったよりも差が開いたりと、個々のメンバーを新しい一面も見ることができ、新しい学びとなりました。
Blokus自体楽しい要素がいっぱいですが、これ一つだとTRYを考えるためのステップが足りません。
そのため今回はTRY出しの手法であるドット投票と組み合わせて振り返りを実施しました。

振り返りでは、やはりゲーム性がある振り返りは純粋に楽しいといった声が聞こえた一方で、時間が足らないと言った声もありました。
このあたりは、今後の振り返り開催で随時改善していければと思います。

今後の活動

まだまだ試してみたいふりかえりはたくさんあります。小さく実験して、チームで様々な発見に結び付けられたらと考えています。

実はRSGT2021参加者には録画が共有されており、社内への展開ができます。(※URLのみの共有はNG)

これはいい機会!と思い、自分が参加できなかったセッション含めて早速、社内で希望セッションのアンケートを取りました。 要望が多いものから順に視聴会+ワークの形から始めて行こうと計画しています。 自分の体験の共有からSECIモデルを実践し、社内の知識創造を実現していこうと思います。

また、セッションには学問的な問い・哲学的な話題も多くありましたが、馴染みのある話題は少なくこちらもちょっとずつではありますが、自分の中に取り込んでいけたらと感じました。

これからもScrumMastersWayは続いていきます!

最後に

Holmesはエンジニア・デザイナーを募集しています。 共にプロダクト作りを通して、社会・組織を良くしていきましょう! 興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com

*1:MiroのGrid機能は同時編集ができない

DevRel活動始めます

こんにちは、id:c-terashimaです

2020年の3月にスタートしたHolmes開発者ブログですが、アピール活動をあまり行ってきておらず数件のアクセスのみという日もありほそぼそと活動してきました。
そんな開発者ブログですが、あることをきっかけに はてなブログランキング 入りします。
あることというのがDDDサポートをしていただいているDDD Community JP主催の松岡さんにご紹介いただいたことです。

blog.hatenablog.com

改めて「インフルエンサーの影響力すごい!」「今までアピール活動してなかったのはもったいなかった」と感じ、自分たちでも活動していくことで

  • より多くのエンジニアにHolmesを知ってもらいたい
  • Holmesの取り組みを知ってもらうことで
    • 同じ悩みを抱えている方の助けになりたい
    • 共感してもらえたエンジニアと繋がりたい

を目指し技術広報活動準備会を立ち上げました!
とはいえ右も左も分からない完全初心者 なので、先人の知恵を借りようと「DevRel/Beginners勉強会」に参加してきました 。

devrel.connpass.com

DevRelとは

Developer Relationsの略
Public RelationsのDeveloper版で開発者向けのマーケティング

DevRelは外部の開発者との相互コミュニケーションを通じて、自社や自社製品と開発者との継続的なつ良好な関係を築くためのマーケティング手法

参考: https://devrel.jp/about/

この勉強会ではDevRelの基本とマーケティング戦略を知ることができHolmes開発グループをより多くのエンジニアに知ってもらうための道が見えた気がします。
「技術より情熱、お金より行動」この言葉を個人スローガンにしていきたいと思います。

これから色々な活動を通じてエンジニアの皆様にお会いできることを楽しみにしております。
もし見かけた場合は優しく声を掛けていただけると幸いです🙇


Holmesはエンジニア・デザイナーを募集しています。 興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com

SpringBoot + Intellij でホットスワップをする

この記事は Holmes Advent Calendar 2020 - Qiita 15 日目の記事です。


こんにちは。Holmesでエンジニアをしている毛見です。

最近SpringBootのBootRunに掛かる時間が長く、少しの修正でもBootRunし直さなければならないので、それをせずに変更を反映できるホットスワップについて調べたのでまとめます。

環境

  • macOS 10.15.7
  • Java11
  • Intellij 2020.2.4
  • spring initializerによりプロジェクトを生成
    • Project : Gradle Project
    • SpringBoot : 2.4.1
    • Packaging : Jar
    • Dependencies : Spring Web, Thymeleaf

設定手順

HotSwapの設定

  • intellijのPreferencesでHotSwapの設定を行う。
    • Reload classes after compilationのAlwaysもしくはAskを選択する。

Preferences | Build, Execution, Deployment | Debugger | HotSwap

それぞれの設定値の内容は公式ドキュメントを参照

テンプレートの変更を常に反映する設定

この設定をしなくてもHotSwap自体は可能ですが、thymeleafテンプレートは、変更を反映する際の一手間を減らせます。

  • application.ymlに cache: falseを追加
spring:
    thymeleaf:
        cache: false
  • build.gradleにsourceResources sourceSets.mainを追加
bootRun {
    sourceResources sourceSets.main
}

HotSwapをする

  1. BootRunをデバッグ実行
  2. コードの変更
  3. inttelijのメニュー/Build/Recompile '編集したファイル名' でコンパイル、もしくはショートカットコマンド ⇧+⌘+F9
  4. intellijのHotSwapの設定で、Askを選択している場合、intellijにクラスをリロードするか聞かれるのでYesを選択。

テンプレートの変更はthymeleafテンプレートの変更を常に反映する設定している場合、3と4の手順は不要です。ページリロードを行うことで変更したテンプレートが読み込まれます。

HotSwapできない変更

感想

少しコードを修正しただけでもBootRunに1〜2分掛かっていたものが10数秒程度で変更を反映出来るようになったのは良かった。HotSwapについて色々調べて様々な設定方法がありましたが、結果的に必要な設定は少なかったので、費用対効果は良いと思いました。


Holmesではエンジニアを募集しています。興味がある方はご連絡下さい。 lab.holmescloud.com

FirebaseのCloud Firestoreを試してみた

この記事は Holmes Advent Calendar 2020 - Qiita 23 日目の記事です。


こんにちは!株式会社Holmesでエンジニアをしている北原です。

私は、2020年の4月に新卒でエンジニアとしてjoinさせていただきました。当初はSpringFrameworkとThymeLeafで開発を行っておりましたが、現在は弊社で使用している技術であるVue.jsの業務にシフトしてきたので絶賛キャッチアップ中です!

その学習も兼ねて、趣味の範囲で小規模なWebアプリケーションの作成を考えているのですが、「storeのデータを永続化させたいけど、DBとかバックエンドの処理が動くサーバが必要だし、コストがかかるなぁ...」という課題が生まれてきました。

そこで目をつけたのがこのFirebaseです。

Firebaseとは

FirebaseはGoogle社が提供するmBaaS(mobile Backend as a Service)で、DBサーバの管理や保守なしでデータの永続化ができ、そのほかにも様々な機能が提供されています。

その中で今回使用するのはCloud Firestoreになります。

Cloud Firestoreについて

最大の特徴はリアルタイムでデータが同期される仕組みで、接続するクライアント全てにおいて同期を行っているので、変更が瞬時に各クライアントに適用されます。

また、オフライン上でも各クライアント上にデータがキャッシュされており、オンラインに戻ると瞬時に同期されます。

データの保存形態に関しては、ODBMS(Object DataBase Management System)となっています。
Cloud Firestoreの場合は、コレクション呼ばれるものの中にドキュメントが多数存在し、それぞれのドキュメントはデータを持っている。といった具合です。

例えば...

  • コレクション = ドキュメントを管理するフォルダ
  • ドキュメント = フォルダ中の書類
  • データ = 書類に書き込まれた文書

といったようなイメージをすると少しわかりやすいかなと思います。

検証環境

※ npmインストール済です

  • OS : macOS Mojave 10.14.6
  • editor : Visual Studio Code v1.52.1
  • npm : v6.14.8
  • project : Vue 3 ステート管理はVueX

VueにおけるFirebaseの設定

  1. Firebase Consoleにログインします
  2. プロジェクトを追加を選択します

    1. プロジェクト名を決めます f:id:k-kitahara:20201221203428p:plain
    2. Googleアナリティクスを利用するか決めます(利用するのであれば) f:id:k-kitahara:20201221203711p:plain 3.Googleアナリティクスのプロパティを作成するアカウントを選択します f:id:k-kitahara:20201221203812p:plain
  3. 作成したプロジェクトを選択して、トップのウェブをクリックします f:id:k-kitahara:20201221204130p:plain

    1. 利用するアプリ名を決めます f:id:k-kitahara:20201221204205p:plain
    2. Firebaseの設定をコピーします f:id:k-kitahara:20201221204230p:plain
  4. プロジェクトのルートで下記のコマンドを実行して、Firebaseのモジュールをインストールします
    $ npm install firebase

  5. src/main.jsに手順3-2でコピーした設定をペーストし、必要な部分のみ保存します f:id:k-kitahara:20201221205520p:plain

以上で、Firebase利用のための設定は完了です。

データベースの作成

  1. Firebase Consoleにログインします
  2. 作成したプロジェクトを選択して、左側のサイドメニューからCloud Firestoreを選択します f:id:k-kitahara:20201221205915p:plain
  3. データベースの作成を選択します f:id:k-kitahara:20201221205947p:plain
    1. セキュリティの保護ルール設定を選択します(テストモードにすると全ての操作を受け付けるので、初期設定では本番環境モードにしてから、適宜セキュリティルールを書き換えていく形が良いと思います) f:id:k-kitahara:20201221210119p:plain
    2. データ保存先のリージョンを選択します f:id:k-kitahara:20201221210255p:plain
  4. ルールのタブを選択します f:id:k-kitahara:20201221210313p:plain
  5. セキュリティルールをアプリケーションに合った形で書き換えます(アクセスするデータベースのパスに対して条件付きで権限を付与していきます。具体的な記法はこちら。)

コードの記述・画面からの操作

  1. VueXのアクションに、Cloud Firestoreにデータを追加する処理を記述します f:id:k-kitahara:20201221210755p:plain
  2. 画面から、処理を記述したアクションを呼び出すと追加されています!! f:id:k-kitahara:20201221210901p:plain

感想

無料版だと多少の制限はあるものの、DBの構成管理なしでデータの永続化が実現できるのは手軽で便利です!

ここの手順では記載しておりませんが、GoogleFacebookなどの認証も対応しており、それらを通じたアプリケーションのログイン/ログアウト機能を実装できたりするので、Webアプリケーションの構築がよりスムーズになるかと思います。

最後に

いかがでしたでしょうか。

私もまだまだ触り始めたばかりではありますが、今後も少しずつ理解を深めていきたいと思います!

Holmesではエンジニア・デザイナーを募集しております。ご興味がある方はこちらからご連絡ください。

lab.holmescloud.com

lab.holmescloud.com

【AviUtl】図形オブジェクトの座標と連動した数値の表示(スクリプト制御・Lua言語)

この記事は Holmes Advent Calendar 2020 - Qiita 24 日目の記事です。


Holmesの倉島です。趣味でAviUtlというツールを用いて映像編集を行なっています。この度、このAviUtlの機能の一つ「スクリプト制御」に触れたので自身の使用例を紹介したいと思います。

AviUtlとは

フリーの映像編集ソフトで、有志によるプラグイン開発等で高い拡張性が特徴です。

AviUtlについて詳しく解説されている記事があったので詳細はこちら。 aviutl.info

スクリプト制御とは

AviUtlのスクリプト(動作・エフェクト等を操作する効果)はLua言語で書かれています。

ja.wikipedia.org

スクリプト制御はAviUtlの機能の一つで、Lua言語を直接記述して映像(図形やテキスト等のオブジェクト)を操作することができる機能です。

実践

例:図形オブジェクトが動くのと連動してX,Y座標をテキストで表示させる。 下記画像の右下のようなテキストを作成します。(X座標 : Y座標) f:id:t-kurashima:20210108130225p:plain

1. 連動させたい図形オブジェクトにスクリプト制御を付与

図形オブジェクトにスクリプト制御を付与し、入力欄に 

rendouX = obj.x
rendouY = obj.y

と入力。
obj.x で図形オブジェクトのx座標を、obj.yでy座標を取得することができ、それらの値をrendouX,rendouYという変数に代入します。
Luaでは変数名の前に修飾詞を入力しない場合はグローバル変数扱いになります。

f:id:t-kurashima:20210108130337p:plain

2. テキストでスクリプト制御

次にX座標 : Y座標 を表示する為に、テキストオブジェクトの入力欄に

<?
hyouji = rendouX .. ":" .. rendouY
mes(hyouji)
?>

と入力します。
※ <? ~ ?>で囲われている内容は直接テキストとしては表示されず、mes()などの関数を用いて表示されるものがテキストの内容となります。
mes()関数は()の中に指定した文字列を表示することができます。その為mes()の()の中に X座標 : Y座標 を表示することができる文字列を指定してあげればよさそうです。
hyouji という変数にrendouX(1. で設定した図形のx座標) + ":" + rendouY(1. で設定した図形のy座標)を代入し、hyouji をmes()に指定すれば表示ができそうですが、Lua言語の文字列結合は 「+」 ではなく「 .. 」で行います。その為

rendouX .. ":" .. rendouY 

と記述すると文字列結合が行えます。これをhyoujiに代入してmes()に指定します

f:id:t-kurashima:20210108130426p:plain

3.動作確認

現在、タイムライン上には、1.のスクリプト制御を付与した図形オブジェクト と 2.のテキストオブジェクトが存在します。

f:id:t-kurashima:20210108130450p:plain

これで図形オブジェクトを動かすと、テキストが動的に X座標 : Y座標 を表示します。

f:id:t-kurashima:20210108130703g:plain

感想

スクリプト制御を用いると、連動系の動きをとても簡単に作成することができます。
今までオブジェクトに一つずつ手作業でパラメーター調整していた苦労ともオサラバです。

最後に

Holmesはエンジニア・デザイナーを募集しています。 興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com

弁護士からみたプロダクト開発の難しさと面白さ

はじめまして。Holmesの開発本部・PMチームの酒井です。

10年弱に亘り弁護士として働いたのち、昨年Holmesに入社してからはCEO室室長として主に経営企画やセールス的な仕事をしてきました。プロダクト開発との関係では、Holmesの事業領域である契約業務のドメインエキスパートとして関与してきたのですが、先月より正式に開発本部・PMチームに異動となり、PMM(プロダクトマーケティングマネージャー)を拝命しました。つまり、プロダクトマネジメントについては完全な素人です。

 

今回は、そんな初心者PdMが、プロダクト開発に潜む溝とそれを克服するために実践していることをまとめてみました。

部門間の言葉の溝をなくす

まず、セールス側で働いていたときには、開発陣から発せられる言葉の意味は全く理解できていませんでしたアジャイル?スプリント?レビュー?インクリメント?何となくわかったつもりでいましたが、開発で働き始めたら何もわかっていなかったことがわかりました。無知の知です。また、同じ言葉なのに全く違う意味で使われている場面もありました。例えば、「リリース」という言葉を、開発は内部リリースの意味で使い、営業は外部リリースの意味で解釈し、マーケはプレスリリースの意味で捉えていました。コミュニケーションコストが高くて仕方ありません。

 

このように、言葉の理解や使い方一つとっても、開発とそれ以外の世界には大きな溝がありますが、この問題を克服するためには、一つひとつの言葉を大切に定義して、その定義を徹底するという地道な作業をしなければならないと思っています。ちなみに、弁護士という生き物は、言葉の定義に並々ならぬこだわりを持つ人種なので、そのバイアスがかかっているのかもしれません。(ちなみに、法律や利用規約においては、第1条が目的、第2条が定義と相場が決まっています。)

 

フィードバックの背後にある課題を想像する

Holmesでは、ユーザーの皆様から寄せられた全ての要望やクレームを、「顧客要望」としてセールスフォースに登録して管理しています。MVP(Minimum Viable Product:実行可能な最低限のプロダクト)の形で市場に投入するのは、ユーザーの皆様からのフィードバックをいただくためと言っても過言ではありません

 

ただ、ユーザーのフィードバックを、きちんと理解せずに言葉通り受け止めるだけでは、其の背後にある本質的な課題を見逃すおそれがあります。「もし顧客に、彼らの望むものを聞いていたら、彼らは『もっと速い馬が欲しい』と答えていただろう」とか、「ドリルを買いに来た人が欲しいのはドリルではなく穴である」といった格言が示すとおりです。ユーザーの言葉を理解するためには、ユーザー自身のことを理解しなければならないと強く感じます

 

課題を理解するために、まずはユーザーを理解する

課題を特定するためには、前提として「ユーザー」をきちんと理解しなければなりません。そして、ユーザーの理解は、企業レベル・個人レベルの両方が必要です。企業としてのユーザーの規模、業種・業界、ビジネス構造、組織図はどうなっているのか。個人としてのユーザーの、部署、立場、日々の業務はどうなっているのか。一人ひとりのユーザーの視点に着目し、その一人の人にとっての世界を想像しなければ、自分たちが誰の、どのような課題に取り組まんとしているのか、迷子になってしまいます。

 

ホームズクラウドは、契約業務に関わらず全ての人の課題解決を目指していますが、契約業務には、法務部門だけでなく、事業部門やその他の管理部門、そして取引先などの様々な当事者が関与します。その分、ホームズクラウドのユーザーも多岐にわたり、必然的にユーザーの課題も多種多様です

 

このような複雑・多様なユーザー課題を深堀りするために必要となるのがドメイン知識です。Holmesの開発組織では、ドメイン駆動設計(DDD)を取り入れています。Holmesには、私以外を含め、弁護士経験者が3名、司法試験合格者が1名、法務部経験者が1名いるのですが、これらのメンバーがプロダクトオーナーとスクラムメンバーにドメイン知識を共有する取り組みを進めています。開発が極めて専門性の高い領域であるのと同じように、契約業務も専門性が高く、独特の専門用語が飛び交う領域です。この2つの異なる世界線が交わるよう、共通言語を作っていくことこそ、Holmesのプロダクトマネージャーとして求められる役割なのではないかと考えています

 

補論:弁護士業務との近似性

実はこの思考回路、弁護士がクライアントからの質問を受けるときに求められる姿勢と全く同じということに気づきました。たとえば、クライアントから「この契約書をレビューしてください」という依頼をうけたとき、契約書の文字面だけを見て、契約書の中の世界だけを見てレビューすることも可能です。ただ、実は、その契約によってやろうとしている取引自体が、法律上問題のある取引であるような場合もあります。だからこそ、弁護士は「このクライアントからの直接の依頼は契約書のレビューだけど、そもそもの問題点は取引の仕組みそのものにあるのではないか?」という想像が求められます。

 

また、裁判における事実認定の過程にも似ています。裁判では、「証拠上明らかな事実から、神様しか知り得ない客観的な事実を『推認』する」という過程を経て、事実認定が行われるのですが、目に見える事実を積み重ねて、過去の経験則(前提知識)に照らし合わせながら、目に見えない「顧客の本質的な課題」の仮説にたどり着くという開発における営みと親しいものに感じます。

 

今後の目標

ユーザーの本質的な課題を解決できるプロダクトを世の中に生み出すためには、開発言語、セールス言語、ドメイン知識という(同じ日本語のはずなのに)全然伝わらない3つの言語をうまく融合させることが必要不可欠です。そのためには、開発メンバーがセールスの言語を学び、セールスメンバーが開発の言語を学び、そして両者がドメイン知識を身につけることが必要になります

 

持っている知識や経験が全く違う人たちが、相互理解を深めていくというのは簡単ではありません。そこのドメイン知識まで必要となると非常に高いハードルのように思えます。しかし、だからこそ、開発言語・セールス言語・ドメイン知識が三位一体の組織を創ることができれば、その組織そのものがHolmesという会社の競争優位の源泉になっていくのではないかと思っています。

 

Holmesでは、法務での経験をプロダクト開発やセールスに活かし、事業の中心として働きたいという人材を募集していますので、いつでもお気軽にご連絡ください!

TestCafeにGaugeを組み合わせてBDDできないか試してみた

社内でE2Eテストツールとして、TestCafeの話題が出たため、前回の記事で試したGaugeとの組み合わせでBDDのようにテストを実行できないか、検証してみました。

実行環境

名前 バージョン
OS Windows 10 Pro 64bit バージョン2004
Node.js 14.15.2
Yarn 1.22.5
TestCafe 1.10.0
Gauge 1.1.6

なぜTestCafe単体ではなく、Gaugeと組み合わせようと思ったのか

TestCafe単体ではテストは簡潔に記述できるものの、実際の運用に乗せることを考えると、ログインや特定の状態への遷移といった、よくある処理の共通化は必要であると思います。

TestCafeはメソッドチェーンでテストを簡潔に記述できますが、共通で前処理を行おうと思うと、ツールのサポートとしてはFixtureのbeforeEachメソッドによるフィクスチャ単位の共通化しか見つけられませんでした。

Page Object Patternでも記述できるため、共通処理はPage Objectとして切り出し、フィクスチャやテストから実行することはできそうですが、BDDのように明示的に前処理を記述することは、TestCafe単体ではできないようなので、GaugeないしはCucumber.jsといったツールと組み合わせることで、明示的な処理の共通化ができるか確認できればと考えました。

また、前回はGaugeとJavaの組み合わせを試したため、今回はGaugeとJavaScriptの組み合わせで、使用感に違いがないかも確認できればと思い、Gauge+TestCafeで試してみることとします。

環境構築

TestCafeのインストール

devexpress.github.io

npmまたはYarnでインストールします。*1

インストールが完了したら、 testcafe -v でバージョンが確認可能です。記事作成時のバージョンは、1.10.0でした。

また、 testcafe -b で、利用可能なブラウザ一覧を確認できます。

# npm
$ npm install -g testcafe

# Yarn
$ yarn global add testcafe

# バージョン確認
$ testcafe -v
1.10.0

# 利用可能なブラウザ確認
# Firefox, Google Chrome, Microsoft Edge(Chromiumベース)、およびInternet Explorer 11と旧Microsoft EdgeがインストールされたWindows 10では、以下のように表示されました
$ testcafe -b
firefox
chrome
ie
edge
edge-legacy

Gaugeのインストール

前回の記事 と同様の手順で、Windowsインストーラーをダウンロードし、Gaugeをインストールします。

記事作成時のバージョンは、1.1.6でした。

Gauge+TestCafeのサンプルプロジェクトのダウンロード

getgauge-examples/gauge-testcafe にサンプルとなるGitプロジェクトがあったため、ZIPダウンロードおよび展開します。

npmまたはYarnで、依存モジュールのインストール後、テストを実行します。

# npm
$ npm install && npm test

# Yarn
$ yarn install && yarn test

TestCafeが起動し、Google Chromeのウィンドウが開きます。

起動時の画面

...が、以下のエラーで失敗しました。

Failed Step: Search for "github TestCafe"
Specification: specs\example.spec:6
Error Message: Error: Timed out
Stacktrace:
Error: Timed out
サンプルテストの修正

specs/example.spec がテスト仕様、 tests/step_implementation.js がテスト実装になります。

テスト内容を確認してみると、以下のようになっていました。

  1. Googleを開く
  2. 「github TestCafe」で検索
  3. 検索結果の最初のリンクのテキストに「GitHub - DevExpress/testcafe:」が含まれるか検証

まず、検索する文字列の入力欄を input[title="Search"] で取得しようとしているものの、日本語環境ではtitleが「検索」になっているようです。

また、GitHubの検索結果のリンクテキストが、記事作成時点では「DevExpress/testcafe: A Node.js tool to automate end ... - GitHub」となっているため、検証も失敗します。

それぞれ以下のように変更し、テストを再実行すると成功しました。

  1. 検索文字列の入力欄取得を input[title="検索"] で行うよう step_implementation.js を変更
  2. example.spec から渡される検証用の文字列を "GitHub - DevExpress/testcafe:" から "DevExpress/testcafe:" に変更

前回と同様、 reports/html-report/index.html にレポートが出力されます。

f:id:h-yamamoto_holmescloud:20201225124621p:plain
Gaugeのテストレポート

実装

いきなり躓きましたが、気を取り直して実装していきます。

テストするブラウザの変更

初期状態では、Google Chromeでのテストのみ実行されました。

コマンドからTestCafeを実行する場合、 testcafe ブラウザ名,ブラウザ名,... JavaScriptテストファイル でテストするブラウザを追加できるため、それっぽい設定はないかと確認したところ、 tests/testcafe_init.jsbrowsers('chrome') という設定がありました。調べてみると、APIを使ってJavaScriptから実行できるようです。

browsers(['chrome', 'ie', 'edge']) のように記述すると、各ブラウザのウィンドウは最初に開きますが、先頭のブラウザにのみテストが実行され、それが終わった段階でテスト終了と判断されます。

おそらく、オーケストレーションを行うGaugeと、テストを実行するTestCafeのライフサイクルの違いが原因かと思います。

ひとまず、Google Chrome以外にも、 browsers('ie')Internet Explorerbrowsers('edge')ChromiumMicrosoft Edgeでテストを実行できることは確認できました。

テスト仕様の追加

前回と同じMarkdownを、 specs/search.spec に保存しました。

テスト実装の記述

当初は tests/search_steps.js を追加して検証しようとしたのですが、GaugeではJavaScriptでテストを実装する場合、 tests/step_implementation.js にしかステップを記述できないようです。

ステップ内で実行する関数の内容を別ファイルに書いてimportしたりはできそうですが、ひとまず tests/step_implementation.js に以下を追記します。

なお、変数 _Selector は、それぞれTestCafeのTestController、およびSelectorになります。

step('検索エンジンのURL <url> を開く', async (url) => {
  await _.navigateTo(url);
});

step('検索文字列入力欄 <inputSelector> を取得する', async (inputSelector) => {
  const searchTextInput = Selector(inputSelector).with({ boundTestRun: _ });
  gauge.dataStore.scenarioStore.put('searchTextInput', searchTextInput);
});

step('<searchText> で検索する', async (searchText) => {
  const searchTextInput = gauge.dataStore.scenarioStore.get('searchTextInput');
  await _.typeText(searchTextInput, searchText);
  await _.pressKey('enter');
});

step('検索結果ページのタイトルが <title> であることを確認する', async (title) => {
  const titleElement = Selector('title').with({ boundTestRun: _ });
  const pageTitle = await titleElement.innerText;
  gauge.message(`検索結果ページのタイトル: ${pageTitle}`);
  await _.expect(pageTitle).eql(title);
});

TestCafeでは通常 fixturetest で記述していきますが、Gauge+TestCafeでは、実行時にGaugeのシナリオがTestCafeのfixtureに変換されるようです。

前回Javaで記述した部分をそのままJavaScriptに置き換えただけなので、TestCafeの記述としては洗練されていないですが、この状態で yarn test でテストの実行ができました。

感想

GaugeとTestCafeの組み合わせは、あまり良くはない印象です。

感じたデメリット

GaugeのJavaScriptによるテスト実装では、ステップを step_implementation.js にしか記述できないようです。私の調査不足かもしれませんが、ドキュメントをざっと読んだ限り、変更方法などは見つけられませんでした。

Gauge+TestCafeのサンプルプロジェクトでも、 step_implementation.js から test_controller_holder.js をimportしているため、実装を分割することは可能ですが、テストのステップをすべて単一ファイルに記述することになると、管理が煩雑になりそうです。

また、TestCafeの複数ブラウザによるテストや、並列テスト実行が活かせなくなりました。こちらはTestCafeのメリットを打ち消してしまっています。

TestCafe単体でできたことが、Gaugeと組み合わせたことでできなくなるのであれば、相性が悪いと言って差し支えないかと思います。

Gauge+Javaとの使用感の違い

Gauge+Javaでは複数ファイルにステップ記述が可能なため、そちらと比較するとGauge+JavaScriptは使い勝手が悪く感じました。

GaugeのData Storeに相当するctxがTestControllerに用意されていたりと、TestCafe自体が高機能ということもあり、Javaと組み合わせたときほど利便性の向上も感じませんでした。

TestCafeでBDDするための代替手段

TestCafeをGaugeと組み合わせるのは難しそうなので、Cucumberなど他のツールとの組み合わせが可能か調べてみました。

3年ほどOpenされているTestCafeのissueで、CucumberとTestCafeの統合についての要望が上がっており、そこからたどったissueの Cucumber Integration with Testcafe removed from roadmap? にて、Cucumber Integration がロードマップから削除されたこと、および gherkin-testcafe の使用が推奨されていました。

gherkin-testcafe を用いれば、Gherkin構文でTestCafeのテスト記述および実行ができるため、現時点ではこれを使うのがTestCafe+BDDには最適なようです。

実運用ではPage Objectとしてテスト対象のページをクラス化し、それをGherkinで記述したテスト仕様クラスから操作するのがいいかと思います。

総括

Gauge+Javaではかなりのメリットを感じられたのですが、Gauge+TestCafeではデメリットが目立つ結果となりました。

TestCafe自体の有用性は確認でき、またPage Object Patternによる記述ができることも確認できたため、今後はPage Object Patternによる実装や、 gherkin-testcafe との組み合わせの検証を行いたいと思います。

最後に

Holmesではエンジニア・デザイナーを募集しております。ご興味がある方はこちらからご連絡ください。

lab.holmescloud.com

lab.holmescloud.com

*1:Node.js、およびYarnのインストールについては割愛します