5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

新卒2年目のエンジニアが単体テストをやってみる

Last updated at Posted at 2019-12-17

はじめに

この記事はZOZOテクノロジーズ #2 Advent Calendar 2019の17日目の記事となります。
昨日は @sashihara さんによる2年間チームで毎週1on1に取り組んでわかった3つの効果 でした。

今年、ZOZOテクノロジーズでは全部で5つのAdvent Calendarが公開されています。

ZOZOテクノロジーズ #1 Advent Calendar 2019
ZOZOテクノロジーズ #2 Advent Calendar 2019
ZOZOテクノロジーズ #3 Advent Calendar 2019
ZOZOテクノロジーズ #4 Advent Calendar 2019
ZOZOテクノロジーズ #5 Advent Calendar 2019

様々な記事が投稿されていますので、皆様お時間有りましたら是非ご覧ください。

本記事の目的

新卒エンジニアで入社した自分はお恥ずかしいことに、今まで単体テストと呼べるものを行ったことがありませんでした。
このままではまずいと思い、単体テストなるものにチャレンジをしてみることに。
そこで、「レガシーコード改善ガイド」という本を読んで単体テスト・テストコードの重要性を理解したので、この二点に着目してみました。
それを踏まえて自分なりに今の環境でできるVBSの単体テストをやってみたので考察を載せます。

前置き

「レガシーコード改善ガイド」によると、レガシーコードというのは、 テストで保護されていない扱いにくいコード と定義されています。
テストで保護されていない扱いにくいコード がなぜ悪いのか?(エンジニア経験のある方ならなんとなく感覚でわかると思います)
「レガシーコードからの脱却」内の言葉を借りると以下です。

レガシーコードとは、バグを多く含み、壊れやすく拡張が難しいコードを指します。
このようなコードの保守と管理には多大な労力がつぎ込まれることになります。
しかも一度作ってしまったレガシーコードの質を上げるには、初めから質の高いコードを作るよりも膨大なコストがかかります。

ざっくりと聞くだけでも課題が山積みですね。。。
「レガシーコード改善ガイド」ではそんなレガシーコードを改善する・予防するためにはテストコードが必要と述べられています。

このことからテストコードを用いて、単体テストをやってみよう!と思い立ち、実際にやってみました。

環境

自分が普段扱っている言語はVBSですが、VBSには有用なテストツールがないので自前でテストコードを書いています。

テストコードを用いた単体テスト

実践してみたテストコードの一部を抜粋。(内容は多少ぼかしてます)
これが単体テストと呼べるかも怪しいですが、、、

Call IsOverTargetAmount_test()
Sub IsOverTargetAmount_test()
	Dim amount : amount = 4999
	' Dim amount : amount = Empty
	' Dim amount : amount = ""
	' Dim amount : amount = NULL
	' Dim amount : amount = "abc"
	' Dim amount : amount = -7000
	' Dim amount : amount = 4999.9999
    response.write "amount : " & amount & "<br>"
    response.write "IsOverTargetAmount : " & (IsOverTargetAmount(amount) = False) & "<br>"
End Sub

Function IsOverTargetAmount(ByVal amount)
	IsOverTargetAmount = False

	If Not (IsNumeric(amount) And amount <> "") Then
		' 引数が数値かどうかバリデーション
		Exit Function
	End If

	If amount >= 5000 Then
		IsOverTargetAmount = True
	End If
End Function

' ▼実行結果
' amount : 4999
' IsOverTargetAmount : True

単体テストにチャレンジしてみての考察

  • 可能な限り、I/Oがシンプルなものにする
    • I/Oが複雑なものはテストコードが書きづらく、レガシーコードになりやすい
    • 最低限Iは複雑でも、Oはシンプルだとテストが楽(個人的理想はBool値)
  • バリデーションは以下の値に注意する
    • 変数の型(数値なのか、文字列なのか、オブジェクトなのか)
    • 数値の場合、少数や負の整数、型の限界値(INTなら -32,768 ~ 32,767)、境界値(不等号の周辺値)
    • 空文字、Empty、NULL、Nothing 等の特定のイレギュラーになりうる値
  • テストコードはあくまで書いてあるコードが正しいことを確認する
    • 仕様(ビジネスロジック)が正しいかどうかはテストコードでは確認できない
  • DB側は単体テストが難しい、、、
    • DBとの接続が発生する場合、モック的なテストデータが必要
    • 準備が手間
  • 手戻りが手前になる
    • 結合テストフェーズになって、手戻りが発生すると厄介なのでそれを防げる
  • そもそも他と依存関係のないコードでなければ単体テストとは呼べない(単体テストをするのが難しい)
  • 単体テストにはホワイトボックス・ブラックボックステストがある

最後に

今回テストコードを書いて単体テスト(ホワイトボックステスト)を行ってみた感想としては、少なくともやる意味はあると思いました。
後戻りする機会が圧倒的に減ることメリット、主観的に完成度は上がると感じました。
しかし、プログラムの書き方や言語によってテストのハードルはかなり差が生まれるというのも実感しました。
単体テストの自動化できる言語もある中、自分でテストコードを書くのは正直工数が増える面があると思います。
また、テストのエビデンスの残し方やテストコードの管理方法等も考えなくてはなりません。
まだまだ課題は山積みですが、今後のサービスの成長に合わせて、微力ながらレガシーコード改善に取り組めればと思います。
ただ、レガシーコードでもサービスとしてここまで成長できたことは非常に尊敬しています。


明日は @mitanih さんが記事を書きます!ぜひご覧ください!

5
4
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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?