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

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

このコミットは、Go言語の go/doc パッケージにおけるテストの網羅性を向上させることを目的としています。具体的には、go/doc パッケージが提供する異なる操作モード(Mode 型で定義される)をすべてテストするために、テストハーネスとテストデータを更新しています。これにより、go/doc が様々な設定で正しく動作することを保証します。

コミット

commit 370f4e49cdebc6450ca09ec37308b1439c87ee07
Author: Robert Griesemer <gri@golang.org>
Date:   Mon Jan 23 10:41:54 2012 -0800

    go/doc: test all operation modes
    
    Golden files have extension .d.golden where d is the mode value (0 or 1 for now)
    (i.e., testdata/file.out is now testdata/file.0.golden, and there is a new file
    testdata/file.1.golden for each testcase)
    
    R=rsc
    CC=golang-dev
    https://golang.org/cl/5573046

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

https://github.com/golang/go/commit/370f4e49cdebc6450ca09ec37308b1439c87ee07

元コミット内容

このコミットは、go/doc パッケージのテストにおいて、すべての操作モードを網羅的にテストするように変更を加えるものです。具体的には、テストの「ゴールデンファイル」(テスト結果の期待値が記述されたファイル)の命名規則を変更し、モード値(現在のところ0または1)を拡張子に含めるようにしました。これにより、各テストケースに対して、異なるモードに対応する複数のゴールデンファイル(例: testdata/file.0.goldentestdata/file.1.golden)が存在するようになります。

変更の背景

go/doc パッケージは、Goのソースコードからドキュメントを生成するための機能を提供します。このパッケージには、ドキュメント生成の挙動を制御するための様々な「モード」が存在します。例えば、エクスポートされた宣言のみを対象とするモードや、エクスポートされていない宣言も含むすべての宣言を対象とするモードなどがあります。

従来のテストでは、これらの異なるモードが十分にテストされていなかった可能性があります。特定のモードでのみ発生するバグや、モード間の相互作用による問題を見つけるためには、すべての操作モードを網羅的にテストすることが不可欠です。このコミットは、このようなテストの網羅性を高め、go/doc パッケージの堅牢性を向上させるために行われました。

前提知識の解説

go/doc パッケージ

go/doc パッケージは、Go言語の標準ライブラリの一部であり、Goのソースコードからドキュメントを抽出・生成するための機能を提供します。このパッケージは、GoのAST(抽象構文木)を解析し、パッケージ、関数、型、変数などの宣言に関する情報を抽出し、それらのドキュメンテーションコメントを処理します。go doc コマンドや godoc ツールは、この go/doc パッケージを利用してドキュメントを生成しています。

Mode 型と AllDecls 定数

go/doc パッケージには、ドキュメント生成の挙動を制御するための Mode 型が存在します。これはビットフラグとして定義されており、複数のオプションを組み合わせることができます。

このコミットで特に重要となるのは AllDecls 定数です。AllDeclsgo/doc.New 関数や go/doc.NewFromFiles 関数に渡される Mode 値の一つで、これを指定すると、パッケージレベルの宣言のうち、エクスポートされていない(小文字で始まる)宣言もドキュメントの対象に含めるようになります。通常、go/doc はエクスポートされた(大文字で始まる)宣言のみを対象としますが、AllDecls を指定することで、より詳細な内部構造のドキュメントを生成することが可能になります。

ゴールデンファイルテスト

ゴールデンファイルテスト(またはスナップショットテスト)は、ソフトウェアテストの手法の一つです。この手法では、テスト対象のコードが生成する出力(この場合は go/doc が生成するドキュメントのテキスト表現)を、事前に「正しい」とされた参照ファイル(ゴールデンファイル)と比較します。

テストの実行時に、コードが生成した出力とゴールデンファイルの内容が一致すればテストは成功です。もし一致しなければ、テストは失敗し、出力が期待値と異なることを示します。これにより、コードの変更が意図しない出力の変更を引き起こしていないかを簡単に検出できます。

このコミットでは、go/doc の異なるモードでの出力を検証するために、モードごとに異なるゴールデンファイルを導入しています。

技術的詳細

このコミットの主要な変更点は、src/pkg/go/doc/doc_test.go にあります。

  1. Test 関数のリファクタリング: 元の Test 関数は、単一のテストロジックを持っていました。このコミットでは、このロジックを test(t *testing.T, mode Mode) という新しいヘルパー関数に抽出しました。この test 関数は、go/doc.New 関数に渡す Mode 値を引数として受け取ります。

  2. ゴールデンファイルの命名規則の変更: 以前は pkg.Name + ".out" のような形式でゴールデンファイルが指定されていました。このコミットでは、fmt.Sprintf("%s.%d.golden", pkg.Name, mode) という形式に変更されました。ここで %dMode の整数値を表します。これにより、例えば a.0.goldena.1.golden のように、異なるモードに対応するゴールデンファイルを区別できるようになりました。

  3. Test 関数での複数モードのテスト実行: 新しい Test 関数は、リファクタリングされた test ヘルパー関数を複数回呼び出すようになりました。

    • test(t, 0): これはデフォルトのモード(Mode のゼロ値)でテストを実行します。通常、エクスポートされた宣言のみが対象となります。
    • test(t, AllDecls): これは AllDecls モードでテストを実行します。これにより、エクスポートされていない宣言もドキュメントの対象に含まれるようになります。
  4. テストデータの追加と変更: 既存のゴールデンファイル(例: alpha.out)は、新しい命名規則に従ってリネームされ(例: a.0.golden)、さらに AllDecls モードに対応する新しいゴールデンファイル(例: a.1.golden)が追加されました。これらの新しいゴールデンファイルには、AllDecls モードで期待される出力(例えば、BUG コメントやエクスポートされていない宣言の情報)が含まれています。

これらの変更により、go/doc パッケージのテストは、異なるドキュメント生成モードにおける挙動を網羅的に検証できるようになり、より堅牢なドキュメント生成が保証されます。

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

--- a/src/pkg/go/doc/doc_test.go
+++ b/src/pkg/go/doc/doc_test.go
@@ -7,6 +7,7 @@ package doc
 import (
 	"bytes"
 	"flag"
+	"fmt"
 	"go/parser"
 	"go/printer"
 	"go/token"
@@ -64,7 +65,7 @@ type bundle struct {
 	FSet *token.FileSet
 }
 
-func Test(t *testing.T) {
+func test(t *testing.T, mode Mode) {
 	// get all packages
 	fset := token.NewFileSet()
 	pkgs, err := parser.ParseDir(fset, dataDir, isGoFile, parser.ParseComments)
@@ -75,7 +76,7 @@ func Test(t *testing.T) {
 	// test all packages
 	for _, pkg := range pkgs {
 		importpath := dataDir + "/" + pkg.Name
-		doc := New(pkg, importpath, 0)
+		doc := New(pkg, importpath, mode)
 
 		// golden files always use / in filenames - canonicalize them
 		for i, filename := range doc.Filenames {
@@ -91,7 +92,7 @@ func Test(t *testing.T) {
 		got := buf.Bytes()
 
 		// update golden file if necessary
-		golden := filepath.Join(dataDir, pkg.Name+".out")
+		golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
 		if *update {
 			err := ioutil.WriteFile(golden, got, 0644)
 			if err != nil {
@@ -113,3 +114,8 @@ func Test(t *testing.T) {
 		}
 	}
 }
+
+func Test(t *testing.T) {
+	test(t, 0)
+	test(t, AllDecls)
+}

コアとなるコードの解説

上記の差分は、src/pkg/go/doc/doc_test.go における主要な変更を示しています。

  1. import "fmt" の追加: fmt.Sprintf を使用してゴールデンファイル名を生成するために、fmt パッケージがインポートされました。

  2. Test 関数の test 関数へのリネームと引数追加: 元の func Test(t *testing.T)func test(t *testing.T, mode Mode) に変更されました。これにより、テストロジックが Mode 型の引数を受け取るようになり、異なるモードでのテスト実行が可能になりました。

  3. doc := New(pkg, importpath, mode): go/doc.New 関数が、ハードコードされた 0 ではなく、test 関数に渡された mode 引数を使用するように変更されました。これが、異なる操作モードでドキュメントを生成する核心部分です。

  4. ゴールデンファイル名の動的な生成: golden := filepath.Join(dataDir, pkg.Name+".out")golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode)) に変更されました。これにより、テストが実行される Mode に応じて、対応するゴールデンファイル(例: a.0.goldena.1.golden)が選択または生成されるようになります。

  5. 新しい Test 関数の導入: func Test(t *testing.T) が新たに定義され、この関数が test ヘルパー関数を2回呼び出しています。

    • test(t, 0): Mode のゼロ値(デフォルトの挙動、通常はエクスポートされた宣言のみ)でテストを実行します。
    • test(t, AllDecls): AllDecls モードでテストを実行します。これにより、エクスポートされていない宣言もドキュメントの対象に含まれるようになります。

これらの変更により、go/doc パッケージのテストは、異なるドキュメント生成モードにおける挙動を網羅的に検証できるようになり、より堅牢なドキュメント生成が保証されます。

関連リンク

参考にした情報源リンク