WWDC 2021のテスト関係のセッションまとめ1 - Embrace Expected Failures in XCTest
WWDC 2021が終わりましたね。
毎年ですが、セッションの動画は非常に有意義な情報が多いです。
WWDC 2021のたくさんあるセッションの中からテスト関係のセッションは次の2種類があります。
- Embrace Expected Failures in XCTest
- Diagnose unreliable code with test repetitions
本稿ではこれらのセッションのうち前者について次に紹介していきます。
後者については別の記事で紹介します。
セッション動画と以前まとめた記事
WWDC2021のセッション動画は次になります。
このセッション動画で紹介されているXCTExpectFailureというAPIはXcode12.5から追加されました。
本セッションは、そのAPIの利用方法について説明をしています。
軽い説明については次の記事に書いたとおりです。
セッションの(軽い)内容
セッションの内容を軽くまとめつつ、多少補足すると次のような感じです。
(太字が私の注釈的なものです)
テストを作成し、それを運用するにはある程度のコストが必要です。
このコストは、例えばテストが失敗した場合の対処といったものがあります。
この運用コストを下げるのに役立つのが今回紹介するAPIです。
Appleは、この運用コストを下げることができるAPIの追加(+Xcodeへの機能追加)を昨今おこなっています。
テストが失敗したとして、それがすぐに解決できないような問題のとき、テストの失敗はノイズになってしまいます。
常に失敗したのを放置し続けると、他のすぐ直すべき失敗もこのノイズによってわからなくなってしまいます。
このノイズを管理する既存の方法としてなにがあるかというと、テストの「無効化」とXcode11.4から追加されたテストの「スキップ(XCTSkip)」です。
無効化を行った場合、コードは実行されないためテスト結果には表示されず、解決しないといけない理由として追うことが難しくなります。
スキップの場合、テスト結果には表示され問題を把握することはできます。
しかし、テストがすべて実行されるわけではないので、新しい問題や既知の問題に対する変更など、情報が見えなくなります。
そこで、3つ目の手段として今回追加されたのがXCTExpectFailureです。
このAPIを使うとテストは普通に実行されますが、失敗することが期待される結果となります。
そのため、本APIを使っている箇所は失敗した場合が成功として判断されて、逆に成功した場合は失敗となります。
これにより失敗によって発生するノイズがなくなって、他の問題がないかどうかを簡単に確認できるようになります。
ただ、失敗というノイズを無くすだけでは根本的な解決にはなりません。
このAPIを利用し、失敗した原因を追いやすくできます。
例えば次のようにバグを参照するURLをはっておくとします。
XCTExpectFailure("<https://example.com/bug> このバグが直るまでテストが落ちる")
すると、テストレポートには次のようにアドレスへのリンクも表示されます(この一番左の虫アイコンがリンクになっています)。
セッションの後半はAPIの使い方の例になります。
その内容について軽く後述します。
APIの使い方の例
ケース1)
下記の場合、このテストケース内にあるアサーションは全て失敗した場合のみパスします。
1つでも成功した場合は、逆に失敗扱いとなります。
XCTExpectFailure("<https://example.com/bug> このバグが直るまでテストが落ちる")
XCTAssert(false)
ケース2)
次のように特定の処理のみに絞ることもできます。
外側にあるコードで発生した箇所でテストが落ちた場合は正常に報告されます。
XCTExpectFailure("<https://example.com/bug> このバグが直るまでテストが落ちる") {
XCTAssert(false)
}
XCTAssert(true)
ケース3)
例えばmacOSのみ失敗するケースがあるときは、その条件のときのみこのAPIを無効にするということもできます。
この場合はoptionsのisEnabledの値をtrueにします(デフォルトはfalse)。
下記のコードであれば、macOSのときはこのAPIは無効化され通常のアサーションとなります(つまり失敗扱いになります)。
let options = XCTExpectedFailure.Options()
#if os(macOS)
options.isEnabled = true
#endif
XCTExpectFailure("<https://example.com/bug> このバグが直るまでテストが落ちる") {
XCTAssert(false)
}
ケース4)
仮にテストが失敗したとしてもテストを失敗にするのではなく成功とすることもできます。
この場合はoptionsのisStrictの値をfalseにします(デフォルトはtrue)。
let options = XCTExpectedFailure.Options()
options.isStrict = false
XCTExpectFailure("<https://example.com/bug> このバグが直るまでテストが落ちる") {
XCTAssert(false)
}
たまに失敗する程度であれば、このようにoptionsのisStrictをfalseにすることで、テストをあえて失敗にしないようにもできます。
おわりに
太字でも書きましたが、最近Appleは自動テストのトリアージをしやすくするための機能を追加しています。
テスト結果の情報が含まれるResult Bundleといったものや、またWWDC2021ではXcode CloudといったAppleのCI/CDサービスの発表もありました。
これらにより、テストを実装しやすく活用しやすくなってきているかと思います。
これらの機能をフルに活用して自動テストをガンガン活用していければと思います。