こんにちは。
LIFULL HOME'S事業本部QAグループの木住野(きしの)です。
本記事は3月7,8日の2日にわたり開催されたJaSST’18 Tokyo1日目の参加レポートです。
前回の記事ではイベントの規模感や会場の雰囲気が伝わったと思いますので、本記事では1日目の講演内容についてご紹介いたします。
Advances in Continuous Integration Testing at Google
登壇者:John Miccoさん (Google)
資料 : Advances in Continuous Integration Testing at Google – Google AI
簡単に要約すると以下のような内容でした。
- Googleでは420万ケースの自動テストがある
- 修正したソースコードの影響範囲を自動分析し必要なテストを実行している
- テスト結果をすべてデータベースに保存している
- 実行するテストの選択や実行のスケジューリングも自動化している
保存されたデータを用いてFlakyなテスト(不安定なテスト)の結果を分析し必要な情報を開発者にフィードバックすることでプロダクトの品質を維持している
例) 前回は成功したケースが今回失敗したら安全ではないと判定され、開発者へフィードバックされる
感想
私の担当領域も自動テスト、CI/CD部分なのでとても楽しみにしていた講演でした。
Flakyなテストについての考察は弊社でもすでに実践済の部分もありましたが、参考になる部分が多くありました。
以下資料には載っていませんがQ&Aなどで聞けた興味深かった点です。
- Googleの開発者は自動テストコードの実装スキルが求められる
- 手動テストはない(ユーザビリティテストや外国の翻訳部分のみ手動でテストしている)
- 手動テストのコストとバグを流出するリスクのバランスを決めて経営陣を納得させた上で自動テストのみで品質を担保している
- 新規事業でも基本的に手動テストはない
会場からは手動テストがないことについて質問が集中していました。(みなさん信じられなかったようです。)
また、テスト結果の分析に当たり前のように機械学習を用いている点にGoogleの基礎的な技術力の高さを実感しました。
コードを書きながら学ぶテスト駆動開発 (チュートリアル)
登壇者: 和田 卓人さん (タワーズ・クエスト株式会社)
資料(当日の内容に近いもの): https://speakerdeck.com/twada/tdd-live-in-50-minutes
こちらはテスト駆動開発の翻訳やワイルド・サバンナ(ライオンのアスキーアート)で著名な和田 卓人(t_wada)さんが実際に教えてくれるという個人的にはとても贅沢なセッションでした!
テスト駆動開発(以下TDD)の概要、進め方、勘所を説明していただいた後に、
デモとしてTDDライブコーディングを見せながら更に実践的な考え方や細かなテストケースの実装方法を教えて下さいました。
その後、参加者でペアプログラミングを行いTDDを実践するという内容でした。
感想
TDDやコンポーネントテストの実装についてより深く腹落ちさせることができました。
また、TDDのRed→Green→ Refactoringで実装を進める心地よさを味わうことができました。
以下印象に残った点です。
テストコードは「1. 準備 , 2.実施, 3. 検証」の順で実行されるので、その順で実装をしようと思うかもしれないが3の検証から実装するのが良い
検証から実装することでテスト対象の機能の役割や動きが明確になるからです。
1 assert 1 test(1テストケースメソッドには1つの検証処理)がオススメ
1テストケースに複数検証処理を入れると以下のデメリットが有るからです。
- 複数の検証があるとテスト結果からどの検証が失敗したのか判断しづらくなる
- 失敗した検証の次の検証は実施されない(Failしても次の検証を実施できるフレームワークもあります)
TDDは不安と自信とコードとの間合いを測る技術
実装に自信がない機能に対してはテストが多くなったり、自信があると最小限のテストコードで進むことができる
ただし、基本は一歩ずつ機能を確認する
最初のうちはミューテーションテストをしながらテストが期待通りに動くか確認しながら進める
テストが想定通りに失敗しないとそもそもの前提が崩れてしまうため、確認する必要がある。
ミューテーションテスト(ミューテーション解析)とは・・・ ミューテーション解析 - Wikipedia
テストコードを構造化したり、適切に説明を追加することで対象コードの仕様を表す資料になる
他の開発者に引き継ぐ場合や将来自分が改修する場合などに重要になります。
# 構造化され、説明が追加されているテストコード例 @DisplayName("FizzBuzzクラス") class FizzBuzzTest { private FizzBuzz fizzbuzz; @BeforeEach void 前準備() { fizzbuzz = new FizzBuzz(); } @Nested class convertメソッド{ @Nested class _3の倍数の時Fizzを返す { @Test void _3を渡すと文字列をFizzに変換する() throws Exception { assertEquals("Fizz", fizzbuzz.convert(3)); } @Test void _99を渡すと文字列をFizzに変換する() throws Exception { assertEquals("Fizz", fizzbuzz.convert(99)); } } } # 以下省略
構造化した場合のテスト結果:
# 構造化されておらず説明もないテストコード例 class FizzBuzzBadTest { private FizzBuzz fizzbuzz; @BeforeEach void 前準備() { fizzbuzz = new FizzBuzz(); } @Test void _3を渡すと文字列をFizzに変換する() throws Exception { assertEquals("Fizz", fizzbuzz.convert(3)); } @Test void _99を渡すと文字列をFizzに変換する() throws Exception { assertEquals("Fizz", fizzbuzz.convert(99)); } # 以下省略
構造化しない場合のテスト結果:
まとめ
どのセッションも魅力的で全てのセッションに出たかったです。
各社の最新のソフトウェアテストの知見や技術、そして熱気に触れられてとても良い刺激になりました。
弊社の自動テストやテスト文化、スキルはまだまだ改善の余地があるので、
改善してよりよいサービスをより早く届けられる仕組みを作りたいと思いました。
また、その成果をJaSSTで発表して、業界へ還元していきたいと思いました!
最後に
エンジニア各職種の中途採用募集中です!
もちろんQAエンジニアも募集しています。
エントリーお待ちしています。
募集中のエンジニア職種一覧【カジュアル面談の応募もこちら】 | 株式会社LIFULL recruit.lifull.com