こんばんわ、hisayukiです。
ここ最近フロントまわりの作業が多く、これを期に負債の返済をしようと思いました。
すでにComponentだけで60ページくらいまで増えちゃってるんですけど、未記入のテストコードを書くことにしました・・・w
そこで少しハマったことがあるので、それについて書いていこうと思います。
状況
StripeJSが認識されない
Stripeの初期化をServiceのconstructorで行っています。
動作そのものについては問題なく、本番環境では動いているのですがテストコードではStripe()がないと怒られました。
StripeのReferenceではこう書かれてるところです。
そもそも、なぜStripe()と定義しただけで使えるのだろうか?
今まで気づかなかった・・・というか気にもしなかった。
動いていたから/(^o^)\
Service単体でテストして初めて気づきました。
npmでのInstallは型定義のみ
Stripe()がそもそもどこにあるのか調べてみた。
npmでInstallしたStripeのパッケージは@Typesの直下にしかない。
実際に見てみると、interfaceばかりでTypescript用の型定義しかない・・・
あれ、実態どこだ・・・w
実態はScriptタグで読み込む
StripeのReferenceを見てるとちゃんと書かれてました。
読まずにやってたのか、実装当時は読んでやったけど忘れたのか・・・w
こっちが実態でJavascriptで書かれています。
<script>でURLから直接読み込み、読み込み後にWindowObjectに入る挙動をします。
つまり実際に使ってるStripe()は、window.Stripe()でした。
windowがグローバルオブジェクトなので、windowは省略できちゃったんですね・・・
Service単体テストでは使えない
画面側のLoadが完了された時に初めてwindow.Stripe()が作成されます。
Serviceの単体テストでは画面側は使わないのでwindow.Stripe()は作成されない。
なのでテストでStripe()がないと怒られる
Component側のテストでもServiceを読み込む場合には同じ現象起こります。
例えば画面側のLoadが終わる前に、ServiceのconstructorでStripe()を呼び出す場合など。
どのタイミングでStripe(publishableKey)
を定義するか考えなおす必要ありますね。
今は最初に読み込まれるAppComponentにngAfterViewInit()を定義して、その中でServiceに持たせるようにしてます。
テストコード大事
TDDにおいては、後追いでテストコード書くのはあまり意味がないとされています。
そもそもTDDはアプリコードを書く前にテストコードを用意して、テストコード側で一切エラーが出ないようにするアプリコードを書くのがお作法です。
これを逆にしてしまうと、既に出来ているアプリコードが動くテストコードを書いてしまいがちになり、何を受け渡して何を返してほしいという在るべき姿をテストするコードではなくなります。
そのため、後追いでテストコードを書くのは意味がないと言われます。
それでも全く無いよりマシなのと、システム規模がデカくなるほど無いことが品質的負債になります。
今回も途中からとはいえ、認識していない動作を理解するきっかけになりましたので書いてよかったと思います。
自動テスト大事、CI/CD大事
まとめ
テストコードあれば気づけたことですが、それ以前に動いてるからいいやってなってたことが問題ですね。。。
改めてTDDの大切さをわかるきっかけになりました。
加えてAngularとTypeScriptの理解を深めるいいきっかけにもなりました!
今回はたまたまStripeのscriptでしたが、同じような読み込み方をするscriptを使う場合は注意しないとですね。
あとは、フロントエンドのテストについての切り分けができていなかったなぁと。
結局Stripeのところをどうやってテストしたのかと、フロントエンドのテストについてはまた別記事で書こうと思います。
コメント