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?

More than 3 years have passed since last update.

Goの単体テスト 学習記録

Last updated at Posted at 2021-03-09

初めに

この記事は私がGo言語のテストを実装するまでに通った道の記録を示したものです。
どんな資料やネット記事を参考にして学習を進めたのかをメインに記載していきます。
テストこれから勉強する人の道しるべの一つとなれば幸いです。
具体的な知識は記載するURLを見てください。

テストの参考

僕がテスト学ぶ上で参考にした記事です。

単体テストとは?

Wikipediaでは以下のように記述されている。

コンピュータープログラミングでは、単体テストはソフトウェアテスト方法であり、ソースコードの個々のユニット(1つ以上のコンピュータープログラムモジュールのセットと関連する制御データ、使用手順、および操作手順)をテストして、それらが使用に適しているかどうかを判断します. wikipedia-Unit_testing

これをGo言語に当てはめてかみ砕いて説明すると、
ソースコードのパッケージ単位(model層やらhandler層やら)で単体テストを実行して、それらが使用に適しているかどうかを判断します.って感じになるかと思います。
実務では実装したコードとセットで単体テストを実装し、PRを出すことでコードの品質の保証としたりするそうです。

単体テストの他にも結合テストや機能テストがあるんですがこれらの説明は割愛します。
package単位での品質を保証するのが単体テスト(車でいうネジや歯車)、
package同士の嚙み合わせを確認するのが結合テスト(歯車の嚙み合わせ)、
機能テストは一連のある機能が正しく動作するか確認するテスト(ドアとかハンドルとか)
みたいな感じです。

DI(Dependency Injection) について

依存性の注入(いそんせいのちゅうにゅう、英: Dependency injection)とは、コンポーネント間の依存関係をプログラムのソースコードから排除するために、外部の設定ファイルなどでオブジェクトを注入できるようにするソフトウェアパターンである。wikipedia-依存性の注入

依存性の注入とありますが、オブジェクトの注入と考えた方が理解しやすいです。
Go言語でいうとstructが一番オブジェクトに近いですね。
Go言語においては各層のパッケージ間のstructの関係はインターフェースを用いて抽象化され、具体的にどのstructを使用するかはそれらのパッケージ外で記述することで、パッケージ間の結合度を低くできます。

GoでDIを利用した実装をしてみる

Go言語ではstructなどで宣言した型にメソッドを実装していくことによって、インターフェースを満たします。
つまり明示的にインターフェース実装の宣言をする必要はなく、インターフェースで定義されているメソッドすべてが任意の型に実装されていれば、その型をインターフェースを満たす型として扱うことができます。(A Tour of Go)

それを踏まえて、この記事を読むことをお勧めします。
DIを使用するメリットなども説明されていて、参考になりました。

Mock について

やっと単体テスト実装の準備が整いました。ここからは単体テストの重要項目、Mockについて学習します。
Mockとは本番でつかっている構造体をテスト用に作りかえた構造体です。
テスト対象の構造体が依存している構造体をMock構造体をに差し替えることで望むテスト条件を用意に作り出すことができます。
image.png

この記事のモックの実装方法が参考になりました。

Mockの対象

Go言語でモックすべきなのは下位パッケージのみではありません。ランダム値生成や時間に関するものなど、テストを実行するたびに変わるような部分はテスト対象の関数の外に出して、モックする必要があります。

以下ではUUIDやTimesなどのモックについて学習するうえで参考になりました。

#DB操作を含むテスト
DB操作を含むテストではDBインスタンスをどうするかの問題があります。
選択肢はテスト用にDBを用意するのか、go-sqlmockを使用するかの2択です。
詳しくは以下で述べられていました。参考になった。

go-sqlmockについてのつまづき

これは筆者の個人的なつまづきなのですが、go-sqlmockについてその呼び出し方や関数名などから不信感を抱き、
正しくは以下のようにしっかりとdatabase/sqlパッケージをモックする必要があるのでは?と思っていました。
ちゃんとgithubのリポジトリを見ていればこんな思い違いは起こさなかったのですが...

参照1:mercari.go #1 で「もう一度テストパターンを整理しよう」というタイトルで登壇しました
参照2:Goのdatabase周りのテストではinterfaceを最大限に活用しようという話

実際にはdatabase/sql/driverパッケージなどを使っていい感じにモックしてるっぽいです。
(駆け出しエンジニアの見解)

最後に

学習した内容を思い出しながら書いていたのですが、自分で断片的な内容になってしまったと反省しております。
いろいろ書き記しながら勉強して、次はもっといい内容になるよう精進します。

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?