オープンソースのフレームワーク「Karate」

伊藤宏幸氏(以下、伊藤):ここで私たちが取った方法は、もう1回、先ほどのProduct Discoveryを適用してみたんです。ここのChannel Gatewayのチームのみなさんから、いろいろヒアリングしながら「こういったツールを導入したらどう?」といろいろと試していって、結局落ち着いたのがKarateというオープンソースのフレームワークでした。

このKarateというのは、APIのテストに特化したオープンソースのフレームワークです。先ほどお見せした、Cucumberとかで使っているGherkinのフォーマットでテストが書けます。あとはAPIに特化しているので、RESTのAPIであれば簡単にテストを書けますし、gRPCやThriftについても、カスタマイズすればすぐにテストが書ける状態になっています。

あとはみなさんTechnology Radarというレポートをご存知ですか? このレポートを知らない方向けに説明しますと、リファクタリングの本とかで有名なマーティン・ファウラーさんが所属しているThoughtWorksという会社が、半年に1回リリースしている、世界中のソフトウェア開発やプラットフォーム開発方法論などの技術トレンドをまとめたものです。

このKarateは、その中でもAPIテストをするのにおすすめされているツールです。このKarateでテストを書くとどうなるかというと、こうなります。これは先ほどのJUnitのコードと同じ内容です。どう違うか。

下が先ほどのコードですね。

どこがどう違うかわかりますかね?まずはコードの量がギュッと縮まったのがわかりますか? つまりコード量が少なくなります。かつGivenやWhenといった先ほどの書式で書いてあるので、そんなにプログラミング言語に詳しくなくてもポイントがわかるわけですよ。例えばGivenで、このAPIを呼ぶんだね。こういうパラメータをセットするんだね。postで呼んだらHTTPの200が返ってきたらOKということだね、ということがすごく簡単に読み取れるわけですよ。

このKarateをチームのニーズに合わせて採用して、先ほどJUnitで書いたテストのコードを全部書き換えました。これはただ書き換えるだけではなくて、Channel Gatewayの開発チームと我々SETが一緒になりながら、一個一個技術的あるいはテストの設計、あるいは仕様的にテストをしづらいところにぶち当たっては、一緒にミスをしながら、この場合はこういう実装をしたらいけるかもしれない、あるいは「ここはヘルパーメソッドとか、あるいは必要だったらプラグインでも作ろうか」みたいなことをお互いに意見を出しながら問題を乗り越えてきました。こんなことを約3ヶ月ほど一緒になってやりました。

その結果どうなったか。実はこのChannel Gatewayというチームは、以前はよく障害を起こすチームと言われていましたが、今はAPIテストのモデルチームになっています。どういうモデルかというと、まずこのKarateでテストスクリプトを書いてE2Eテストをやった結果ですね。本番障害が実際に30パーセントほど減っています。さらにこの30パーセントという数字は、リリース前に適切なテストをやることで、リリース前に適切に検知・除去できたバグの数は含みません。つまり、実際にはもっと多くの障害を事前検知できたと言えます。

あとは、こういうKarateで書いたテストスクリプトが既にあるので、他のチームやサービスから「APIのテストをしたいんですが、どうしたらいいですか?」と相談をもちかけられたら、このチームのGitHubリポジトリをそのまま見せれば実際に済んじゃうんですよ。というのも、そこの機能をGitHubリポジトリに、必要なテストのパターンと動かしたものが全部書かれていて見えるからです。

LINEの場合は、興味をもった人がわりとそのコードのサンプルを見せたら自分たちでやってくれるという社風があるので、本当にモデルを見せるだけでけっこう施策の余地が広がるというような素地があります。そういう意味でモデルになっています。

今ではこのチームは、開発チームメンバーの全員、これはプロダクトマネージャーも含めてKarateでテストスクリプトを書けるようになっています。加えて、機能追加したものについてはすべて必ずKarateでテストスクリプトを書いて、それでリリースというようなスタイルになっています。

ここのポイントを最後に。みなさん、これは英語圏の方はご存知だと思いますが、英語のcompassionという言葉の意味をご存知でしょうか。これは共感とか思いやりという言葉になります。たまたま先日この言葉の語源を知ることができました。ラテン語のcompatioという言葉が語源らしいです。

このcompatioとは何かというと、「一緒に苦しむ」という意味なんだそうです。つまりどういうことかというと、一緒に苦しむことで、開発者やSETが同じ目線に立って問題に向き合うことで、目線を合わせることで一緒に問題解決をすることで、お互いに共感や思いやりを持ちあうことで施策を広めていくことができる。

つまり、こういうことが私たちがChannel Gatewayで一緒に痛い目にあったことで得られたもの。かつ、Channel Gatewayが今モデルチームとなっている結果につながっているのではないかと思っています。

チームの育成の重要性

時間が押し始めているのでサクッといきましょう。次にチームの育成の重要性についてですね。ここでみなさんの意見をお聞かせください。ちょっと難しいのと、さっき時間を取りすぎたので今回5分と書いてあるんですけど、3分でお願いします。「マイクロサービスをテストするとき、どういうことが難しいですか?」

マイクロサービスのテストは何が難しいですか?問題自体が難しいかもしれないですけど、お聞かせください。

(参加者書き込み中)

今回難しいお題なのはわかってます。「うちはマイクロサービスやってないよ」というところがいるかと思いますので、それはそれでもいいと思います。

「複数のオーナーシップがあって技術が違うよね」、確かにそれはそうですよね。マイクロサービスは各サービスで自分たちで好きな言語でサービスを作っていることがわりと多いです。そうなるとそれを一緒にテストするのは難しいですよね。ありがとうございます。

やっぱり問題が難しかったのか、あまり出てこないですね。では時間も押しているので1回ここでストップしまして、セッションに戻りましょうか。ちなみにアイデアがあるようでしたら、全然書き込んでいただいてけっこうです。

この問題をなぜ出したかというと、私たちが今絶賛取り組んでいる問題だからです。私たちも同じ問題にぶつかっていて、私たちがこの問題で感じたブロッカーは、一言で言うとスキル不足でした。これは開発者やテスター、QAだけではなくて、我々SET自身のスキル不足も認識しました。私たち自身も、マイクロサービスの知識を当時はしっかりもっているわけではなかったのです。ですから、けっこう的外れの施策を出していたことも当時はありました。

そこで私たちが取った施策は、スキル不足だったら自分たちでカバーすればいいじゃないということで、メンバー、チーム、組織を一斉に強化するためのアイデアというのがここのポイントです。

Learning Sessionという取り組み

ここで私たちSETがやったことは、Learning Sessionという取り組みでした。これはすごく簡単に言いますと、業務時間中に行う勉強会です。

みなさんの中で、モブプログラミングをやられる方はいらっしゃいますかね? そのモブプログラミングを作った人の1人、Chris Lucianさん、右の方ですね。この方から論文とか経験談とかを2年前のカンファレンスで直接教えてもらって、それにインスパイアされてトライしてみたのが、私たちのチームでの取り組みです。

どういうことをやったかというと、こういう感じでトライしてみました。まず基本的に毎日30分から60分ぐらい、勉強の時間を取ります。それを業務時間中にやります。業務にプラスになるトピックであれば、何でもOKとしました。

基本、みんなでモブプログラミングの形式でトライすることにしました。ここでは「君、そんなのもわからないの?」という発言は一切せず、批判とかはしないで「そういうアイデアがあるんだね、いいね」みたいな感じで、みんなで楽しむみたいなことを旨として、これを続けてきました。

実際にどういうことをやったかというと、こういうことを学習しました。まず、今はコンテナオーケストレーションツールのスタンダードになっているKubernetes。あとは先ほどのKarate。そしてUI系のVue.js。

また、IntelliJをよく使うのでショートカットの使い方ですとか、あとはお互いのメンバーの好みとか技術スタックを知るためのDrucker Exercise。あとはマネージャーや他のチームとかにアピールするためのグッとくるレポートの書き方を教えあったりしました。

こういうことをだいたい2、3ヶ月続けていった結果、何が起こったかというと、私たちはSebas Reportという新しいツールを発明しました。

このツールは何かというと、マイクロサービスで問題が起こったときに、マイクロサービスのどこで問題が起こったのかをピンポイントで検知・報告してくれるレポートツールです。

マイクロサービスを簡単に説明すると、例えばAPIが1つあるとすると、その裏に複数のサービスがあったりするわけですよ。例えばお金の計算だけをやるところとか、商品をピッキングするところとか、だいたいそういうサービスが裏であるわけです。

APIを呼んだだけで、そこから500とか503(といったエラーコード)だけ返ってきても、適宜にロギングをしていないと、中のどこのサービスでこけたかわかりづらいんですよ。それを問題が起きたのはここ、と示せるようにしたのが、このSebas Reportです。

これによって、このMTTR(Mean Time To Recovery)、つまりはサービスのリカバリーという意味ですが、問題を発見してからサービスを復旧させるまでの時間を縮めることができました。私たちは、マイクロサービスの難しさとか複雑さとかをある程度コントロールできるようになってきました。

ツールのイメージはこんな感じです。基本はJUnitとかCucumberとかのレポートツールと同じです。なのでグリーンが成功、レッドが失敗ですね。この赤いところをクリックすると、このKarateのシナリオのどこでミスしたかがわかるわけです。ここをクリックすると、HTTPのリクエストとレスポンスの詳細が見れたりします。

ここにTRACE IDというのを表示できるようにしています。これをクリックすると何が起きるかというと、ZIPKINというツールを使いまして、このAPIの裏で動いているマイクロサービスの依存関係や、その中でどこがエラーになっているかというのを一目瞭然に見えるようにしてくれています。

この場合ですと、APIの中ではFRONT、TODO、USERという順番でリクエストを呼び出しているんですけど、これを見ると(TODOが)エラーになっているから、結果的にエラーだというのがわかります。

このレポートで、エラーが起きているのがどこかというのがわかるだけでも、十分問題解決が早くなりますよね。このツールは、先ほどのLearning Sessionで私たちが学習したものをふんだんに取り入れて、1からフルスクラッチで作り上げたものです。

例えば画面はKarateのレポートから、ZIPKINというオープンソースのビジュアライズツールを組み入れて、あとはUIはVue.jsでイチからフルスクラッチで作っています。さらにバックエンドでKubernetesを活用したりしています。

このSebas Reportを導入した結果どうなったかと言いますと、はっきりとMTTRは改善しました。MTTRの中でも、とくに障害検知のところだけに絞っても、下手したら1週間ぐらい掛かっていたのが少なくとも2時間ぐらいで検知できて、どこのサービスで問題起こったからそこのサービスを担当した人に即連絡、ということができるようになりました。そうなれば当然サービスが止まる時間が短くなるから、サービスが稼働できる状態、レジリエンスを高めることができます。

この資料を書いたのが今年(2020年)の4月時点ですが、この時点でも既に5チームがこのSebas Reportを使い始めてくれています。なので、ここではLearning Sessionを使って私たちが適切なスキルを得て、それで今の問題に対するソリューションとしてSebas Reportというものを作りました。

それを受けて開発者やテスターのみなさん、あるいはプロダクトマネージャーが、問題解決の改善を実現できて、それによって、またここから新たなマイクロサービスの問題を解決するソリューションにつながっています。なので、私はこういう育成という手法でSebas Reportを作りましたというのが、ここのポイントでした。

私たちが直近で取り組んでいる3つの施策

ちょっと時間が押しているのですが、今私たちが直近で取り組んでいる施策3つを本当にサクッと紹介します。まず1つ目はAyaperfという、自作のパフォーマンステストツールです。これは、LINEで実施しているサービスで必要な負荷を実際にかけられるツールが、世の中のOSSのツールになかったので自作で作っちゃいました。

Kubernetesを活用して、適切な負荷を与えられるようにしました。かつ言語は多くのチームが好んで使っているKotlinで書いています。その結果、GrafanaやElasticsearchで負荷を見れるという仕組みを導入しました。

次にDesign Sprint。これはProduct Discoveryと同じで、スタートアップなどで使われるユーザーの本当のニーズを確認するための手法の1つです。これを私たちはテスト自動化の改善やテストに関する問題解決に適用しました。

さらに、今はTestable Infrastructureというものを構築しています。これはみなさん、Immutable Infrastructureという言葉を聞いたことはありませんか? それのテスト版です。よくテストをやるときに「開発環境とステージングと本番で環境差分があるのでテストをしてもあまり意味がないんじゃない?」とか、適切なテストをできなくてバグを検知できなかったとかありませんか?あるいはテストデータを共有しているので、データのバッティングを避けるためにテストがしにくいとか。

こういった問題を解決するために、テストが必要なときだけ各テスト環境のコピーをKubernetesで作り上げて、そのテストをします。それでテストが終わったらそれを捨てちゃう。それがまた必要になったら同じものをイチからまっさらな状態から復元することで、テスト環境自体をいつでも再利用できるものとして提供しようという取り組みです。こういったものを我々SETがやっている最中です。

私たちSETが取り組んだ3つのこと

さて、私のセッションの締めくくりです。私たちはこういったいろいろな施策、あるいはいろいろな問題に取り組んで、それをどうやって解消したかというアイデアをみなさん、あるいは社内でもこういうのを定期的に共有したりしています。

こういうことをし続けていった結果、例えば私たちが宣伝しなくてもだいたい関心のあるチーム自ら「これおもしろそうだよね」と言ってくれて、先ほどのSebas ReportとかAyaperfを使い始めてくれているチームが今増えています。

また、私たちのこの失敗談をベースに、自分たちでプロジェクト問題とかテストに関する問題を自分たちで解決してしまったというチームも今、着実に増え始めています。なので自分たちの関わっているところだけじゃない、自分たちがやったことを受けて他のチームが「おもしろそうだ」「ちょっとトライしてみよう」みたいなかたちで、自然派生的なかたちで自律的に広がっていくということが、今は少しずつですが、でき始めているかなと思います。

最初に話したように、新しい施策をやるときには必ず何らかの反発とかを受けるものです。そのような状況は、今私がLINEのSETの活動として説明させていただいた通り、適切な方法でうまくやればすばらしい成果に作り替えることが可能です。

私たちSETではとくにやったのがこの3つでした。適切な支援を得る。開発チームと一緒に痛い目に合う。「同じ釜の飯を食う」と、先ほどTwitterにもありました。そういうことです。あとは自然発生的に施策を広める。こういうところを私たちSETはやっていましたし、やっています。

ただ、これは必ずしも、今回参加している全員に当てはまる解決策ではないと思っています。これはあくまで、私たちLINEのSETがぶち当たったからこそ、トライしてうまくいったものをリストアップしてだけとも言えます。つまり何が言いたいかと言いますと、みなさんの環境に合った、みなさんの開発環境とかチームに合った解決策が、それぞれあるはずです。

なのでそれは、いろいろ試してみて初めてわかってくるところがあると思います。今回の我々SETの活動で、基本的にやって失敗したものの中から、うまくいったものをヒントとしてみなさんに共有いたしました。同じ理屈でぜひ、みなさんにもいろいろと実験をしてほしいんですね。みなさんの会社とかチームに適した解決方法をぜひ、実験しながらうまくいったものを出してもらいたいと思います。

ぜひAgile2021で共有を

そしてそういううまくいったアイデアを、私は今回このAgile2020でプロポーザルが通って登壇の段取りまでいったんですが、コロナの影響でイベント自体がキャンセルになってしまったので、結局今回は登壇ができなくなってしまいました。ただ、来年このイベントはやるそうです。私はAgile2021にもプロポーザルを出そうと思っています。

ぜひ今回参加していただいているみなさんには「私たちはこういう問題があって、こう解決しました」「こういう実験をやってこれがうまくいったよ」みたいなアイデアを、ぜひこの来年のAgile2021でお互い共有し合いませんか? そしてお互いの課題解決のスキルを一緒に高めていきませんか?

では私からは以上になります。どうもご清聴ありがとうございました。

司会者:はい、伊藤さんセッションありがとうございました。また、視聴者みなさんもディスカッションタイムでのTwitterのコメントをありがとうございました。

ではここからQ&Aタイムに移るんですが、みなさんどなたかクエスチョンありますか? けっこうみなさんハッシュタグでいろいろと書いていただいたので、その辺をあとで楽しくじっくりと振り返って読ませていただければなと思います。先ほど伊藤さんがおっしゃったようにそれぞれのみなさんの開発環境で課題感は違うと思いますので、「こういったときはどうなんだ?」とか、いろいろざっくばらんにお答えできればなと思うんですが、1問いただきましたね。

伊藤:ありがとうございます。「Channel Gatewayのテストではユニットテストは存在していたのですか?」という質問ですね。こちら回答としては、ユニットテストは存在はしていました。ただ、ユニットテストとしては当時機能はしていませんでした。というのも、ユニットテストは普通アサートとかしますよね?

ところがその当時のChannel Gatewayのユニットテストは、System.outとか標準出力しか書かれていなくて、アサーションが一切ありませんでした。つまりユニットテストは役に立っていなかったということですね。そこを含めてこの事例では改善をしていまして、今ではユニットテストもあります。ただ、今回はとくにAPIテストにフォーカスをして事例を紹介いたしました。

司会者:ありがとうございました。