モデル検査こんにちは、SWETの鈴木穂高(@hoddy3190)です。私は、こちらの記事で紹介されているようなAndroidテストの教育活動をする傍ら、形式手法という技術の可能性を模索しています。今回は、形式手法についての簡単な説明や、調べていくにつれてわかってきた実用可能性等をご紹介できればと思います。動機まず、なぜ私が形式手法について調べようと思ったのかをご説明します。SWETに所属する前、私は、別の部署で4年ほどゲーム開発に携わっていました。そこでよく課題に感じていたのは、日本語で書かれる仕様の不備(考慮漏れ、記載漏れ、矛盾など)により、大きな手戻りにつながることが多いということでした。開発プロセス上でそのような問題が発生すると、当然再発防止策MTGが開かれます。考慮漏れを防ぐためのチェックリストなどがよく再発防止策として施行されます。プロダクト特有の属人性の高い知識が求められるレビューやチェックリストの目視チェックは、段々と運用の綻びが出てきます。技術的なアプローチでこれらを解決できないかを考えるようになりました。そこで出会ったのが、形式手法という技術です。形式手法とは形式手法とは、仕様を明確に記述したり、記述された設計の性質を機械的に検証する手法の総称です。実は形式手法自体の研究は1970年ごろから始まっており、その歴史は深いです。形式手法を適用して品質向上につながったという事例は、欧米を中心に多く報告されています。導入事例としてどのようなものがあるのかは、形式手法の実践ポータルがよくまとまっていると思います。航空宇宙や鉄道など、高い信頼性が必要とされる分野での事例が多いです。公開されている事例は多くありません。私はまず、形式仕様記述とモデル検査について、調べてみたり、実際に触ってみたりして、前述した仕様書の問題への解決に活用できそうかを検討しました。モデル検査ともに、開発へ適用する際のコストの高さや、仕様書問題への解決策として本当に効果的かという点に懸念が出ました。モデル検査においては、設計や実装の考慮漏れを防げる可能性がありそうだということがわかってきました。モデル検査についてさらに詳しく調べてみることにしました。別のアプローチの解決策を模索していますが、今回は触れません。モデル検査についてモデル検査とは、システムを有限個の状態を持つモデルで表現し、モデルが取りうるすべての状態を機械的かつ網羅的に検査することで、システムが仕様を満たすことを確認する手法です。bがあったとし、「aとbの積が常に9以下である」が成り立つのかを確認したいとしましょう。モデル検査の手順としては、次のようになります。検査したいもの(仕様書、ソースコードなど)から専用のモデリング言語でモデルを作成する検査対象が満たすべき性質から検査式を作成するモデル検査ツールにかけるモデルを作成すると下のようになります。検査式は、assertから始まる部分になります。モデル検査のモデルを書くための言語にはいくつか種類があるのですが、ここではPromelaという言語で記述しています。上で定義しているChooseがインライン展開され、aには1から3のいずれかの値が代入される。9)}モデル検査ツールにはSpinというツールを使います。コマンドラインで検査にかけることができます。9を満たすことを確認します。モデルに一切そういうロジックを書かずに、このような網羅的な探索ができるのも、モデル検査の良いところです。9)に置き換えるとどうなるでしょう。9を満たさなかったaとbのすべての組を反例として示してくれます。3)のときに、検査式を満たさなかったことがわかります。このように、モデル検査は、自動的に網羅的な検査をしてくれます。そのため、並列システムの不整合のような再現させづらいタイミングで発生する不具合や、場合分け不足など設計の考慮不足が起因の不具合などを効果的に見つけてくれます。品質の高いソフトウェアを開発するための有効な手段の1つになるだろうと考えています。モデル作成の難易度が高いというデメリットもあります。実際のシステムをうまく抽象化してモデルを作成するスキルも求められます。Night#6で発表した、「形式手法について調べてみた」に掲載しております。お時間があれば是非ご覧になってください。PoCづくりモデル検査の仕組みがわかったところで、プロダクトに適用できるのかどうかを確かめるために、いくつかの簡単なPoCを作ってみることにしました。Conceptの略で、ここではモデル検査の実用性を確かめるために、簡単なデモを作ることを指しています。PoCの題材決めに際しては、プロダクトに適用する可能性も加味し、プロダクト開発でよく起きる設計・実装上の問題にフォーカスすることを心がけました。そこで、テーマとして挙げたのは、MySQLです。MySQLは、トランザクション分離レベルごとの挙動の把握が難しく、障害につながることがよくあると思います。今回はMySQLにおけるdeadlockの検知をするモデルのご紹介をしたいと思います。複数のプロセスから、CRUDのクエリをランダムにそのモデルに投げ、異常が起きるかどうかを検査します。}}では、モデル検査ツールにかけてみましょう。stateというメッセージが出力されます。これは、網羅的な検査をしていく中で、実行可能な文がなくなったことを意味します。created出力された結果を見ると、53行目のinsertの中で処理が先に進めなくなったことがわかります。updateで共有ロックをとったものの、お互いinsertに進行ができなくなったようです。これがMySQLでいうところのdeadlockに相当します。実際の運用では、このトランザクション内の処理を、プロダクトコード内の処理にあわせてCRUDの組み合わせや順番を変更することを想定しています。先に書いたとおり、モデル検査には「モデル作成の難易度が高い」というハードルがあります。低コストでモデル検査を行える可能性があると考えています。設計確認としてのモデル検査UIのようなイベント駆動での非同期処理の設計確認にもモデル検査が使えます。簡略化して書きますが、APIから取得した要素をリストビューに追加し、追加要素の中心となる位置までスクロールするという処理を実装した際、以下のような設計ミスに気づいた事例がありました。ように考慮漏れが起きやすい処理の設計の検証にもモデル検査が有効です。7)}モデル検査にかけると、反例として、「要素数は9だが、スクロール位置は3」が経路と合わせて出力されます。created今回の実装で問題だったのは、別々のストリームで非同期処理をおこなっていたことによるものでした。中心位置取得のリクエストが投げられる追加するリスト要素を取得するリクエストが投げられる中心位置取得のリクエストの結果が返ってくる追加するリスト要素を取得するリクエストの結果が返ってくるとなっており、意図していた挙動とは異なることがわかります。別々のストリームで非同期を走らせると、処理順番は常に同じにならないというのは、非同期処理を扱う上で基本的な話ではあります。設計の欠陥に実装した後気づくのと、実装の前に気づくのとでは手戻りのインパクトが異なります。注意の勘所がわかっていないと気づくのは難しいです。自分が考えている設計が本当にこれでよいのか、考慮漏れはなさそうかを確認するためにも有効だろう思いました。今後の展望いくつかのPoC作りを通して、モデリング言語で表現できる範囲がわかってきました。これからは、実際のプロダクトコードにモデル検査を適用できる部分を探してみたいと思います。その方向でさらなる可能性を見極めていきたいと思います。さいごにこのようにSWETでは、少しずつではありますが、形式手法の可能性について研究をしています。経過をかなり省いて書いてしまった部分もありますが、なにか疑問がございましたら、@hoddy3190までお尋ねくださいませ。本記事の続報についてはbuildersconでお話できればと思っています。会場にお越しください!形式手法の研究は私含め2人のメンバーで行っております。2人とも半年ほど前に形式手法をはじめたばかりです。(ゲームアーキテクチャ)また、その他のチームへのご応募お待ちしております。JUnit5でUIテストを書こうAndroidこんにちは。SWETチームの@zhailujiaです。Junit5を使ったUIテストの書き方を紹介して行きたいと思います。5テストをまだ公式対応していません。1.0.0Libraryをリリースしました。これによりAndroidXのActivityScenarioなどのAPIとJunit5を組み合わせたUIテストが遂に書けるになりました。5に必要最小限の設定を記述しています。5も同一プロジェクトに設定して共存できますが、今回は割愛します。Testテストを書こうProjectソースはAndroid-Junit5/Instrumeny/Sample/から引用しています、ご参照ください。APIを使用可能になりました。5版@ActivityTestも廃止になりました。Resolution機能に対応している。そのため、ActivityScenarioは、直接テストケースのパラメータとして使うことができる。testでも使えます。テストの構造化、日本語の表示を実現できます。RepeatedTest指定した回数で繰り返しテストを実行できます。RepetitionInfoからcurrentRepetition(現在の実行回数)、totalRepetitions(実行すべき総回数)を取得できます。DisplayNameに対応している。ParameterizedTestParameterizedTestは異なる引数でテストを複数回実行できます。Argumentsアノテーションで宣言する。ソースアノテーションは複数種類ありますが、今回は展開せず@ArgumentsSourceを使う例を挙げます。テストメソッドのパラメータとしてデータを受け取ります。DisplayNameに対応している(今回は省略)。}テスト実行結果パラメタライズドテストは以下のような効果が考えられますRepeatedTestとParameterizedTestを活用して、重複するテストコード、テストケースを削減できます。argumentsを利用してにテストのGiven-When-Thenをペアに設定ことで可読性が上がります。Esspressoだけで画面上複数のビューの操作する時、テストコードがダラダラ長くなりがち部分も、arguments化して綺麗にまとまります。ご興味があれば試してみてください。android-junit5はまだリリースされたばかりなので、RepeatedTestとParameterizedTestの動作にはいくつか注意点がありますが、今回は割愛させていただきます。Lifecycleなど一歩進んだ使い方もあります。JUnit5のさらなる活用を使ってみましょう。参考リストhttps://github.com/mannodermaus/android-junit5/wiki/Instrumentation-Tests-Setuphttps://junit.org/junit5/docs/current/user-guide/謝辞@marcelschnellさんと共同開発者たちが素晴らしいプラグインを開発してくださって深く感謝しています。5に関して貴重な意見と経験を教えていただきました。ありがとうございます。発表・イベントリポートこんにちは、SWETグループの田熊です。先日、社内のAndroidアプリエンジニアを対象にユニットテストのハンズオンを行いました。本記事では、どのようなことを考えながらハンズオンを作成していったのかと、ハンズオンの内容を紹介しようと思います。ハンズオンを開催したのかこれまでのSWETは、メンバーがプロダクトに個別にジョインし、品質保証や生産性向上につながるような取り組みをしてきました。SWETが関わっていないプロダクトからも「テストがなくてつらい」などの声があがっていたため、自動テストのナレッジをスケールさせていくことも必要だと考えていました。そこで、自動テストの普及の一貫としてテストハンズオンの実施を検討しました。社内状況の把握DeNAはサービスが多岐に渡るため、SWET内で各サービスにどの程度自動テストが普及しているかを把握できておらず、どのようなレベル感のハンズオンを作成すればいいかがわかりませんでした。現状をより正確に知るために、社内のエンジニアに自動テスト実施状況を確認するアンケートを取りました。その結果、下記のようなことがわかりました。ユニットテストについて約50%がもっと力を入れていきたいと考えている約25%が導入したいと思っているが、できていない作成における課題として多かったものテストが書きにくい設計になっている(50%)工数がとれない(40.9%)費用対効果がわからない(13.6%)UIテストやE2Eについて約40%が導入したいと思っているが、できていない作成における課題として多かったもの工数がとれない(36.4%)ナレッジがない(36.4%)テストが書きにくい設計になっている(31.8%)この結果をうけて、まずはユニットテストにおける課題の半数を占める「テストが書きにくい設計になっている」について、ハンズオンを通じて何かしらのアプローチができないかと考えました。初回のターゲットを検討した結果、ネイティブAndroidアプリエンジニアを対象に行うことにしました。理由としては、Androidテスト全書など、ハンズオンの参考になるドキュメントが充実していたからです。「テストが書きにくい設計になっている」問題に対してのアプローチを、プロダクトのコードを変更する目的ごとに考えました。テストを導入しつつテストが書きにくい設計を改善するそして、各アプローチを盛り込んだ「テストをはじめよう編」と「テストのないアプリにテストを書こう編」の2つのテーマでハンズオンを作成をすることにしました。各人の時間の都合やパフォーマンス等を鑑み、ハンズオンは2日にわけてそれぞれ2時間で実施とすることにしました。テストをはじめよう編テストを始めよう編のアウトラインは下記です。座学なぜテストを書くのかAndroidにおけるテストの説明TDDの紹介チュートリアルTDDチュートリアル(参加者に実際に手をうごかしてもらう)自習(各自お題をTDDで進めてもらう)アウトラインについて、どうしてこのような構成にしたかを振り返ります。テストを書くのかこの章では、テストを書くことによるメリットと、書かない場合のリスクについてまとめています。Androidテスト全書の1章とSWET内部で作成した自動テストの効能をまとめたドキュメントを参考にしながら作成しました。テストを書く習慣をつけるためには、そのメリットについて納得している必要があります。自動テストのメリットについて昨今のエンジニアであれば一度は聞いたことがあるかもしれません。普段テストが書きにくいプロダクト開発をしている場合、日常的に自動テストに触れられておらず、そのメリットの認識も曖昧になっているかもしれないと思いました。よって、なぜテストを書くのか?を改めて確認し、テストを書くモチベーションの向上につなげようという意図があり冒頭に説明をいれました。test)をまとめています。Androidテスト全書の1章を参考にしながら作成しました。この章はAndroidアプリ開発におけるテストの基礎知識を整理するために追加しました。TDDの紹介/TDDチュートリアルTDDは下記の点から題材として最適と思い採用しました。ハンズオンで使用した資料をアップしましたので、ご興味がある方はどうぞ!※外部公開に際し、資料は一部修正を加えております。Androidテストハンズオン基礎編TDDチュートリアルテストのないアプリにテストを書こうテストのないアプリにテストを書こう編のアウトラインは下記です。レガシーコードを改善しようレガシーコード改善に役立つ知識テストダブルレガシーコード改善テクニックテストのないアプリにテストを書こう(参加者に実際に手をうごかしてもらう)こちらもどうしてこのような構成にしたかを振り返ります。レガシーコードを改善しようこの章では、自動テスト実施状況アンケート結果で社内の半数がテストが書きにくい設計を課題としていることを紹介し、地道にテストを導入しつつテストが書きにくい設計を改善しようという提案をしました。目的は、タイトルの通りレガシーコード改善への動機づけです。テストが書きにくい部分に引きずられてテストを書かずにいると、悪循環になってしまうからです。レガシーコード改善に役立つ知識ここでは、テストダブルとレガシーコード改善テクニックの紹介をしました。Androidテスト全書の2章とレガシーコード改善ガイドを参考に作成しました。テストが書きにくい設計のアプリにテストを書いていくのは、なかなかに難易度が高いタスクです。テストダブルを使って依存を切り離すテクニックと、レガシーコード改善ガイドにある最低限の修正でテストを書けるようにするテクニックを知っていると、そのタスクの助けになると思いこの章を追加しました。テストのないアプリにテストを書こうあえてテストが書きにくい設計で実装したサンプルアプリを題材に、参加者にユニットテストを書いてもらうセクションです。Requestとして提出してもらい、SWETメンバーがレビューを行う方式にしました。ここでは、その前の章で説明したテストダブルやレガシーコード改善テクニックを、参加者が実際に使って身につけてもらうことを目的としています。Requestレビューを通じて説明した内容がきちんと伝わっているかと、参加者がお題にどのように取り組んだかを確認できるようにしました。資料こちらも実際にハンズオンで使用した資料の一部をアップしましたので、ご興味がある方はどうぞ!※外部公開に際し、資料は一部修正を加えております。平均4.78と良いフィードバックをいただくことができました。(5段階評価で5が良い・1が悪い)ハンズオンの内容の質にこだわったのはもちろん、専用のslackチャンネルを設けて質問をしやすくしたり、講師以外にもTAを3人配置するなどといった運営の工夫も功を奏したのだと思います。ハンズオンは好評のうちに終えることができましたが、実際にプロダクト状況を改善していくには継続的な取り組みが必要になります。参加者のテスト導入について相談を受けられるようにし、実プロダクトへの貢献も進めていきたいと考えています。今後もSWETでは社内のエンジニアがテスト技術について学ぶことができるコンテンツの作成を進めていきます。現在、下記を企画しています。ユニットテストハンズオンのiOS編モバイルのUIテストハンズオンGo言語でTDDを学ぶことができるCodelabこのような取り組みを通じて、社内のエンジニアが自動テストスキルを向上できる仕組みと、社内のエンジニアがいつでもテストについてSWETに相談できるような環境を作っていきます。最後に、SWETでは一緒に自動テストの普及に取り組んでくれるエンジニアを募集しています。発表・イベントリポートこんにちは。2019にSWETからは3名が登壇しました。参加メンバーが特に印象に残ったセッションをご紹介していきたいと思います!登壇者より自身のセッションについて一言マルチモジュールなプロジェクトでテストはどう変わる?登壇者の田熊(@fgfgtkm)です。このセッションでは私がマルチモジュールなプロジェクトでのテストを考えたときに、変えていく必要があると思った3点を紹介させていただきました。DIテスト方針メトリクスの収集DIのセクションでは、循環参照の問題や依存解決の定義をモジュール内に閉じ込めるため、これまでのやり方を変更しなければいけない可能性があることを話しました。Injection』のセッションを紹介させていただきました。私も拝見させていただき、とてもわかりやすく勉強になりました。テスト方針のセクションでは、モジュール単位で動作確認ができるようにテスト方針を考える、という話をしました。Nitrogenについて触れ、自動テストでカバーする領域を増やしていける環境が整いつつあることもご紹介させていただきました。最後にメトリクス収集について、複数のモジュールのレポートをまとめて見たい場合マージが必要になることと、PITというツールを例にどのようにレポートをマージするかについて話しました。想定していたよりも大きな部屋で多くの開発者に話をさせていただけることになったので、マルチモジュールというトレンドを取り入れつつも、これからテストにもっと力を入れていきたいと思っている方に下記のことを伝えられたらいいなと思いながら構成を考えました。自分のプロジェクトにどんなテストが必要かを考えるテストの環境や技術は日々進化しているテストに対する考えや知識をアップデートするきっかけになればとても幸いです。EspressoのテストをAndroidの最新トレンドに対応させよう登壇者の外山(@sumio_tym)です。次のようなトピックを解説しました。Objectsデザインパターンを適用する前提で解説しています。Objectsに書き換える様子をライブコーディングしている点が見どころです。気になる方は是非動画もチェックしてみてください。UIテスト(Espresso)の高速化をさらにすすめる登壇者の平田(@tarappo)です。2018の続編という形で「UIテストの高速化をさらにすすめる」というタイトルで登壇しました。UIテストの課題になりやすいものの1つに実行時間の増加があります。このUIテストの実行時間をどのように短くするかという話をしました。前回話した内容は実際に試してみるのがやや大変だったかと思いますが、今年の登壇内容は誰もがすぐに試せるようになっています。LabやFlankを試してみてもらえるとうれしいです。※動画はこちら登壇の際に、その先にある課題として自動テストがあることにより得られるred/green以外の情報などについても話しました。その課題については、どこかの機会で話せると嬉しいなと思っています。Test環境を手に入れろ!改めまして田熊(@fgfgtkm)です。今回はSpek関連のセッションが2つありましたので、それぞれご紹介させていただきます。Nishikoriさんのセッションです。こちらのセッションでは、SpekだけでなくKotlin製モックライブラリのMockKやコードカバレッジライブラリのJacocoなどトータルのユニットテスト環境について紹介されていました。※動画はこちらSpek2とMockKはどちらもKotlinフレンドリーな記述が可能で、Kotlinに慣れ親しんだ開発者がユニットテストを書き始めるときにとても導入しやすいと思っています。私のセッションでマルチモジュールなプロジェクトの場合レポートのマージが必要なことに触れましたが、こちらのセッションではJacocoでの具体的なマージ方法を紹介していました。それぞれの導入手順や使い方について丁寧に説明しているため、これからテスト環境を構築していく際の参考にすると良いと思いました。Morimotoさんのセッションです。Componentsを使用したクラスのテストをどのようにSpekで書くかを紹介していました。※動画はこちらSpekはテストコードの読みやすさから人気が高まっていると感じていますが、Androidが絡むとJUnitに比べて書き方のナレッジやサンプルが少ない印象です。セッションの中ではAndroid開発の中で採用されることが多いLiveDataとRoomのテストをSpekで書くための工夫が紹介されており、Spekで書けるテストの範囲を増やしていく際に役立つ知見の詰まったセッションだと思いました。build.gradle.ktsに移行しよう改めまして外山(@sumio_tym)です。こちらはtnjさんによる発表です。DSLへ移行する方法についての発表でした。DSLへ移行することで、IDEによるコード補完が効きやすくなるというメリットがあります。Gradleのビルドスクリプトでは、GroovyとKotlinを共存させることができます。その特徴を最大限利用して、徐々にGroovyからKotlinへ置き換えていくテクニックを分かりやすく解説していました。DSL化しようとして挫折した苦い経験があります。その当時を思い返してみると、着手する場所が悪かったがために、芋蔓式に全部Kotlin化せざるを得なくなったのが敗因でした。この発表で解説されている順番にしたがえば徐々に書き換えられるので、挫折せずにKotlin化を完遂できそうです。DSLへの移行を検討されている方は、是非参考にしてみてください。CI/CDチームの加瀬(@Kesin11)です。こちらのlitmonさんのセッションは、CIサービスやデプロイの自動化などに興味があるCI/CDチームとして、参加前から注目していました。※動画はこちら発表内容のメインは、それなりの人数で開発されているであろうアプリのリリース作業について人間が調整するのにコストが高くなりすぎたので、自動的に毎週リリースされるフローを構築したというものでした。Consoleのリリース前レポートでした。LabのRoboテストを直接利用することで同等のクラッシュ検知と通知は実現しているとのことでした。Consoleで使用されているのはこのRoboテストのようです。個人的な感想ですが、リリース作業を自動化するというフローはそもそもプロダクト全体の品質がかなり高い状態でないと、逆に検証不足でバグが頻出してしまうことも起こり得るのではないかなと思います。クックパッドでは以前から大規模にUIテストを含めた自動テストが行われているということをブログなどで拝見していたので、そのような積み重ねがあってこそ達成できるリリースフローなのかもしれません。この発表ではテストについての話はありませんでしたが、テストの必要性をより意識した発表でした。AutomationTestチームの鈴木です。Iijimaさんの発表をご紹介いたします。※動画はこちら本セッションでは、登壇者自身の実際の開発経験を踏まえながら、TDDによって得られるメリットについて解説されていました。ライブコーディングでTDDを実演しながら説明されていたので、初心者の方でも大きな抵抗なく読み進めることができると思います。内容はもちろん、説明の仕方もわかりやすく大変参考になりました。2019のセッションのうち、登壇者のセッションと各メンバーがそれぞれ印象に残ったセッションをご紹介しました。SWETグループでは、DroidKaigiでの登壇に限らず、積極的に対外的なアウトプットを行っています。Night(テストについて語り合う勉強会)も定期的に開催しております。Night(4月開催予定)の開催を予定しております。ご興味のある方は是非ご参加ください。SWETグループではAndroidに限らずテストの自動化やCI/CDに興味があり、私達と一緒に働いてくれる仲間を募集しています。その2の最終日の記事ですSWETの平田(@tarappo)です。アドベントカレンダーも本日で最終日です。2018年は残りわずかとなりました。Testing」をふりかえってみたいと思います。2018」の動画やスライドは公開されており、以下から見ることができます。今だと日本語訳もありますし、見て参考になるものが多いかと思います。Testing」は以下になります。Testing」で紹介されたのは以下の3種類になります。10から追加された機能もあれば、ベースの機能があってそれが改良されたものもあります。testing」について紹介したいと思います。そこまで使ってみた情報が世に転がっていないので、是非とも使ってみて様々な知見を世に公開してもらえると嬉しいです。9.3で改良がおこなわれて動作や精度が向上しています。実際に発表された例では以下のように改善されています。MB他にもありますが、今回のメインは残り2つですのでこれぐらいにしておきます。coverageについての話は別途どこかしらで紹介できればと思います。10以降のスキームエディタから設定できるようになっています。Scheme」を選択した後、「Test」を選ぶと表示される以下の画面にあります。Xcode10のスキームエディタこの画面の「Options」を選択すると表示される以下の3項目が今回紹介する機能になります。ordering」では以下の2つの項目について紹介します。testing」では以下の1つの項目について紹介をします。testsこの機能は「新しく作成したテストコードを自動的に実行対象に含めるかどうか」の設定になります。このオプションを無効にした場合、新規で実装したテストコードは常に実行対象外(disable)になります。デフォルトはチェックがついた有効の状態になっています。今までは、テストコードの中からあるテストクラスやテストケースを実行対象外にするということができました。これだと新規に追加したテストコードは実行対象になってしまいます。今回のオプションを有効活用をすれば、新規に実装したテストコードは常に実行対象外にするといったことができます。今までは「実行対象のテストコードを実行対象外にする」という行為のみでしたが、「実行対象外のテストコードを実行対象にする」という逆のやり方もできるようになったということです。実際の利用ケースを考えてみましょう。以下の2つのスキームがあるとします。本オプションを有効にする実装したテストコードは常にスキームBでは実行対象となりますが、スキームAでは実行対象にはなりません。nightlyで問題なく通りつづけ安定性が確認されたらスキームAのほうで、そのテストコードを実行対象とします。このようなケースでの使い方もできるようになっています。このケースはあくまでも例であり、利用方法はいろいろと考えられます。テストコードを実行対象外にする方法さて、今回の話からは少し脱線した蛇足的な話になります。これは開発時において、テストコードを一時的に無視したいときの話です。JUnit4では@Ignoreアノテーション(JUnit5だと@Disabled)があります。このアノテーションにはコメントを付与することもできます。いうようにxというprefixをつけることでテストをスキップさせることができます。pendingというのもあります。Xcodeの場合だと以下のようにすることで実行対象外にできます。orderこの機能は「対象としたスキームに含まれるテストコードに対して、テストの実行をランダムでおこなうかどうか」の設定になります。デフォルトではチェックが付いていない無効状態になっています。無効の状態だとテストの実行順はアルファベット順になっています。自動テストはそれぞれのテストケースが独立していることが望ましいです。あるテストケースが他のテストケースに副作用を与える形になっていると、次のような問題が起こる可能性があります。テストケースが増えて、実行順序が変わったことによりテストが落ちるようになる特定のテストだけを動かそうとして動かないつまり、「全てのテストコードを動かせば成功するが、それ以外の方法で動かすと失敗する」という形になったりします。副作用を与えているかどうかということに気づかないこともあります。そのため、ランダムで実行させるとテストケースが独立していないことに気づく一助となったりします。このような重要な機能ですが、他のテスティングフレームワークではランダム実行についてはどうなっているのでしょうか?JUnit4はAndroidでも利用されていますが、このバージョンではランダム実行はできません。JUnit5からランダム実行ができるようになっています。ランダム実行をしたのと同じ順番で再度実行をするためのseedというものが発行されるようになっています。それ以外にもアルファベット順とOrderアノテーション順というのがあります。詳しくは以下のサイトを確認してみてください。https://junit.org/junit5/docs/snapshot/user-guide/#writing-tests-test-execution-orderRSpecでは2.8(2012/01)の時点で、すでにランダムで実行できるようになっています。JUnit5と同様にseedを発行できます。再度同じ順番で実行ができるというのは、テストの実行をランダムでおこなう場合は必須の機能とも言えます。テストコードをランダムで実行して失敗し、修正をしたあとに直っているかどうかの確認をするためには同じ順番で実行できることが重要です。10ではランダムでの実行がサポートされましたが、同じ順番で再度実行できないといった状況です。再現確認をおこなうことが出来ません。どのような順番で実行されたかは分かるので、手動で頑張るという荒業はあるにはありますが、なかなか厳しいです。機能ではありますが、これについては致命的です。今後改善されることを期待したいと思います。Radar」にはそのことについて書かれたチケットがすでにあります。2018」では多少多めに時間をとって説明をしていました。9の時点でxcodebuildコマンドからシミュレーターの並列起動ができるようになり、fastlaneのsnapshotでは対応されました。以下の機能不足がありました。10からはこの不足部分が解消されています。Simulatorに対して並列でテストを実行できるようになりました。これはXcodeを使って開発している際においても、テストの実行時間を削減できるようになったということです。Simulatorこの機能は「対象としたスキームに含まれるテストコードに対して、同じiOSのシミュレーターで並列実行させるかどうか」の設定になります。デフォルトでこの設定は無効になっていますが、有効にすると1つの親からクローンのSimulatorを作り、並列にテストを実行してくれます。xcodebuildコマンドのオプションとしては以下が追加されています。-helpをすると他にも増えていることがわかります。shardingとは異なり、テストクラス単位で勝手にわりふられます。並列化によりテストの実行時間は短縮されます。この並列化をおこなうことにおいてよくあるケースとして、1つの実行時間が長いクラスがあるとその実行時間にひっぱられる形となるということです。以下の図のようにクラスAからEまで5クラスあったとします。クラスAの実行時間が長いと、並列数を増やしても最終的にAの実行時間がトータルの実行時間になってしまいます。いわれる対処法は、実行時間が長いクラスを分割することです。今回の例ですと、クラスAをクラスA1とクラスA2なりに分割するということです。クラスの分割これにより、トータルの実行時間は短くなります。2018」では、必要になったら実行時間が長いクラスを分割しましょうという話がありましたが、必要なタイミングで分割しやすい形になっているとは限りません。そのため、テストコードを最初から分解しやすい形にしておくことが求められます。いったものをちゃんと分けて実装しておくことが大事です。XCTestにおいてもsetUp()とtearDown()があるので、十分に活用することが大事です。test」や「AAA」といったものを知って実践するのが良いでしょう。テストのランダム実行でも同様ですが、より自動テストを適切に実装する必要性が問われるようになってきているとも言えます。fastlaneでも利用されているテスト結果をファイル形式などで出力してくれるxcprettyはこの並列実行への対応がおこなわれていません。そのため、fastlaneのscanなどを利用している場合は、テスト結果の出力は不完全な状態ではあります。並列実行のその次のステップへ今回のような並列実行ができるようになったというのは次のステップがいろいろと考えられるようになったとも言えます。2016」で発表されましたが、xcodebuildコマンドでクラスを指定してテストコードを実行するオプション(only-testing)が追加されています。このようなオプションと組み合わせることにより、さらなるテストの実行時間の最適化はできるようになります。現状の仕組みを用いて自身でこの最適化をおこなうのは非常に高コストではあります。並列実行に関してはCircleCIではparallelismというkeyを設定することにより並列実行をしてくれるというものがあります。詳細については以下のページをチェックしてもらえればと思います。Labというデバイスファームを用いて、テストを並列化するFlankというものもあります。このFlankがBitriseから利用できるようになるという話もあります。このように、今後はCIサービス側とその先のサービスで並列化をよりサポートをしてくれるようになってくるかもしれません。10からは、xcodebuildコマンドからの実行だけでなくXcodeからの実行においても非常にいろいろと便利になってきています。自動テストにおける土台は少しずつではありますが進化してきています。ここ数年の進化を駆使すればいろいろとできることは増えています。その結果として、いろいろなサービスも生まれてきています。その手の知見が共有できていない状況といえます。本記事などを参考に触っていただき得られた知見を世に公開してもらえると嬉しい限りです。その1の2日目の記事ですこんにちは。SWETの加瀬(@Kesin11)です。LabはiOSとAndroidに対応した実際の実機デバイス上でテストを実行してくれるサービスです1。Labが将来的にiOSをサポートするかどうかという話はこれまで何もありませんでした。LabのiOS版が発表されたとき個人的には大興奮でした。LabにあるiOS実機でXCTest、XCUITestを実行してくれて、デバイスごとのテスト結果や動画などを確認できます。LabのiOS版について、以下の複数の利用方法についてそれぞれ解説していきます。Bitriseから使うgcloudコマンドから使う(ローカル)gcloudコマンドから使う(CI環境)Fastlaneプラグインから使うなお、本記事の動作確認はこちらのリポジトリをベースにXCTestを追加し、XCUITestを少し修正したものを使用しています。使用したXcodeのバージョンは10.1です。https://github.com/browserstack/xcuitest-sample-browserstackBitriseから使うBitriseはモバイルアプリに特化したCI/CDサービスです。Bitriseをお使いであれば、現状ではこの方法が最も簡単、かつ無料の方法になります。Testingというステップが存在します。これは名前の通りに実機デバイスでXCTest、XCUITestを実行し、テスト結果だけではなくてそのときのスクリーンショット、動画、デバイスログも保存してくれるものです。Labを使用していることが公式に解説されています。Labは本来アカウントの認証が必要であったり、一定以上の使用には課金が必要です(認証と料金については後述)。Testingを使用する場合にはFirebaseとのやりとりをBitriseがやってくれるため、アカウントの認証不要、さらに現在はβ版のためか無料で使うことができます。Testingのステップから確認できます。執筆時点での一覧はこのようになっていました。6が存在し、多少ですがiPadも種類が用意されています。9.0からそろっています。iOSバージョンの実機を実際に手元で用意、管理するのはなかなか大変だと思います。これこそが、この手のサービスで最も嬉しいポイントではないでしょうか。Testingのさらに詳しい使い方やスクリーンショットは、Bitrise公式のドキュメントやブログが充実していますので、そちらを見てもらうと分かりやすいと思います。Labを使う方法になります。Labを使うにはアカウントの認証と、紐付けるプロジェクトの選択が必要になります。PROJECT_IDを実行してください。PROJECT_IDはfirebaseのプロジェクトIDです。firebaseのプロジェクトを作成していない場合、先にfirebaseのプロジェクトを作成しておいてください2。gcloudコマンドのセットアップができたら、まずは使用できるデバイスの一覧を見てみましょう。Bitriseと同じリストが表示されましたね。次にテスト用のビルドを作成します。ドキュメントにあるようにxcodebuildでビルドします。アプリ名とスキームがMyAppで、ビルド結果の出力先をfirebase_testとした場合には以下のようなコマンドになります。Labでテストを実行するには、テスト用のビルド成果物とxctestrunファイルを1つのzipに圧縮する必要があります。MyApp_iphoneos12.1-arm64e.xctestrunあるいはFastlaneを導入済みならばscanのbuild_for_testingオプションを使ってテスト用ビルドを生成しても大丈夫です。true)テスト用のビルドができたらいよいよテストを実行してみましょう。--xcode-version=10.1テストを実行したいデバイスの設定を--deviceの引数に渡します。modelとversionには先ほどのモデル一覧で表示されたMODEL_IDとOS_VERSION_IDSを指定します。必要であればlocaleとorientationも指定可能で、指定しなかった場合のデフォルトはenとportraitとなります。listで一覧の確認が可能です。Lab側でテストを実行するXcodeのバージョンのようです。10.1でビルドした場合に--xcode_versionの指定無しでも動くことを確認しましたが、古いXcodeを使用している場合や、新しいXcodeが出た直後などにはバージョンを指定しておいた方がいいかもしれません。Labのページで結果を見ることができます。実行が完了するとこのように複数のデバイスでテストケースごとのテスト結果、スクリーンショットや動画を確認できます。Labを実行をできるようにしておくのがよいでしょう。iosを実行するにはアカウントの認証が必要です。認証にはブラウザでログインする必要があるので通常の方法ではCI環境で認証することはできず、テストを実行できません。この問題はサービスアカウントを使って認証することで解決できます。この方法に関してのドキュメントはAndroid版の方に一応存在するのですが、あまり分かりやすいとは言えないため解説します。サービスアカウントによる認証まずはGCPのコンソールからサービスアカウントを作成します。https://console.cloud.google.com/iam-admin/serviceaccounts/サービスアカウントの権限には「プロジェクトの編集者」の権限を付ける必要があります。権限の設定が完了したら最後にjson形式で鍵を生成してください。APIを検索し、両方とも有効化してください3。jsonの鍵を用意できたらgcloudコマンドがサービスアカウントを使うように認証させます。listを実行してサービスアカウントにACTIVEが付いていればOKです。runを実行して、まずはローカルの環境で実行できることを確認しておきましょう。Labを実行するときにエラーとなってしまう場合があるようです。https://stackoverflow.com/questions/48327027/cant-run-firebase-test-lab-tests-using-gcloud-and-service-account-403-does-no?rq=1上記のベストアンサーではない方の回答に、Firebaseのサービスアカウントの鍵を使うと動作したという回答がありました。Firebaseのサービスアカウントの鍵は以下のurlからアクセスできるページで作成できます。https://console.firebase.google.com/u/0/project/FIREBASE_PROJECT_ID/settings/serviceaccounts/adminsdk(FIREBASE_PROJECT_IDのところは自分のプロジェクトidに書き換えてアクセスしてください)自分が試したところ、たしかに動作することを確認しました。詳しい理由は不明ですが、自分と同じようにGCPで作成したサービスアカウントではどうしてもエラーになってしまう場合に試してみるといいかもしれません。CIサービスのビルドフローの設定サービスアカウントの認証ができたところで、次はCIサービスのビルドフローに組み込んでみましょう。お使いのCIサービスでgcloudコマンドを使えるようにし、先ほどと同様にサービスアカウントで認証をしてからテストを実行するフローを構築してください。注意が必要なのは、サービスアカウントの鍵のjsonです。チームの体制にもよりますが、一般的にはリポジトリにコミットするべきではないでしょう。使用するCIの環境によっては秘密にしておきたいファイルをリポジトリとは別に登録するという方法ができない場合もあるかと思います。そのような場合は、CircleCIのドキュメントにあるようにjsonの中身を環境変数として登録しておき、ビルドフローの中で再度jsonとして書き出すという方法が使えます。CircleCI実際のサンプルとしてBitriseでgcloudを使ってサービスアカウントの認証、テストを実行する方法を紹介します。サービスアカウントの鍵であるjsonの中身をcatとpbcopyなどを使って丸ごとコピーして環境変数にセットしておきます。以下のコードでは$SERVICE_ACCOUNT_KEYで参照しています。BitriseのScriptステップはシェルスクリプトをそのまま実行できるため、ここでインストールから認証まで行います。runを実行するだけです。テスト用のビルドについては説明済みですので、今回は省略します。model=iphone6s,version=10.3,locale=ja_JP,orientation=landscape上記のサンプルには主にgcloudコマンドをセットアップするBitrise特有のコードも含まれてしまっていますが、サービスアカウントで認証してテストを実行する部分は他のCI環境でも同様に動作すると思います。CircleCIの組み合わせの記事を探してみるのがよいでしょう。Labを実行するFastlaneプラグインを使用するという選択肢もあります。fastlane/fastlane-plugin-firebase_test_lab使い方はREADMEに書いてあるように、scanでテスト用のビルドを行ってからfirebase_test_lab_ios_xctestでテストを実行します。注意点として、READMEのサンプルをそのまま使用した場合はgcloudのデフォルトの認証情報が使われます。gcloudのコマンドから実行したときと同様に、CI環境では動きません。oauth_key_file_pathというオプションにサービスアカウントの鍵のパスを指定することで、サービスアカウントで認証を行うことができます。])ただし注意点として、FastlaneのプラグインはコミュニティによってメンテされているためXcodeのバージョンが上がった場合などに動かなくなる可能性があります。10.1でxctestrunの形式が微妙に変わったことで動かなくなってしまったバグの修正PRがついこの前マージされたようです。このように何かがバージョンアップされた場合に壊れてしまうリスクがあるということは覚えておいた方がいいでしょう。最後は気になるお値段の方ですね。Blogなどをウォッチしておくといいでしょう。Labを使用する場合は無料プランと、従量課金プランがあります。Planの場合はテスト5回/日のようです。チームの規模が大きい場合には全てのpull-reqごとに実行するような使い方は難しいと思いますので、テストを実行するブランチを絞ったり、深夜ビルドでのみ実行するといった工夫が必要かもしれません。Planにした場合、回数の上限はなくなり$5/デバイス/時間となります。これの意味するところは、テストを実行したデバイス全ての稼働時間の合計が1時間につき$5という意味です。具体的な例としては、1回の実行に12分かかるテストを5台のデバイスで実行した場合、合計で1時間=$5と計算されるということになります。Deviceのみとなります。上記の料金の計算は執筆時点(2018年12月)のドキュメントを参考にしたものであり、必ずしも正しいことを保証するものではありません。Firebaseの料金は今後変化する可能性がありますので詳しくはFirebaseの料金のページを参照するようにしてください。Labによる実機テストを行う方法の解説をしました。Labはとても簡単に使えて、無料プランもあるのでこの手のサービスの中ではかなり試しやすいサービスだと思います。ビルドのたびに様々なiOSデバイス、iOSバージョンの実機で自動テストを実行することが理想ですが、人手を介さずにそれを全自動で行ってくれるシステムを構築・運用することはとても難しいです。Labを使って、ゼロ円から実機の自動テストを始めてみませんか?Android版では実機だけではなくエミュレータを使用してテストを実行することも可能です。実はGCPのプロジェクトIDでも実行することは可能ですが、テスト結果画面を見るにはFirebaseのプロジェクトページにアクセスする必要があるため、どのみちGCPのプロジェクトに紐づけたFirebaseのプロジェクトを作成する必要があります。いうように有効化するか尋ねられるので、そこでyesとしても大丈夫なようです。2019でSWETのKuniwakが、テストによる開発プロセス改善の実例に関して紹介いたします。@orga_chem(Kuniwak)こと国分佑樹2018年からSWETチームで働いているエンジニアです。専門はユニットテストやプロセス改善による開発の安定化と高速化。2017最多いいね数賞など。オープンソース活動も活発にしており、静的検査ツールや効率的なテストを支援するためのライブラリ等を開発しています。私の所属するSWETという組織の目指すものは「テストを楽しく、賢く、価値を届けられるように」であり、私たちは日々これを達成すべく働いています。このような組織に所属する私が取り組んでいるものは、テストをうまく使って開発速度の安定化や向上、より保守性の高い設計を達成することです。この発表では、私が取り組んできたテストによる開発プロセスの改善の実例をお話しします。TechCon2019についてDeNAでは、ゲームやエンタメだけでなく、Eコマース、ソーシャルLIVE、ヘルスケア、オートモーティブ、そして横浜DeNAベイスターズのようなスポーツなど、様々な事業を行っています。技術の力で事業の未来をリードするため、様々なチャレンジも行っています。TechConはこれらのチャレンジの中から、技術的に特に面白いものを厳選して皆さんにお披露目するお祭りです。TechConの次回開催内容が決定したのでお知らせします。TechConの最新情報は、公式Twitterアカウント(@DeNAxTech)にて確認いただけます。(1)リンクプライバシーポリシースターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。