[インデックス 16650] ファイルの概要
このコミットは、Go言語のテストツール go test におけるコードカバレッジ計測時のパッケージ再ビルドの挙動を改善するものです。特に、go test -cover コマンド実行時に、カバレッジ計測のためにソースコードが書き換えられたパッケージに依存する他のパッケージが適切に再ビルドされない問題を解決し、テストの正確性と信頼性を向上させます。これにより、標準ライブラリのテストが go test -short -cover std で正常に実行できるようになりました。
コミット
commit 8b9c1a224be4100b44df9c83aabcf6ec4a8f7832
Author: Russ Cox <rsc@golang.org>
Date: Wed Jun 26 14:31:12 2013 -0400
cmd/go: proper rebuild of affected packages during go test
With this CL, go test -short -cover std successfully builds and
runs all the standard package tests. The tests that look a file
line numbers (log and runtime/debug) fail, because cover is
not inserting //line directives. Everything else passes.
ok cmd/api 0.038s coverage: 66.6% of statements
? cmd/cgo [no test files]
ok cmd/fix 0.043s coverage: 27.2% of statements
ok cmd/go 0.063s coverage: 2.4% of statements
? cmd/godoc [no test files]
ok cmd/gofmt 0.085s coverage: 61.3% of statements
? cmd/yacc [no test files]\n ok archive/tar 0.023s coverage: 74.2% of statements
ok archive/zip 0.075s coverage: 71.8% of statements
ok bufio 0.149s coverage: 88.2% of statements
ok bytes 0.135s coverage: 90.4% of statements
ok compress/bzip2 0.087s coverage: 85.1% of statements
ok compress/flate 0.632s coverage: 79.3% of statements
ok compress/gzip 0.027s coverage: 76.7% of statements
ok compress/lzw 0.141s coverage: 71.2% of statements
ok compress/zlib 1.123s coverage: 77.2% of statements
ok container/heap 0.020s coverage: 85.8% of statements
ok container/list 0.021s coverage: 92.5% of statements
ok container/ring 0.030s coverage: 86.5% of statements
? crypto [no test files]
ok crypto/aes 0.054s coverage: 54.3% of statements
ok crypto/cipher 0.027s coverage: 68.8% of statements
ok crypto/des 0.041s coverage: 83.8% of statements
ok crypto/dsa 0.027s coverage: 33.1% of statements
ok crypto/ecdsa 0.048s coverage: 48.7% of statements
ok crypto/elliptic 0.030s coverage: 91.6% of statements
ok crypto/hmac 0.019s coverage: 83.3% of statements
ok crypto/md5 0.020s coverage: 78.7% of statements
ok crypto/rand 0.057s coverage: 20.8% of statements
ok crypto/rc4 0.092s coverage: 70.8% of statements
ok crypto/rsa 0.261s coverage: 80.8% of statements
ok crypto/sha1 0.019s coverage: 83.9% of statements
ok crypto/sha256 0.021s coverage: 89.0% of statements
ok crypto/sha512 0.023s coverage: 88.7% of statements
ok crypto/subtle 0.027s coverage: 83.9% of statements
ok crypto/tls 0.833s coverage: 79.7% of statements
ok crypto/x509 0.961s coverage: 74.9% of statements
? crypto/x509/pkix [no test files]
ok database/sql 0.033s coverage: 75.0% of statements
ok database/sql/driver 0.020s coverage: 46.2% of statements
ok debug/dwarf 0.023s coverage: 71.5% of statements
ok debug/elf 0.035s coverage: 58.2% of statements
ok debug/gosym 0.022s coverage: 1.8% of statements
ok debug/macho 0.023s coverage: 63.7% of statements
ok debug/pe 0.024s coverage: 50.5% of statements
ok encoding/ascii85 0.021s coverage: 89.7% of statements
ok encoding/asn1 0.022s coverage: 77.9% of statements
ok encoding/base32 0.022s coverage: 91.4% of statements
ok encoding/base64 0.020s coverage: 90.7% of statements
ok encoding/binary 0.022s coverage: 66.2% of statements
ok encoding/csv 0.022s coverage: 88.5% of statements
ok encoding/gob 0.064s coverage: 82.2% of statements
ok encoding/hex 0.019s coverage: 86.3% of statements
ok encoding/json 0.047s coverage: 77.3% of statements
ok encoding/pem 0.026s coverage: 80.5% of statements
ok encoding/xml 0.039s coverage: 85.0% of statements
ok errors 0.022s coverage: 100.0% of statements
ok expvar 0.048s coverage: 72.0% of statements
ok flag 0.019s coverage: 86.9% of statements
ok fmt 0.062s coverage: 91.2% of statements
ok go/ast 0.028s coverage: 46.3% of statements
ok go/build 0.190s coverage: 75.4% of statements
ok go/doc 0.095s coverage: 76.7% of statements
ok go/format 0.036s coverage: 79.8% of statements
ok go/parser 0.075s coverage: 82.0% of statements
ok go/printer 0.733s coverage: 88.6% of statements
ok go/scanner 0.031s coverage: 86.5% of statements
ok go/token 0.062s coverage: 79.7% of statements
? hash [no test files]
ok hash/adler32 0.029s coverage: 49.0% of statements
ok hash/crc32 0.020s coverage: 64.2% of statements
ok hash/crc64 0.021s coverage: 53.5% of statements
ok hash/fnv 0.018s coverage: 75.5% of statements
ok html 0.022s coverage: 4.5% of statements
ok html/template 0.087s coverage: 83.9% of statements
ok image 0.108s coverage: 67.1% of statements
ok image/color 0.026s coverage: 20.1% of statements
ok image/draw 0.049s coverage: 69.6% of statements
ok image/gif 0.019s coverage: 65.2% of statements
ok image/jpeg 0.197s coverage: 78.6% of statements
ok image/png 0.055s coverage: 56.5% of statements
ok index/suffixarray 0.027s coverage: 82.4% of statements
ok io 0.037s coverage: 83.4% of statements
ok io/ioutil 0.022s coverage: 70.1% of statements
FAIL log 0.020s
ok log/syslog 2.063s coverage: 71.1% of statements
ok math 0.023s coverage: 76.5% of statements
ok math/big 0.235s coverage: 79.2% of statements
ok math/cmplx 0.020s coverage: 66.5% of statements
ok math/rand 0.031s coverage: 69.9% of statements
ok mime 0.022s coverage: 83.0% of statements
ok mime/multipart 0.389s coverage: 76.1% of statements
ok net 2.219s coverage: 58.0% of statements
ok net/http 4.744s coverage: 82.9% of statements
ok net/http/cgi 0.593s coverage: 68.5% of statements
ok net/http/cookiejar 0.038s coverage: 90.3% of statements
ok net/http/fcgi 0.047s coverage: 37.6% of statements
ok net/http/httptest 0.068s coverage: 68.9% of statements
ok net/http/httputil 0.058s coverage: 52.8% of statements
? net/http/pprof [no test files]
ok net/mail 0.025s coverage: 80.3% of statements
ok net/rpc 0.063s coverage: 71.5% of statements
ok net/rpc/jsonrpc 0.047s coverage: 81.3% of statements
ok net/smtp 0.032s coverage: 74.1% of statements
ok net/textproto 0.023s coverage: 66.0% of statements
ok net/url 0.020s coverage: 78.2% of statements
ok os 4.729s coverage: 73.3% of statements
ok os/exec 39.620s coverage: 65.1% of statements
ok os/signal 0.541s coverage: 89.9% of statements
ok os/user 0.022s coverage: 62.2% of statements
ok path 0.018s coverage: 90.8% of statements
ok path/filepath 10.834s coverage: 88.4% of statements
ok reflect 0.055s coverage: 83.2% of statements
ok regexp 0.084s coverage: 75.5% of statements
ok regexp/syntax 0.547s coverage: 85.2% of statements
ok runtime 4.755s coverage: 75.9% of statements
? runtime/cgo [no test files]
FAIL runtime/debug 0.018s
ok runtime/pprof 0.368s coverage: 8.5% of statements
? runtime/race [no test files]
ok sort 0.059s coverage: 97.7% of statements
ok strconv 0.315s coverage: 95.6% of statements
ok strings 0.147s coverage: 96.1% of statements
ok sync 0.083s coverage: 56.7% of statements
ok sync/atomic 0.035s coverage: 0.0% of statements
ok syscall 0.043s coverage: 24.0% of statements
ok testing 0.018s coverage: 24.0% of statements
? testing/iotest [no test files]
ok testing/quick 0.062s coverage: 83.2% of statements
ok text/scanner 0.020s coverage: 91.5% of statements
ok text/tabwriter 0.021s coverage: 90.4% of statements
ok text/template 0.052s coverage: 81.1% of statements
ok text/template/parse 0.024s coverage: 86.1% of statements
ok time 2.431s coverage: 88.8% of statements
ok unicode 0.024s coverage: 92.1% of statements
ok unicode/utf16 0.017s coverage: 97.3% of statements
ok unicode/utf8 0.019s coverage: 97.4% of statements
? unsafe [no test files]
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/10586043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8b9c1a224be4100b44df9c83aabcf6ec4a8f7832
元コミット内容
cmd/go: proper rebuild of affected packages during go test
With this CL, go test -short -cover std successfully builds and
runs all the standard package tests. The tests that look a file
line numbers (log and runtime/debug) fail, because cover is
not inserting //line directives. Everything else passes.
変更の背景
Go言語の go test コマンドは、パッケージのテストを実行するための主要なツールです。これに -cover フラグを付けることで、コードカバレッジを計測できます。コードカバレッジを計測するために、go test -cover はテスト対象のGoソースファイルを一時的に書き換えます。具体的には、各ステートメントの実行を記録するための計測コード(プロファイリングフック)を挿入します。
このコミットが導入される以前は、go test -cover を実行した際に、カバレッジ計測のために書き換えられたパッケージに依存する他のパッケージが、その変更を認識して適切に再ビルドされないという問題がありました。Goのビルドシステムは、依存関係が変更された場合にのみ再ビルドを行うように最適化されていますが、カバレッジ計測によるソースコードの内部的な変更が、ビルドシステムに依存関係の変更として適切に伝わらないケースがあったと考えられます。
この問題は、特に標準ライブラリのような相互に複雑な依存関係を持つ大規模なコードベースで顕著でした。コミットメッセージにあるように、go test -short -cover std(標準ライブラリのテストをカバレッジ計測付きで短時間実行する)が正常に動作しないという具体的な問題が発生していました。これは、カバレッジ計測が有効な状態でテストを実行すると、ビルドエラーや、誤ったカバレッジ結果、あるいはテストの失敗につながる可能性があったことを示唆しています。
このコミットの目的は、go test -cover が実行された際に、カバレッジ計測のために変更されたパッケージだけでなく、そのパッケージに推移的に依存するすべてのパッケージが、テスト環境内で正しく再ビルドされるように go コマンドのビルドロジックを修正することでした。これにより、カバレッジ計測の正確性と、テスト実行の信頼性が向上します。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念とツールに関する知識が必要です。
-
Goパッケージと依存関係:
- Goのコードは「パッケージ」という単位で整理されます。各パッケージは、
importステートメントを通じて他のパッケージに依存することができます。 - Goのビルドシステムは、これらの依存関係を解決し、必要なパッケージを適切な順序でビルドします。
- パッケージは、そのソースコードが置かれているディレクトリによって識別されます(例:
fmt,net/http)。
- Goのコードは「パッケージ」という単位で整理されます。各パッケージは、
-
go testコマンド:go testは、Goパッケージのテストを実行するためのコマンドです。- テストファイルは、
_test.goというサフィックスを持ち、テスト対象のパッケージと同じディレクトリに配置されます。 go testは、テスト対象のパッケージとテストファイルをコンパイルし、テストバイナリを生成して実行します。- 内部テストと外部テスト:
- 内部テスト: テスト対象のパッケージと同じパッケージ名を持つテストファイル(例:
package mypackage)。これらのテストは、テスト対象パッケージの内部要素(非エクスポートされた関数や変数)にアクセスできます。 - 外部テスト: テスト対象のパッケージ名に
_testサフィックスを付けたパッケージ名を持つテストファイル(例:package mypackage_test)。これらのテストは、テスト対象パッケージを外部からインポートする形でテストし、エクスポートされた要素のみにアクセスできます。これは、ユーザーがパッケージをインポートして使用する際の挙動をシミュレートするのに役立ちます。
- 内部テスト: テスト対象のパッケージと同じパッケージ名を持つテストファイル(例:
-
コードカバレッジ (
go test -cover):-coverフラグは、go testにコードカバレッジ計測を有効にするよう指示します。- カバレッジ計測では、Goツールチェーンがテスト対象のソースコードを一時的に書き換え、各ステートメントが実行されたかどうかを追跡するコードを挿入します。このプロセスは「インストルメンテーション」と呼ばれます。
- インストルメンテーションされたコードは、実行時にカバレッジデータを生成し、テスト終了後にそのデータがレポートされます。
- このインストルメンテーションは、ソースコードの抽象構文木(AST)レベルで行われ、元のソースコードとは異なるバイナリが生成されます。
-
Goのビルドキャッシュと再ビルドの仕組み:
- Goのビルドシステムは、ビルド時間を短縮するためにビルドキャッシュを利用します。
- パッケージの依存関係やソースコードが変更されていない場合、Goは以前のビルド結果を再利用します。
- しかし、ソースコードが変更された場合、Goは影響を受けるパッケージとその依存パッケージを再ビルドする必要があります。この再ビルドのトリガーが適切に機能しないと、古いバージョンの依存パッケージが使用されたり、ビルドエラーが発生したりする可能性があります。
-
//lineディレクティブ://lineディレクティブは、Goコンパイラに対して、その後のコードの行番号とファイル名を変更するよう指示する特殊なコメントです。- コード生成ツール(例えば、
go generateや、このケースでのカバレッジツール)が元のソースコードを変換する際に、デバッグ情報やエラーメッセージが元のソースコードの正確な位置を指すようにするために使用されます。 - コミットメッセージで「
logとruntime/debugのテストが失敗するのは、coverが//lineディレクティブを挿入していないため」とあるのは、カバレッジツールがソースコードを書き換えた際に、元の行番号情報を保持するための//lineディレクティブを適切に挿入していなかったため、行番号に依存するテストが誤動作したことを示しています。このコミットの直接の修正範囲外ですが、カバレッジツールの課題の一つとして言及されています。
技術的詳細
このコミットの核心は、go test -cover が有効な場合に、テスト対象パッケージのソースコードがインストルメンテーションによって変更された際に、その変更が依存パッケージに適切に伝播し、再ビルドがトリガーされるようにすることです。
以前の go test の実装では、カバレッジ計測のためにパッケージ P のソースコードが書き換えられた場合、P を直接インポートするテストバイナリは新しい P を使用するようにビルドされました。しかし、P をインポートするパッケージ Q があり、さらに Q をインポートするパッケージ R があるような推移的な依存関係の場合、R が Q をビルドする際に、Q が古いバージョンの P に依存していると見なしてしまう可能性がありました。これは、Goのビルドシステムが、パッケージの変更を検出するために、主にエクスポートされたメタデータ(APIシグネチャなど)やファイルハッシュを使用するためです。カバレッジ計測による内部的な変更は、必ずしもこれらの検出メカニズムによって「変更」として認識されるとは限りませんでした。
このコミットは、この問題を解決するために src/cmd/go/test.go に recompileForTest という新しい関数を導入しました。
recompileForTest 関数の主なロジックは以下の通りです。
-
パッケージのクローンと再マッピング:
recompileForTestは、テスト対象のパッケージpreal(元のパッケージ)と、カバレッジ計測のためにインストルメンテーションされたptest(テスト用のパッケージ)を受け取ります。pmain(テストメインパッケージ)とpxtest(外部テストパッケージ、もしあれば)の依存関係グラフを走査します。prealに推移的に依存するすべてのパッケージpについて、そのパッケージの「クローン」を作成します。このクローンは、元のパッケージの情報をコピーしつつ、いくつかのビルド関連のプロパティを変更します。mマップを使用して、元のパッケージからクローンされたパッケージへのマッピングを保持し、重複してクローンを作成しないようにします。
-
ビルドプロパティの書き換え:
- クローンされたパッケージ
p1のpkgdirを、テスト用の作業ディレクトリ (testDir) に設定します。これにより、これらのパッケージが通常のGoモジュールキャッシュではなく、テスト専用のディレクトリにビルドされるようになります。 targetを空に設定し、fakeをtrueに、forceLibraryをtrueに設定します。これらは、Goのビルドシステムに対して、これらのパッケージが一時的なテスト目的でビルドされるものであり、ライブラリとして扱われるべきであることを示唆します。Staleフラグをtrueに設定します。これは、Goのビルドシステムに対して、このパッケージが「古くなっている」と見なし、強制的に再ビルドする必要があることを明示的に伝えます。- 最も重要なのは、クローンされたパッケージの
importsリストを再帰的に走査し、依存するパッケージも必要に応じてクローンされたバージョンに置き換えることです。これにより、prealに依存するQが、ptestに依存するように変更され、さらにQに依存するRも、変更されたQに依存するように連鎖的に変更されます。
- クローンされたパッケージ
-
強制的な再ビルド:
recompileForTestは、pmainとpxtest(もしあれば)に対してrewrite関数を適用します。これにより、テスト実行に必要なすべてのパッケージが、カバレッジ計測のために変更されたパッケージの正しいバージョンに依存するように、その依存関係グラフが「書き換え」られます。- この書き換えと
Stale = trueの設定により、Goのビルドシステムは、これらのパッケージが変更されたと認識し、テスト実行のために必要なすべての依存パッケージを、カバレッジ計測が適用された状態で再ビルドします。
このアプローチにより、カバレッジ計測が有効な場合でも、Goのビルドシステムが依存関係の変更を正確に検出し、必要なすべてのパッケージを再ビルドするようになります。これにより、go test -cover がより堅牢になり、複雑な依存関係を持つプロジェクトでも正確なカバレッジ結果が得られるようになりました。
src/cmd/go/build.go の変更は、builder.action メソッドにおける objdir と objpkg の計算ロジックを微調整するものです。p.pkgdir が設定されている場合はそれを使用し、そうでない場合は b.work を使用するように変更されています。これは、recompileForTest で pkgdir がテスト用の作業ディレクトリに設定されるようになったことと関連しており、ビルドアーティファクトの出力先をより柔軟に制御できるようにするための変更と考えられます。
コアとなるコードの変更箇所
このコミットによる主要なコード変更は、以下の2つのファイルに集中しています。
-
src/cmd/go/build.go:func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *actionメソッド内で、a.objdirとa.objpkgの計算ロジックが変更されました。- 変更前:
a.objdir = filepath.Join(b.work, a.p.ImportPath, "_obj") + string(filepath.Separator) a.objpkg = buildToolchain.pkgpath(b.work, a.p) - 変更後:
work := p.pkgdir if work == "" { work = b.work } a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator) a.objpkg = buildToolchain.pkgpath(work, a.p) - この変更により、
objdirとobjpkgのパスを決定する際に、パッケージのpkgdirフィールドが優先的に使用されるようになりました。pkgdirが空の場合は、従来のb.workがフォールバックとして使用されます。
-
src/cmd/go/test.go:func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error)メソッド内で、複数の変更が行われました。- 削除されたコードブロック:
- 以前は、カバレッジモードでパッケージ
pのソースが書き換えられた場合に、pをインポートする他のパッケージがpに推移的に依存していると、カバレッジ分析が不可能であるというエラーを返すロジックがありました。このブロックが削除されました。
// In coverage mode, we rewrite the package p's sources. // All code that imports p must be rebuilt with the updated // copy, or else coverage will at the least be incomplete // (and sometimes we get link errors due to the mismatch as well). // The external test itself imports package p, of course, but // we make sure that sees the new p. Any other code in the test // - that is, any code imported by the external test that in turn // imports p - needs to be rebuilt too. For now, just report // that coverage is unavailable. if testCover && contains(p1.Deps, p.ImportPath) { return nil, nil, nil, fmt.Errorf("coverage analysis cannot handle package (%s_test imports %s imports %s)", p.Name, path, p.ImportPath) } - 以前は、カバレッジモードでパッケージ
testCoverとdeclareCoverVarsの適用箇所の変更:testCoverとdeclareCoverVarsのロジックが、元のパッケージpではなく、テストパッケージptestに適用されるように移動されました。
recompileForTest関数の追加と呼び出し:func recompileForTest(pmain, preal, ptest, pxtest *Package, testDir string)という新しい関数が追加されました。- この関数は、
testメソッド内でptest != p && testCoverの条件が満たされる場合に呼び出されます。これは、テスト対象のパッケージがカバレッジ計測のために変更され、かつカバレッジが有効な場合に、依存パッケージの再ビルドが必要であることを意味します。 recompileForTestの内部では、cloneとrewriteという2つのヘルパー関数が定義されています。cloneは、指定されたパッケージのコピーを作成し、そのコピーをmマップに保存します。rewriteは、パッケージのpkgdirをtestDirに設定し、targetを空、fakeをtrue、forceLibraryをtrue、Staleをtrueに設定します。また、そのパッケージがインポートする他のパッケージに対しても再帰的にcloneを呼び出します。
recompileForTestは、pmainとpxtest(もしあれば)に対してrewriteを呼び出すことで、テスト環境内の依存関係グラフを再構築し、必要なパッケージが強制的に再ビルドされるようにします。
コアとなるコードの解説
このコミットの主要な変更は、go test -cover が有効な場合のGoのビルドシステムの挙動を根本的に改善することにあります。
-
src/cmd/go/build.goの変更:objdirとobjpkgは、Goのビルドプロセスにおいて、コンパイルされたオブジェクトファイルやパッケージアーカイブが一時的に保存されるディレクトリと、そのパッケージの内部的なパスを決定するために使用されます。work := p.pkgdir; if work == "" { work = b.work }という変更は、パッケージpにpkgdirが設定されている場合(これは通常、テストのために一時的に作成されたパッケージの場合に設定されます)は、そのpkgdirを優先的に使用することを意味します。- これにより、
recompileForTest関数によってテスト専用の作業ディレクトリに再マッピングされたパッケージが、その新しい場所でビルドされるようになります。これは、通常のビルドキャッシュとは分離された、テスト固有のビルド環境を確立するために重要です。
-
src/cmd/go/test.goの変更:- 旧カバレッジ分析の制限の削除: 以前のコードブロックは、カバレッジ計測が推移的な依存関係を持つパッケージで正しく機能しないという既知の制限を回避するためのものでした。このコミットがその問題を解決したため、この制限は不要となり、関連するエラーチェックが削除されました。これは、新しい
recompileForTestロジックがこの問題を解決したことの直接的な証拠です。 testCoverとdeclareCoverVarsの適用箇所の移動:testCoverはカバレッジ計測が有効かどうかを示すフラグです。declareCoverVarsは、カバレッジ計測のためにソースコードに挿入される変数(どのステートメントが実行されたかを記録するためのもの)を宣言する処理です。- これらのロジックが、元のパッケージ
pではなく、テストパッケージptestに適用されるように変更されたのは、カバレッジ計測のインストルメンテーションが、テスト実行のために特別に用意されたptestのインスタンスに対して行われるべきであることを明確にするためです。これにより、元のパッケージのビルドには影響を与えず、テスト実行時のみカバレッジ計測が適用されるようになります。
recompileForTest関数の導入:- これがこのコミットの最も重要な部分です。この関数は、
go test -coverが有効な場合に、テスト対象のパッケージprealがインストルメンテーションによって変更された際に、その変更が依存関係グラフ全体に適切に伝播するようにします。 clone関数は、パッケージのディープコピーを作成し、そのコピーをtestDir(テスト専用の作業ディレクトリ)にマッピングします。これにより、元のパッケージとは独立した、カバレッジ計測済みのパッケージのバージョンが作成されます。rewrite関数は、クローンされたパッケージのビルド関連のメタデータ(pkgdir,target,fake,forceLibrary,Stale)を更新します。pkgdir = testDir: パッケージのビルド出力先をテスト専用ディレクトリに強制します。target = "": ビルドターゲットをリセットします。fake = true: このパッケージが一時的な目的で作成された「偽の」パッケージであることを示します。forceLibrary = true: このパッケージが実行可能ファイルではなく、ライブラリとしてビルドされるべきであることを強制します。Stale = true: これが最も重要で、Goのビルドシステムに対して、このパッケージが「古くなっている」と見なし、強制的に再ビルドする必要があることを明示的に伝えます。これにより、依存関係グラフ内のすべての関連パッケージが、カバレッジ計測済みのバージョンにリンクされるようになります。
recompileForTestは、pmain(テストのメインパッケージ)とpxtest(外部テストパッケージ)の依存関係を再帰的に走査し、prealに推移的に依存するすべてのパッケージをクローンし、その依存関係をptest(カバレッジ計測済みのprealのバージョン)にリダイレクトします。これにより、テスト実行時にすべてのコードがカバレッジ計測が有効な状態でビルドされ、実行されることが保証されます。
- これがこのコミットの最も重要な部分です。この関数は、
- 旧カバレッジ分析の制限の削除: 以前のコードブロックは、カバレッジ計測が推移的な依存関係を持つパッケージで正しく機能しないという既知の制限を回避するためのものでした。このコミットがその問題を解決したため、この制限は不要となり、関連するエラーチェックが削除されました。これは、新しい
この一連の変更により、go test -cover は、複雑な依存関係を持つGoプロジェクトにおいても、より正確で信頼性の高いコードカバレッジ計測を提供できるようになりました。
関連リンク
- Go Command Documentation: https://pkg.go.dev/cmd/go
- Go Test Documentation: https://pkg.go.dev/cmd/go#hdr-Test_packages
- Go Code Coverage: https://go.dev/blog/cover (これはブログ記事ですが、Goのカバレッジツールの仕組みについて詳しく解説されています)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード(特に
src/cmd/go/ディレクトリ) - Go言語のコミット履歴とコードレビューコメント
- Go Code Coverageのブログ記事
- Goのビルドシステムに関する一般的な知識