go测试--进阶
<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>前言</li><li>控制编译的参数<ul><li>-args</li><li>-json</li><li>-o</li></ul></li><li>控制测试的参数<ul><li>-bench regexp</li><li>-benchtime s</li><li>-cpu 1,2,4</li><li>-count n</li><li>-failfast</li><li>-list regexp</li><li>-parallel n</li><li>-run regexp</li><li>-timeout d</li><li>-v</li><li>-benchmem</li></ul></li></ul></div><p></p><h2 id="前言">前言</h2>
<p>go test有非常丰富的参数,一些参数用于控制测试的编译,另一些参数控制测试的执行。</p>
<p>有关测试覆盖率、vet和pprof相关的参数先略过,我们在讨论相关内容时再详细介绍。</p>
<h2 id="控制编译的参数">控制编译的参数</h2>
<h3 id="-args">-args</h3>
<p>指示go test把-args后面的参数带到测试中去。具体的测试函数会根据此参数来控制测试流程。</p>
<p>-args后面可以附带多个参数,所有参数都将以字符串形式传入,每个参数作为一个string,并存放到字符串切片中。</p>
<pre><code class="language-go">// TestArgs 用于演示如何解析-args参数
func TestArgs(t *testing.T) {
if !flag.Parsed() {
flag.Parse()
}
argList := flag.Args() // flag.Args() 返回 -args 后面的所有参数,以切片表示,每个元素代表一个参数
for _, arg := range argList {
if arg == "cloud" {
t.Log("Running in cloud.")
} else {
t.Log("Running in other mode.")
}
}
}
</code></pre>
<p>执行测试时带入参数:</p>
<pre><code class="language-shell">$ go test -run TestArgs -v -args "cloud"
TestMain setup.
=== RUN TestArgs
--- PASS: TestArgs (0.00s)
unit_test.go:28: Running in cloud.
PASS
TestMain tear-down.
ok gotest0.353s
</code></pre>
<p>通过参数-args指定传递给测试的参数。</p>
<h3 id="-json">-json</h3>
<p>-json 参数用于指示go test将结果输出转换成json格式,以方便自动化测试解析使用。</p>
<p>如下输出</p>
<pre><code class="language-shell">
$ go test -run TestAdd -json
{"Time":"2019-02-28T15:46:50.3756322+08:00","Action":"output","Package":"gotest","Output":"TestMain setup.\n"}
{"Time":"2019-02-28T15:46:50.4228258+08:00","Action":"run","Package":"gotest","Test":"TestAdd"}
{"Time":"2019-02-28T15:46:50.423809+08:00","Action":"output","Package":"gotest","Test":"TestAdd","Output":"=== RUN TestAdd\n"}
{"Time":"2019-02-28T15:46:50.423809+08:00","Action":"output","Package":"gotest","Test":"TestAdd","Output":"--- PASS: TestAdd (0.00s)\n"}
{"Time":"2019-02-28T15:46:50.423809+08:00","Action":"pass","Package":"gotest","Test":"TestAdd","Elapsed":0}
{"Time":"2019-02-28T15:46:50.4247922+08:00","Action":"output","Package":"gotest","Output":"PASS\n"}
{"Time":"2019-02-28T15:46:50.4247922+08:00","Action":"output","Package":"gotest","Output":"TestMain tear-down.\n"}
{"Time":"2019-02-28T15:46:50.4257754+08:00","Action":"output","Package":"gotest","Output":"ok\tgotest\t0.465s\n"}
{"Time":"2019-02-28T15:46:50.4257754+08:00","Action":"pass","Package":"gotest","Elapsed":0.465}
</code></pre>
<h3 id="-o">-o</h3>
<p>-o 参数指定生成的二进制可执行程序,并执行测试,测试结束不会删除该程序。</p>
<p>没有此参数时,go test生成的二进制可执行程序存放到临时目录,执行结束便删除。</p>
<p>如下:</p>
<pre><code class="language-shell">$ go test -run TestAdd -o TestAdd#编译成二进制文件
TestMain setup.
PASS
TestMain tear-down.
ok gotest0.439s
$ TestAdd # 直接使用二进制文件运行测试
TestMain setup.
PASS
TestMain tear-down.
</code></pre>
<p>本例中,使用-o 参数指定生成二进制文件”TestAdd”并存放到当前目录,测试执行结束后,仍然可以直接执行该二进制程序。</p>
<h2 id="控制测试的参数">控制测试的参数</h2>
<h3 id="-bench-regexp">-bench regexp</h3>
<p>go test默认不执行性能测试,使用-bench参数才可以运行,而且只运行性能测试函数。</p>
<p>其中正则表达式用于筛选所要执行的性能测试。如果要执行所有的性能测试,使用参数<code>-bench .</code>或<code>-bench=.</code>。</p>
<p>此处的正则表达式不是严格意义上的正则,而是种包含关系。</p>
<p>比如有如下三个性能测试:</p>
<ul>
<li>func BenchmarkMakeSliceWithoutAlloc(b *testing.B)</li>
<li>func BenchmarkMakeSliceWithPreAlloc(b *testing.B)</li>
<li>func BenchmarkSetBytes(b *testing.B)</li>
</ul>
<p>使用参数<code>-bench=Slice</code>,那么前两个测试因为都包含<code>Slice</code>,所以都会被执行,第三个测试则不会执行。</p>
<p>对于包含子测试的场景下,匹配是按层匹配的。举一个包含子测试的例子:</p>
<pre><code class="language-go">func BenchmarkSub(b *testing.B) {
b.Run("A=1", benchSub1)
b.Run("A=2", benchSub2)
b.Run("B=1", benchSub3)
}
</code></pre>
<p>测试函数命名规则中,子测试的名字需要以父测试名字作为前缀并以<code>/</code>连接,上面的例子实际上是包含4个测试:</p>
<pre><code class="language-shell">- Sub
- Sub/A=1
- Sub/A=2
- Sub/B=1
</code></pre>
<p>如果想执行三个子测试,那么使用参数<code>-bench Sub</code>。如果只想执行<code>Sub/A=1</code>,则使用参数<code>-bench Sub/A=1</code>。如果想执行<code>Sub/A=1</code>和<code>Sub/A=2</code>,则使用参数<code>-bench Sub/A=</code>。</p>
<h3 id="-benchtime-s">-benchtime s</h3>
<p>-benchtime指定每个性能测试的执行时间,如果不指定,则使用默认时间1s。</p>
<p>例如,执定每个性能测试执行2s,则参数为:<code>go test -bench Sub/A=1 -benchtime 2s</code>。</p>
<h3 id="-cpu-124">-cpu 1,2,4</h3>
<p>-cpu 参数提供一个CPU个数的列表,提供此列表后,那么测试将按照这个列表指定的CPU数设置GOMAXPROCS并分别测试。</p>
<p>比如<code>-cpu 1,2</code>,那么每个测试将执行两次,一次是用1个CPU执行,一次是用2个CPU执行。<br>
例如,使用命令<code>go test -bench Sub/A=1 -cpu 1,2,3,4</code> 执行测试:</p>
<pre><code class="language-shell">BenchmarkSub/A=1 1000 1256835 ns/op
BenchmarkSub/A=1-2 2000 912109 ns/op
BenchmarkSub/A=1-3 2000 888671 ns/op
BenchmarkSub/A=1-4 2000 894531 ns/op
</code></pre>
<p>测试结果中测试名后面的-2、-3、-4分别代表执行时GOMAXPROCS的数值。 如果GOMAXPROCS为1,则不显示。</p>
<h3 id="-count-n">-count n</h3>
<p>-count指定每个测试执行的次数,默认执行一次。</p>
<p>例如,指定测试执行2次:</p>
<pre><code class="language-shell">$ go test -bench Sub/A=1 -count 2
TestMain setup.
goos: windows
goarch: amd64
pkg: gotest
BenchmarkSub/A=1-4 2000 917968 ns/op
BenchmarkSub/A=1-4 2000 882812 ns/op
PASS
TestMain tear-down.
ok gotest10.236s
</code></pre>
<p>可以看到结果中也将呈现两次的测试结果。</p>
<p>如果使用-count指定执行次数的同时还指定了-cpu列表,那么测试将在每种CPU数量下执行count指定的次数。</p>
<p>注意,示例测试不关心-count和-cpu参数,它总是执行一次。</p>
<h3 id="-failfast">-failfast</h3>
<p>默认情况下,go test将会执行所有匹配到的测试,并最后打印测试结果,无论成功或失败。</p>
<p>-failfast指定如果有测试出现失败,则立即停止测试。这在有大量的测试需要执行时,能够更快的发现问题。</p>
<h3 id="-list-regexp">-list regexp</h3>
<p>-list <strong>只是列出匹配成功的测试函数,并不真正执行。而且,不会列出子函数。</strong></p>
<p>例如,使用参数”-list Sub”则只会列出包含子测试的三个测试,但不会列出子测试:</p>
<pre><code class="language-shell">$ go test -list Sub
TestMain setup.
TestSubParallel
TestSub
BenchmarkSub
TestMain tear-down.
ok gotest0.396s
</code></pre>
<h3 id="-parallel-n">-parallel n</h3>
<p>指定测试的最大并发数。</p>
<p>当测试使用t.Parallel()方法将测试转为并发时,将受到最大并发数的限制,默认情况下最多有GOMAXPROCS个测试并发,其他的测试只能阻塞等待。</p>
<h3 id="-run-regexp">-run regexp</h3>
<p>根据正则表达式执行单元测试和示例测试。正则匹配规则与-bench 类似。</p>
<h3 id="-timeout-d">-timeout d</h3>
<p>默认情况下,测试执行超过10分钟就会超时而退出。</p>
<p>如,我们把超时时间设置为1s,由本来需要3s的测试就会因超时而退出:</p>
<pre><code class="language-shell">$ go test -timeout=1s
TestMain setup.
panic: test timed out after 1s
</code></pre>
<p>设置超时可以按秒、按分和按时:</p>
<ul>
<li>按秒设置:-timeout xs或-timeout=xs</li>
<li>按分设置:-timeout xm或-timeout=xm</li>
<li>按时设置:-timeout xh或-timeout=xh</li>
</ul>
<h3 id="-v">-v</h3>
<p>默认情况下,测试结果只打印简单的测试结果,-v 参数可以打印详细的日志。</p>
<p>性能测试下,总是打印日志,因为日志有时会影响性能结果。</p>
<h3 id="-benchmem">-benchmem</h3>
<p>默认情况下,性能测试结果只打印运行次数、每个操作耗时。使用-benchmem则可以打印每个操作分配的字节数、每个操作分配的对象数。</p>
<pre><code class="language-shell">// 没有使用-benchmem
BenchmarkMakeSliceWithoutAlloc-4 2000 971191 ns/op
// 使用-benchmem
BenchmarkMakeSliceWithoutAlloc-4 2000 914550 ns/op 4654335 B/op 30 allocs/op
</code></pre>
<p>此处,每个操作的含义是放到循环中的操作,如下示例所示:</p>
<pre><code class="language-go">func BenchmarkMakeSliceWithoutAlloc(b *testing.B) {
for i := 0; i < b.N; i++ {
gotest.MakeSliceWithoutAlloc() // 一次操作
}
}
</code></pre>
</div>
<div id="MySignature" role="contentinfo">
♥永远年轻,永远热泪盈眶♥<br><br>
来源:https://www.cnblogs.com/failymao/p/15032785.html
頁:
[1]