Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 16133] ファイルの概要

このコミットは、Go言語のgoコマンドにおけるテストパッケージの挙動、特に「外部テストパッケージ」の利用方法に関するドキュメントを改善するものです。具体的には、_testサフィックスを持つパッケージがどのようにコンパイルされ、実行されるかについての説明がgo help testおよびgo help testfuncの出力に追加されました。これにより、Goのテストフレームワークの理解が深まり、開発者がより適切にテストを記述できるようになります。

コミット

commit 091970c5514567f8d44c76761f14310ae305ee86
Author: Kamil Kisiel <kamil@kamilkisiel.net>
Date:   Mon Apr 8 14:42:06 2013 +1000

    cmd/go: document usage of external test packages
    
    Fixes #5144
    
    R=golang-dev, r, dave, adg
    CC=golang-dev
    https://golang.org/cl/8171044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/091970c5514567f8d44c76761f14310ae305ee86

元コミット内容

このコミットの元々の内容は、「cmd/go: 外部テストパッケージの利用方法をドキュメント化する」というものです。これは、Goのgo testコマンドがどのように外部テストパッケージ(_testサフィックスを持つパッケージ)を扱うかについて、ユーザー向けのドキュメントが不足していた点を補うことを目的としています。コミットメッセージにはFixes #5144とありますが、Goの公式リポジトリでこの番号のIssueは見つかりませんでした。これは、古いIssueトラッカーの番号であるか、あるいは内部的な参照番号である可能性があります。

変更の背景

Go言語のテストフレームワークは、シンプルでありながら強力です。しかし、その内部的な挙動、特に「内部テストパッケージ」と「外部テストパッケージ」の違いについては、明示的なドキュメントが不足していることがありました。

Goでは、テストファイル(_test.goで終わるファイル)は、通常、テスト対象のパッケージと同じパッケージ名で宣言されます。これを「内部テストパッケージ」と呼びます。この場合、テストコードはテスト対象のパッケージの内部要素(エクスポートされていない関数や変数など)にアクセスできます。

一方で、テストファイルがテスト対象のパッケージ名に_testサフィックスを付けたパッケージ名(例: package mypackage_test)で宣言されることがあります。これを「外部テストパッケージ」と呼びます。外部テストパッケージは、テスト対象のパッケージを通常のユーザーがインポートするのと同じようにインポートします。これにより、テストコードはテスト対象のパッケージのエクスポートされた要素のみにアクセスでき、パッケージの公開APIのみをテストするのに適しています。

このコミットが行われた当時、go testコマンドのヘルプドキュメントには、この外部テストパッケージの概念と、それがどのようにコンパイル・実行されるかについての明確な説明がありませんでした。そのため、開発者が外部テストパッケージを使用する際に、その挙動を理解する上で混乱が生じる可能性がありました。このコミットは、このドキュメントのギャップを埋め、開発者がGoのテストフレームワークをより効果的に利用できるようにすることを目的としています。

前提知識の解説

Go言語のパッケージとテスト

Go言語では、コードは「パッケージ」という単位で整理されます。パッケージは、関連する機能の集合であり、再利用可能なコードの最小単位です。

Goのテストは、testingパッケージとgo testコマンドによってサポートされます。テストファイルは、慣習的にテスト対象のソースファイルと同じディレクトリに配置され、ファイル名の末尾に_test.goが付きます。

内部テストパッケージと外部テストパッケージ

Goのテストには、主に以下の2つの形式があります。

  1. 内部テストパッケージ (Internal Test Package):

    • テストファイルが、テスト対象のパッケージと同じパッケージ名で宣言されます(例: package mypackage)。
    • テストコードは、テスト対象のパッケージのエクスポートされていない(非公開の)識別子にもアクセスできます。これは、パッケージの内部実装の詳細をテストする場合に便利です。
    • go testコマンドは、テスト対象のパッケージとテストファイルをまとめて1つのバイナリとしてコンパイルし、実行します。
  2. 外部テストパッケージ (External Test Package):

    • テストファイルが、テスト対象のパッケージ名に_testサフィックスを付けたパッケージ名で宣言されます(例: package mypackage_test)。
    • テストコードは、テスト対象のパッケージをインポートして使用します(例: import "path/to/mypackage")。
    • 外部テストパッケージは、テスト対象のパッケージのエクスポートされた(公開された)識別子のみにアクセスできます。これは、パッケージの公開APIが意図した通りに動作するかどうかを検証する「ブラックボックステスト」に適しています。
    • go testコマンドは、テスト対象のパッケージとは別に、外部テストパッケージを独立したバイナリとしてコンパイルし、実行します。

go testコマンド

go testコマンドは、Goのテストを実行するための主要なツールです。このコマンドは、指定されたパッケージ内の_test.goファイルを検出し、テスト関数(TestXxx)、ベンチマーク関数(BenchmarkXxx)、および例関数(ExampleXxx)を実行します。

go testは、デフォルトで現在のディレクトリにあるパッケージをテストします。また、パッケージパスを指定して特定のパッケージをテストすることも可能です。

技術的詳細

このコミットは、go testコマンドのドキュメントに、外部テストパッケージの挙動に関する重要な情報を追加することで、Goのテストフレームワークの理解を深めることを目的としています。

Goのビルドシステムは、_testサフィックスを持つパッケージを特別に扱います。通常のパッケージとは異なり、これらのパッケージはテスト対象のパッケージとは別のコンパイル単位として扱われます。これにより、外部テストパッケージは、テスト対象のパッケージの公開APIのみに依存し、その内部実装から完全に分離されます。これは、テストの独立性を高め、リファクタリングがテストに与える影響を最小限に抑える上で非常に重要です。

このドキュメントの追加は、特にGoの初心者や、テストのベストプラクティスを学びたい開発者にとって有益です。外部テストパッケージの存在とその目的を明確にすることで、開発者はテスト戦略をより意識的に選択できるようになります。例えば、公開APIの動作保証には外部テストパッケージを、複雑な内部ロジックの検証には内部テストパッケージを使用するといった使い分けが可能になります。

また、この変更は、go testコマンドのヘルプメッセージをより包括的にすることで、ユーザーがコマンドラインから直接、必要な情報を得られるようにするというGoの設計哲学にも合致しています。

コアとなるコードの変更箇所

このコミットでは、以下の2つのファイルにそれぞれ3行ずつ、同じ内容のドキュメントが追加されています。

  1. src/cmd/go/doc.go
  2. src/cmd/go/test.go

それぞれのファイルで、既存のテストに関する説明の後に以下の行が追加されています。

--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -398,6 +398,9 @@ the file pattern "*_test.go". These additional files can contain test functions
 benchmark functions, and example functions. See 'go help testfunc' for more.
 Each listed package causes the execution of a separate test binary.
 
+Additionally, test files that declare a package with the suffix "_test" will be
+compiled and executed separately from the package test binary.
+
 By default, go test needs no arguments. It compiles and tests the package
 with source in the current directory, including tests, and runs the tests.
 
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -50,6 +50,9 @@ the file pattern "*_test.go". These additional files can contain test functions
 benchmark functions, and example functions. See 'go help testfunc' for more.
 Each listed package causes the execution of a separate test binary.
 
+Additionally, test files that declare a package with the suffix "_test" will be
+compiled and executed separately from the package test binary.
+
 By default, go test needs no arguments. It compiles and tests the package
 with source in the current directory, including tests, and runs the tests.

コアとなるコードの解説

追加された3行のドキュメントは以下の通りです。

Additionally, test files that declare a package with the suffix "_test" will be
compiled and executed separately from the package test binary.

この文は、Goのテストシステムにおける「外部テストパッケージ」の挙動を簡潔かつ明確に説明しています。

  • test files that declare a package with the suffix "_test": これは、package mypackage_testのように、テスト対象のパッケージ名に_testサフィックスを付けて宣言されたテストファイルを指します。
  • will be compiled and executed separately from the package test binary: この部分が最も重要です。これは、外部テストパッケージが、テスト対象のパッケージのテストバイナリ(内部テストパッケージを含む)とは独立してコンパイルされ、実行されることを意味します。

この説明により、ユーザーは以下の点を理解できます。

  1. 外部テストパッケージの存在: _testサフィックスを持つパッケージが特別な意味を持つこと。
  2. コンパイルの独立性: 外部テストパッケージが、テスト対象のパッケージとは別の実行可能ファイルとしてビルドされること。これにより、外部テストパッケージはテスト対象のパッケージの公開APIのみに依存し、内部実装の詳細に触れることがない「ブラックボックステスト」が可能になることが示唆されます。
  3. 実行の独立性: これらのテストが、メインのパッケージテストとは別に実行されること。

この情報は、go help testsrc/cmd/go/doc.goが参照される)とgo help testfuncsrc/cmd/go/test.goが参照される)の出力に表示されるため、開発者はコマンドラインから直接この重要な挙動について学ぶことができます。これにより、Goのテストフレームワークの透明性が向上し、開発者がより効果的にテストを設計・実装できるようになります。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメントおよびソースコード
  • Go言語のテストに関する一般的な知識
  • Goのgo testコマンドの挙動に関するコミュニティの議論 (一般的な理解に基づく)