1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Flutter】プラットフォームごとに挙動が異なる場合のウィジェットテスト

Posted at

プラットフォーム(OS)によって遷移先の画面を変える機能のウィジェットテストを書いていた際
日本語の情報が見つからずちょっとした躓きポイントにハマってしまったのでその対処の記録です。

プラットフォームにより異なる挙動を一つの環境でテストするには、テスト実行時プラットフォームを偽装する必要があります。
またそれだけでなく、プロダクトコード側のプラットフォーム判別もテスト時の偽装に対応したものでなければならない:
具体的には dart:ioPlatform.isXxx は偽装に適応する仕組みがないため使えず、flutter/foundationdefaultTargetPlatform でないといけないのですが
その辺りまではテスト時の具体的な偽装のやり方共々 下記記事に一通り書かれているのでそちらをご覧下さい。

debugDefaultTargetPlatformOverrideTargetPlatform.xxx をセットしてプラットフォーム偽装を行った際は
上記記事内にもあるようにそのテストから抜ける際に必ず debugDefaultTargetPlatformOverridenull を(再)セットする必要があり、忘れると下記のようなエラーでテストが失敗します。

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
The value of a foundation debug variable was changed by the test.

When the exception was thrown, this was the stack:
#0      debugAssertAllFoundationVarsUnset.<anonymous closure> (package:flutter/src/foundation/debug.dart:41:7)
#1      debugAssertAllFoundationVarsUnset (package:flutter/src/foundation/debug.dart:44:4)
#2      TestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:1068:12)
#3      AutomatedTestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:1525:11)  
#4      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1049:7)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)

The test description was:
  Your Test Case Name
════════════════════════════════════════════════════════════════════════════════════════════════════

ならば tearDown() でnullをセットすればいいよね、上記の記事にもそう書かれているしということで

tearDown(() {
  debugDefaultTargetPlatformOverride = null;
});

これでOKっしょ・・・と思ったのですがテスト結果変わりません。エラー内容も同じ。
えぇ? なんでナンデ?? と情報探し回ったりコード弄りまわしてみたりすることしばし、見つかった英語の情報から得た結論は
ウィジェットテストの場合 tearDown() でnullセットしてはならず、各テストの末尾にnullセット処理を都度書かないといけない でした。

回答末尾の Important: 以下をざっくり訳すと

debugDefaultTargetPlatformOverride = nulltearDown() に移したくなるだろうけどそれだと動かない
何故なら debugAssertAllFoundationVarsUnset()tearDown() より前に呼ばれるから

という感じでしょうか(若干意訳)。直前の節で

debugDefaultTargetPlatformOverride はテスト全体に影響するトップレベル変数なので各テスト終了時には null にリセットされていなければならないので debugAssertAllFoundationVarsUnset() でそのチェックを行う

とも書かれている(同)ので、ウィジェットテストでは tearDown() より前に expect(debugDefaultTargetPlatformOverride, isNull) みたいな検証がされるんだな~と理解しておけばよさそうに思いました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?