[インデックス 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のビルドシステムに関する一般的な知識