我有一个不是用 golang 编写的生产 golang 代码和功能测试。功能测试运行编译后的二进制文件。我的生产代码的非常简化的版本在这里:main.go:
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
os.Exit(0)
}
if i%2 == 0 {
os.Exit(1)
}
time.Sleep(time.Second)
}
}
我想为我的功能测试构建覆盖率配置文件。为此,我添加了包含以下内容的 main_test.go 文件:
package main
import (
"os"
"testing"
)
var exitCode int
func Test_main(t *testing.T) {
go main()
exitCode = <-exitCh
}
func TestMain(m *testing.M) {
m.Run()
// can exit because cover profile is already written
os.Exit(exitCode)
}
并修改main.go:
package main
import (
"flag"
"fmt"
"math/rand"
"os"
"runtime"
"time"
)
var exitCh chan int = make(chan int)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
exit(0)
}
if i%2 == 0 {
fmt.Println("status 1")
exit(1)
}
time.Sleep(time.Second)
}
}
func exit(code int) {
if flag.Lookup("test.coverprofile") != nil {
exitCh <- code
runtime.Goexit()
} else {
os.Exit(code)
}
}
然后我构建覆盖二进制文件:
go test -c -coverpkg=. -o myProgram
然后我的功能测试运行这个覆盖二进制文件,如下所示:
./myProgram -test.coverprofile=/tmp/profile
6507374435908599516
PASS
coverage: 64.3% of statements in .
然后我构建了显示覆盖率的 HTML 输出:
$ go tool cover -html /tmp/profile -o /tmp/profile.html
$ open /tmp/profile.html
exit 方法永远不会显示 100% 的覆盖率,因为 if flag.Lookup("test.coverprofile") != nil。所以行 os.Exit(code) 是我的覆盖结果的一个盲点,尽管事实上,功能测试在这条线上进行并且这条线应该显示为绿色。
另一方面,如果我删除条件 if flag.Lookup("test.coverprofile") != nil,行 os.Exit(code) 将在不构建覆盖率配置文件的情况下终止我的二进制文件。
如何重写 exit() 和 main_test.go 以显示覆盖无盲点?
第一个想到的解决方案是time.Sleep():
func exit(code int) {
exitCh <- code
time.Sleep(time.Second) // wait some time to let coverprofile be written
os.Exit(code)
}
}
但这不是很好,因为会导致生产代码在退出前变慢。
最佳答案
根据我们在评论中的对话,我们的覆盖率配置文件永远不会包含该行代码,因为它永远不会被执行。
如果没有看到您的完整代码,就很难想出一个合适的解决方案,但是您可以做一些事情来增加覆盖率而不会牺牲太多。
GOLANG 的标准做法是避免测试主应用程序入口点,因此大多数专业人员将尽可能多的功能提取到其他类中,以便轻松测试它们。
GOLANG 测试框架允许您在没有主函数的情况下测试您的应用程序,但您可以在其中使用 TestMain 函数,该函数可用于测试代码需要在主函数上运行的位置线。下面是 GOLANG Testing 的一个小例子。
It is sometimes necessary for a test program to do extra setup or teardown before or after testing. It is also sometimes necessary for a test to control which code runs on the
mainthread. To support these and other cases, if a test file contains a function:func TestMain(m *testing.M)
查看 GOLANG Testing 了解更多信息。
下面是一个测试代码所有功能的示例(覆盖率为 93.3%,我们将其设为 100%)。我对您的设计做了一些更改,因为它不太适合测试,但功能仍然相同。
主要包
dofunc.go
import (
"fmt"
"math/rand"
"time"
)
var seed int64 = time.Now().UTC().UnixNano()
func doFunc() int {
rand.Seed(seed)
var code int
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
code = 0
break
}
if i%2 == 0 {
fmt.Println("status 1")
code = 1
break
}
time.Sleep(time.Second)
}
return code
}
dofunc_test.go
package main
import (
"testing"
"flag"
"os"
)
var exitCode int
func TestMain(m *testing.M) {
flag.Parse()
code := m.Run()
os.Exit(code)
}
func TestDoFuncErrorCodeZero(t *testing.T) {
seed = 2
if code:= doFunc(); code != 0 {
t.Fail()
}
}
func TestDoFuncErrorCodeOne(t *testing.T) {
seed = 3
if code:= doFunc(); code != 1 {
t.Fail()
}
}
main.go
package main
import "os"
func main() {
os.Exit(doFunc());
}
如果我们使用封面配置文件构建我们的应用程序。
$ go test -c -coverpkg=. -o example
然后运行它。
$ ./example -test.coverprofile=/tmp/profile
运行测试
1543039099823358511
2444694468985893231
6640668014774057861
6019456696934794384
status 1
PASS
coverage: 93.3% of statements in .
所以我们看到我们得到了 93% 的覆盖率,我们知道这是因为我们没有对 main 的任何测试覆盖率来解决这个问题,我们可以为它编写一些测试(这不是一个好主意) 因为代码有 os.Exit 或者我们可以重构它,所以它非常简单,功能很少,我们可以将它排除在我们的测试之外。
要从覆盖率报告中排除 main.go 文件,我们可以使用构建 tags,方法是在 main.go<> 文件。
//+build !test
有关构建标志的更多信息,请查看此链接:http://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool
这将告诉 GOLANG 该文件应该包含在存在标签 build 的构建过程中,但NOT 存在标签 test 的地方。
查看完整代码。
//+build !test
package main
import "os"
func main() {
os.Exit(doFunc());
}
我们需要构建稍微不同的覆盖应用程序。
$ go test -c -coverpkg=. -o example -tags test
运行它会是一样的。
$ ./example -test.coverprofile=/tmp/profile
我们得到下面的报告。
1543039099823358511
2444694468985893231
6640668014774057861
6019456696934794384
status 1
PASS
coverage: 100.0% of statements in .
我们现在可以构建覆盖 html。
$ go tool cover -html /tmp/profile -o /tmp/profile.html
关于go - 显示无盲点的功能测试覆盖率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39690509/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test