英文:
How to print from go test to console without using verbose option
问题
我想从一个测试中向控制台打印一条信息,但不想看到冗长的测试输出。
我尝试使用以下方法在测试中进行打印:
fmt.Println("我的消息") // STDOUT
fmt.Fprintln(os.Stderr, "我的消息") // STDERR
t.Log("我的消息\n") // testing.T log
这些方法都会在控制台上显示相同的效果,如果使用go test -v
命令,则会显示,但如果只使用go test
命令,则不会显示。
然而,使用go test -v
命令,我还会得到所有冗长的测试输出,例如:
=== RUN My_Test
--- PASS: My_Test (0.07s)
go help testflag
命令说:
-v
详细输出:记录所有运行的测试。即使测试成功,也打印所有Log和Logf调用的文本。
但是我想要的是不记录所有运行的测试,但是仍然打印所有Log和Logf调用的文本。
有没有办法在测试中打印可见的消息,但不看到RUN
和PASS
的消息?
英文:
I want to print an informative message to console from a test, but not have the verbose test output.
I have tried printing from the test using:
fmt.Println("my message") // STDOUT
fmt.Fprintln(os.Stderr, "my message") // STDERR
t.Log("my message\n") // testing.T log
which all produce the same effect of showing in the console if go test -v
is used, but not showing if just go test
is used.
However, with go test -v
, I also get all the verbose test output like:
=== RUN My_Test
--- PASS: My_Test (0.07s)
go help testflag
says:
-v
Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds.
but what I want is to not log all tests as they are run, but still print all text from Log and Logf calls even if the test succeeds
Is there a way to print a visible message from within a test, but not see the RUN
and PASS
messages?
答案1
得分: 1
尽管这段代码在测试期间不会打印任何内容,但它会在测试结束后打印出来,这比根本不打印要好。
在你的测试文件中定义一个os.File
,用于写入消息:
var messagesFile *os.File
func messages() *os.File {
if messagesFile == nil {
messagesFile, _ = os.Create("tests.out")
}
return messagesFile
}
os.Create
会在文件不存在时创建一个新文件,否则会截断现有文件。
在你的测试中,将消息写入该文件:
messages().WriteString("my message")
使用go test
运行你的测试,然后使用cat
命令查看文件内容。在我的情况下,我使用make
命令:
test:
go test .
@cat tests.out
输出如下所示:
ok <测试路径>
my message
英文:
Although this doesn't print during the test, it prints straight after, which is better than not printing at all.
Define an os.File
in your test file to write messages to:
var messagesFile *os.File
func messages() *os.File {
if messagesFile == nil {
messagesFile, _ = os.Create("tests.out")
}
return messagesFile
}
os.Create
creates a new file if one doesn't exist, otherwise truncates the existing file.
Within your tests, write messages to that file:
messages().WriteString("my message")
Run your tests using go test
, then cat
the file. In my case, I use make
:
test:
go test .
@cat tests.out
Output looks like:
ok <path to tests>
my message
答案2
得分: 0
测试框架“劫持”了标准输出和错误流,出于明显的原因。所以无论如何,写入这些流的内容是否出现在输出中都由测试框架控制,并且除了使用“-v”标志显示或隐藏所有内容之外,它没有提供其他“自定义”选项。
你可以使用“-json”测试标志来实现:
-json
以 JSON 格式记录详细输出和测试结果。这以机器可读的格式呈现与“-v”标志相同的信息。
因此,你可以获得使用“-v”时会得到的所有输出,但是每行都有一个单独的 JSON 对象。
有了这个测试函数:
func TestMy_Test(t *testing.T) {
fmt.Println("[custom] my message from fmt.Println")
}
运行 go test -v .
的输出:
=== RUN TestMy_Test
[custom] my message from fmt.Println
--- PASS: TestMy_Test (0.00s)
PASS
ok github.com/icza/play 0.002s
运行 go test -json .
的输出:
{"Time":"2022-05-10T09:26:26.712800797+02:00","Action":"run","Package":"github.com/icza/play","Test":"TestMy_Test"}
{"Time":"2022-05-10T09:26:26.71293072+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"=== RUN TestMy_Test\n"}
{"Time":"2022-05-10T09:26:26.712946548+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"[custom] my message from fmt.Println\n"}
{"Time":"2022-05-10T09:26:26.712954637+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"--- PASS: TestMy_Test (0.00s)\n"}
{"Time":"2022-05-10T09:26:26.712958774+02:00","Action":"pass","Package":"github.com/icza/play","Test":"TestMy_Test","Elapsed":0}
{"Time":"2022-05-10T09:26:26.712964812+02:00","Action":"output","Package":"github.com/icza/play","Output":"PASS\n"}
{"Time":"2022-05-10T09:26:26.713170439+02:00","Action":"output","Package":"github.com/icza/play","Output":"ok \tgithub.com/icza/play\t0.002s\n"}
{"Time":"2022-05-10T09:26:26.713573313+02:00","Action":"pass","Package":"github.com/icza/play","Elapsed":0.003}
你可以编写一个简单的应用程序来处理和过滤这些 JSON 对象。或者你可以像过滤其他任何输出一样过滤输出。
运行 go test -json . |grep '[custom]'
的输出:
{"Time":"2022-05-10T09:28:24.197077681+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"[custom] my message from fmt.Println\n"}
如果你还想要“pass”或“fail”消息,运行 go test -json . |grep '"pass\|"fail\|\[custom\]'
的输出:
{"Time":"2022-05-10T09:29:26.069181336+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"[custom] my message from fmt.Println\n"}
{"Time":"2022-05-10T09:29:26.069189228+02:00","Action":"pass","Package":"github.com/icza/play","Test":"TestMy_Test","Elapsed":0}
{"Time":"2022-05-10T09:29:26.069199239+02:00","Action":"pass","Package":"github.com/icza/play","Elapsed":0}
英文:
The testing framework "hijacks" the standard output and error streams for obvious reasons. So no matter what, whether writing to those streams appears in the output is controlled by the testing framework, and it provides no means to "customize" it other than showing or hiding all using the -v
flag.
What you may do is use the -json
testing flag:
-json
Log verbose output and test results in JSON. This presents the
same information as the -v flag in a machine-readable format.
So you get all the output you would otherwise get with -v
, but you have a separate JSON object for each line.
Having this test function:
func TestMy_Test(t *testing.T) {
fmt.Println("[custom] my message from fmt.Println")
}
Output of go test -v .
=== RUN TestMy_Test
[custom] my message from fmt.Println
--- PASS: TestMy_Test (0.00s)
PASS
ok github.com/icza/play 0.002s
Output of go test -json .
{"Time":"2022-05-10T09:26:26.712800797+02:00","Action":"run","Package":"github.com/icza/play","Test":"TestMy_Test"}
{"Time":"2022-05-10T09:26:26.71293072+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"=== RUN TestMy_Test\n"}
{"Time":"2022-05-10T09:26:26.712946548+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"[custom] my message from fmt.Println\n"}
{"Time":"2022-05-10T09:26:26.712954637+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"--- PASS: TestMy_Test (0.00s)\n"}
{"Time":"2022-05-10T09:26:26.712958774+02:00","Action":"pass","Package":"github.com/icza/play","Test":"TestMy_Test","Elapsed":0}
{"Time":"2022-05-10T09:26:26.712964812+02:00","Action":"output","Package":"github.com/icza/play","Output":"PASS\n"}
{"Time":"2022-05-10T09:26:26.713170439+02:00","Action":"output","Package":"github.com/icza/play","Output":"ok \tgithub.com/icza/play\t0.002s\n"}
{"Time":"2022-05-10T09:26:26.713573313+02:00","Action":"pass","Package":"github.com/icza/play","Elapsed":0.003}
You can write a simple app that processes and filters these JSON objects. Or you can filter the output as you could filter any other output.
Output of go test -json . |grep '\[custom\]'
{"Time":"2022-05-10T09:28:24.197077681+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"[custom] my message from fmt.Println\n"}
If you also want the "pass" or "fail" messages, run go test -json . |grep '"pass"\|"fail"\|\[custom\]'
{"Time":"2022-05-10T09:29:26.069181336+02:00","Action":"output","Package":"github.com/icza/play","Test":"TestMy_Test","Output":"[custom] my message from fmt.Println\n"}
{"Time":"2022-05-10T09:29:26.069189228+02:00","Action":"pass","Package":"github.com/icza/play","Test":"TestMy_Test","Elapsed":0}
{"Time":"2022-05-10T09:29:26.069199239+02:00","Action":"pass","Package":"github.com/icza/play","Elapsed":0}
答案3
得分: 0
你可以创建自己的日志函数并用它在屏幕上打印输出。
func Log(args ...interface{}) {
fmt.Fprintln(os.Stdout, args...)
}
你还可以根据传递的标志条件来打印日志。
var p = flag.Bool("p", false, "Enable Local Logging")
func MyLog(args ...interface{}) {
if *p {
fmt.Fprintln(os.Stdout, args...)
}
}
示例
package main
import (
"fmt"
"testing"
"os"
"flag"
)
var p = flag.Bool("p", false, "Enable Local Logging")
func Log(args ...interface{}) {
if *p {
fmt.Fprintln(os.Stdout, args...)
}
}
func IntMin(a, b int) int {
if a < b {
return a
}
return b
}
func TestIntMinBasic(t *testing.T) {
ans := IntMin(2, -2)
if ans != -2 {
t.Errorf("IntMin(2, -2) = %d; want -2", ans)
}
}
func TestIntMinTableDriven(t *testing.T) {
var tests = []struct {
a, b int
want int
}{
{0, 1, 0},
{1, 0, 0},
{2, -2, -2},
{0, -1, -1},
{-1, 0, -1},
}
Log("Print to Screen")
for _, tt := range tests {
testname := fmt.Sprintf("%d,%d", tt.a, tt.b)
t.Run(testname, func(t *testing.T) {
ans := IntMin(tt.a, tt.b)
if ans != tt.want {
t.Errorf("got %d, want %d", ans, tt.want)
}
})
}
}
func BenchmarkIntMin(b *testing.B) {
for i := 0; i < b.N; i++ {
IntMin(1, 2)
}
}
要传递标志,你可以使用-args
。
-args
将命令行的剩余部分(-args 后面的所有内容)传递给测试二进制文件,未经解释和更改。由于此标志会消耗命令行的剩余部分,因此包列表(如果存在)必须出现在此标志之前。
命令示例:
go test -args -p
英文:
You can create you own Log function and use it for printing on screen
func Log(args ...interface{}) {
fmt.Fprintln(os.Stdout, args...)
}
You can also make it to print log based on condition passed through flag
var p = flag.Bool("p", false, "Enable Local Logging")
func MyLog(args ...interface{}) {
if *p {
fmt.Fprintln(os.Stdout, args...)
}
}
Example
package main
import (
"fmt"
"testing"
"os"
"flag"
)
var p = flag.Bool("p", false, "Enable Local Logging")
func Log(args ...interface{}) {
if *p {
fmt.Fprintln(os.Stdout, args...)
}
}
func IntMin(a, b int) int {
if a < b {
return a
}
return b
}
func TestIntMinBasic(t *testing.T) {
ans := IntMin(2, -2)
if ans != -2 {
t.Errorf("IntMin(2, -2) = %d; want -2", ans)
}
}
func TestIntMinTableDriven(t *testing.T) {
var tests = []struct {
a, b int
want int
}{
{0, 1, 0},
{1, 0, 0},
{2, -2, -2},
{0, -1, -1},
{-1, 0, -1},
}
Log("Print to Screen")
for _, tt := range tests {
testname := fmt.Sprintf("%d,%d", tt.a, tt.b)
t.Run(testname, func(t *testing.T) {
ans := IntMin(tt.a, tt.b)
if ans != tt.want {
t.Errorf("got %d, want %d", ans, tt.want)
}
})
}
}
func BenchmarkIntMin(b *testing.B) {
for i := 0; i < b.N; i++ {
IntMin(1, 2)
}
}
And to pass the flag you can use -args
> -args
Pass the remainder of the command line (everything after -args) to the test binary, uninterpreted and unchanged. Because this flag consumes the remainder of the command line, the package list (if present) must appear before this flag.
Cmd Example:
go test -args -p
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论