-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session 8: Unit Test #7
Conversation
CoreAudioTypes に関して Xcode の不具合の可能性がありますね。 あと、ViewInspectorは単体テストでSwiftUIのテストを行うもので、UIテストではない認識です。 |
なるほど! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
今朝ちらっと話した DI について早速反映しててよいですねー👏 気になったところをコメントしました!
fd9505d
to
7431a83
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
次は結構細かい部分で気になったところにコメントしました!
guard let now = DateFormatter.iso8601Full.date(from: "2020-04-01T12:00:00+09:00") else { | ||
return | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
must
return してしまうと、もしも日付文字列のタイプミスがあった場合に正しくテストができなくリスクがあるため避けた方が良いです。
明確なリスクとしては、もしも iso8601Full 内のフォーマットが変わった場合にテストが正しく実行できなくなってしまいます。そのため、最初の実装時にブレークポイントなどで手動でテストが実行されることを確認してたとしても、構造上防ぐようにしたいです。
対応案1: 強制アンラップ
まず最初に思いつくのは!
ですね。これはもしもパースできなかったらテストが失敗します。ただし、強制アンラップが失敗したというランタイムエラーがでるだけなので、テストの失敗ログとしてはもうちょっと正しいものにしたいです。
let now = DateFormatter.iso8601Full.date(from: "2020-04-01T12:00:00+09:00")!
対応案2: テストを fail させる
次に XCTFail です。これはテストを失敗させられるかつ、任意のログを残せるので案1より良いと思います。
guard let now = try DateFormatter.iso8601Full.date(from: "2020-04-01T12:00:00+09:00") else {
XCTFail("失敗した具体的な理由を書く")
}
問題
そこで問題!案2も実はベストプラクティスではなく、より良い方法がありますので探してみてください!
- ヒント1: XCTest framework がオプショナル型に関する関数をいくつかもっています
- ヒント2: XCTAssertNil と XCTAssertNotNil ではないです
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これですか...??
826065b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7765252
WeatherRequest.encode()のJSONEncoder().dateEncodingStrategyを.iso8601にすると、エンコード結果が、2020-04-01T12:00:00+09:00
ではなく、2020-04-01T03:00:00Z
となってしまいます。
APIとのやりとりはこれでも問題ないみたいなのですが、テストのこの部分だけを変えるのも納得いかないので、もし何か方法があれば教えていただきたいです...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WeatherRequest.encode()のJSONEncoder().dateEncodingStrategyを.iso8601にすると、エンコード結果が、2020-04-01T12:00:00+09:00ではなく、2020-04-01T03:00:00Zとなってしまいます。
+09:00 の JST でテストしたいのであれば、TimeZone を明示的に指定する方法を探してみてください!
Date 周りは結構難しいのですが、以下のような説明になります。
- Date は特定の日時を表している型で、内部表現は unixtime のようなものを保持しているだけ。そのため
2020-04-01T12:00:00+09:00
と2020-04-01T03:00:00Z
は同じ Date 型の値になる。 - DateFormatter / ISO8601DateFormatter は Date 型を人間が読みやすい文字列のフォーマットに変換(Date to String)またはparse(String to Date)するためのもの。そのため Locale や Timezone の指定がある。
- Locale を指定するとどこの国の日付の読み方にするかを指定できる。例えば日本は年月日を表現するときは
年/月/日
の順に書くが、アメリカだと月/日/年
の順になる。そういった表現も DateFormatter が対応してくれている。 - TimeZone は時差のことで基準となる UTC(≒ GMT) を
+00:00
またはZ
として、そこから + or - のどちらにずれているかを表現している。 - Locale と TimeZone は Date 型は意識していないことが重要。あくまでも DateFormatter を通して人間が読む時の文字列表現をどうするかという話なだけ。
- Locale を指定するとどこの国の日付の読み方にするかを指定できる。例えば日本は年月日を表現するときは
- ここら辺の話は 【Swift】Dateの王道 【日付】 が結構詳しいです。
- ただし、今は iOS 15 からサポートされた Date.FormatStyle を優先して使います。DateFormatter は実は生成コストがめちゃくちゃ高いのでキャッシュしたりする必要があるのですが、 Date.FormatStyle はその問題を解決しています。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
おそらく、.dateEncodingStrategyを.iso8601にするとGMTになってしまうので、
DateFormatterを作ってtimeZoneを指定したものを.formatted(DateFormatter)に渡してエンコードするということですよね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
acbd4d8
Encoder/Decoderを切り出して、責務を分離しました。
YumemiWeatherClientがEncoderとDecoderに依存する形で使用しています。
ab146c6
to
53905dc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM です!
Session 8: Unit Test
Updates
テスト用にForecastViewModelMockを実装ViewInspectorの導入ForecastViewのテストケースを実装Issues