testする対象を見極める
タイトル
ページ分割
前提
同じ目的を達成できるならば、コードは少ない方が良い
適切な箇所を、適切な分だけテストする
test codeを書く前にすべきこともある
型を正しくする
今までに一度もfailしたことのないテストって存在してる価値があるのか、みたいな感覚もある(言い過ぎ)
大幅に改修する際に安心感がある
というかどのみち同じチェックを手動でやらないといけないなら、それを全部テストに書いときゃ良い、という気もする
まあそれでも必要になったときに書きゃ良い、とも言えるかもしれない
将来のための保険としてのテスト
意図せず壊れることを防ぐ
過去に生じた問題を再度起こさないため
一度バグったことがある箇所
説明としてのテスト
仕様を列挙して明示する
いくつかの満たすべき条件がある際に、それをテストで明示する
コメントで明示しても効力にならないので、型とテストで明示する
この関数が満たすべき要件は5つあると言った場合に、それぞれに対してtest caseを書いときゃ良い
読む人もそれを見れば理解できる
使い方を示す
その関数の使用方法が分かりづらいものは、テストで使い方を明示する
そもそもわかりやすくしろ、というのはもちろんあるmrsekut.icon
テストコードがなかった時の以下の時間を減らす
バグ修正にかかる時間
必要な文書を書く時間
設計にかかる時間
これらの時間よりもテストコードの記述、実行、メンテにかける時間の方が短くないと意味がない
上記の目的を達成するためにどこにtestを書くべきか
regressionを回避するためには、以下を意識する
そのtestで実行される(プロダクション)コードの量
そのコードの複雑さ
そのコードが扱っているドメインの重要性
コードベースの特に重要な部分のみをテストする
そのコードがバグったときの影響の大きさを意識する
外部から持ち込んだコード
library、API
バグが存在していることに気付かない、ということを避ける
逆に言えば、できるだけバグを検出するために書く、ということ
まずは型で検証できないところをしたい
I/Oとか
TypeScriptを使っている場合
ランタイムエラーになるようなところ
ルーティングなど、ページ遷移してるかどうかはテストしたい
これはViewの話になるのか
フォームのvalidation
逆にこの辺って型検査ってできるのかな
型システムに正規表現がアレばいける
静的検査はできると思うが
上記の目的を達成するためにどこにtestを書かないべきか
テストの内容が自明すぎるもの
例えば、JSONで表現されたtableを見て値を返す関数などは、テストしようにもそもそもそのtableが間違っていたら無意味だし、テスト書く際の認知として無意味な感じがする
code of truthみたいな
プロダクションコードと同じことを別の書き方で表現してるだけのテストは各意味がない
regressionの保護の役に立たない
逆に言えば、テストコードを見れば、ビジネス要求が導き出せる
あえてアルゴリズムをテストしてるものは除く
感覚的にバグる未来が見えない関数、みたいなのがある
上記の目的を達成するためにどういう表現のtestを書くべきか
実装の安定した部分にのみ依存するようにする
つまりpublic interface
実装に変更があった場合にテストコードが影響しないようになる
リファクタリングへの耐性
偽陽性があると、テストがfailすることの価値が下がる
手順をテストするのではなく、最終結果をテストする
ブラックボックスと捉える
コツとして、「いったんどういうロジック7日は忘れる」みたいなのありそう
それの責務だけに着目する
その関数から最終的に得られる結果は何なのか、を考える
と、いうことをやれば、どんな抽象度にも応用できる?
感覚的にはviewとかusecaseが対象になりそうな気はする
懸念点として、コーナーケースのテストがしづらそう、というのがある
複雑なロジックを3つ持っているやつをテストしようとすると、それぞれのコーナーケースを外から検証するのは難しそう
とも思うが、まあ別に必ず抽象度を上げた箇所のみをテストするというわけでもないか
テストケース自体が間違っている、ということを避ける
Test use cases, not code.
ユースケースをテストする
迅速なフィードバック
保守のしやすさ
どういうtest caseを書くべきか
どういうテストケースを選択するのが良いのか難しい
適当に選んだ正常系のケースを書けばよいのか?
それがテストケースとして選ばれる意味合いがうすすぎる
テストコードの意図が伝わりづらそう
sum(a,b)のテストケースとして、無限にある選択肢の中からsum(1,2) == 3を選んだのはなぜ??という気持ちになる
テストの良さの評価軸がいくつかある
テストとして存在する意味がある
例えば、型では表現できなかった不変条件のようなものをテストするとか
ロジックとして間違いやすそうな箇所をテストするとか
境界値とかそういうの
保守性が高い、リファクタリングしても壊れない
今実装中のそれに対して、テストが必要かどうか?を問う
自明すぎないか
抽象度を上げれば必要になりそうではないか
コツとしては、
将来、どのようにリファクタリングされるか、を考える
チェックと探索
test codeてやっているのは既知のことを高速にチェックしてるだけ
未知の部分はテストできていない
いま私は自動テストの話をしていますが、自動テストって結局のところテストじゃないよねみたいな話をよくされます。自動テストはテストを行ってるのではなくて、高速にチェックを行ってるんだよね、と言われます。
それはその通りです。テストというものは2つに分かれていて、それは「チェック」と「探索(Explore)」であると言われています。これは言い方を変えると「Known領域」(既知)と「Unknown領域」(未知)なんですね。
自動テストは既に分かっているものが、今もその通りである、ということを高速に確かめる最強の手段の一つです。既知を既知のままにし続ける。
それに対して、スキルのあるテストエンジニアが得意なものが未知のものを既知にしてくることですね。つまり、未知のバグを発見してくることです。これはものすごく価値のあることなんです。ref プロダクションコードの2軸
publicなAPI、privateなAPI
そのAPIをpublicにすることが適切なのか?を考える
いやぁ〜、にゅあんす
直接的には繋がりません。
と言われてもなあ
感覚でわかるけど、説明として適切だとは思えんmrsekut.icon
そのpublicなAPIは、以下のいずれかを満たしていないといけない
clientが目標を達成するために使う、publicな操作
clientが目標を達成するために使う、publicな状態