- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个不是用 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
main
thread. 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/
我的Angular-Component位于一个flexbox(id =“log”)中。可以显示或隐藏flexbox。 我的组件内部有一个可滚动区域,用于显示日志消息。 (id =“message-li
我真的很困惑 有一个 phpinfo() 输出: MySQL 支持 启用 客户端 API 版本 5.5.40 MYSQL_MODULE_TYPE 外部 phpMyAdmin 显示: 服务器类型:Mar
我正在研究这个 fiddle : http://jsfiddle.net/cED6c/7/我想让按钮文本在单击时发生变化,我尝试使用以下代码: 但是,它不起作用。我应该如何实现这个?任何帮助都会很棒
我应该在“dogs_cats”中保存表“dogs”和“cats”各自的ID,当看到数据时显示狗和猫的名字。 我有这三个表: CREATE TABLE IF NOT EXISTS cats ( id
我有一个字符串返回到我的 View 之一,如下所示: $text = 'Lorem ipsum dolor ' 我正在尝试用 Blade 显示它: {{$text}} 但是,输出是原始字符串而不是渲染
我无法让我的链接(由图像表示,位于页面左侧)真正有效地显示一个 div(包含一个句子,位于中间)/单击链接时隐藏。 这是我的代码: Practice
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
最初我使用 Listview 来显示 oracle 结果,但是最近我不得不切换到 datagridview 来处理比 Listview 允许的更多的结果。然而,自从切换到数据网格后,我得到的结果越来越
我一直在尝试插入一个 Unicode 字符 ∇ 或 ▽,所以它显示在 Apache FOP 生成的 PDF 中。 这是我到目前为止所做的: 根据这个基本帮助 Apache XSL-FO Input,您
我正在使用 node v0.12.7 编写一个 nodeJS 应用程序。 我正在使用 pm2 v0.14.7 运行我的 nodejs 应用程序。 我的应用程序似乎有内存泄漏,因为它从我启动时的大约 1
好的,所以我有一些 jQuery 代码,如果从下拉菜单中选择了带有前缀 Blue 的项目,它会显示一个输入框。 代码: $(function() { $('#text1').hide();
当我试图检查 Chrome 中的 html 元素时,它显示的是 LESS 文件,而 Firefox 显示的是 CSS 文件。 (我正在使用 Bootstrap 框架) 如何在 Chrome 中查看 c
我是 Microsoft Bot Framework 的新手,我正在通过 youtube 视频 https://youtu.be/ynG6Muox81o 学习它并在 Ubuntu 上使用 python
我正在尝试转换从 mssql 生成的文件到 utf-8。当我打开他的输出 mssql在 Windows Server 2003 中使用 notepad++ 将文件识别为 UCS-2LE我使用 file
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我正在尝试执行单击以打开/关闭一个 div 的功能。 这是基本的,但是,点击只显示 div,当我点击“关闭”时,没有任何反应。 $(".inscricao-email").click(function
假设我有 2 张卡片,屏幕上一次显示一张。我有一个按钮可以用其他卡片替换当前卡片。现在假设卡 1 上有一些数据,卡 2 上有一些数据,我不想破坏它们每个上的数据,或者我不想再次重建它们中的任何一个。
我正在使用 Eloquent Javascript 学习 Javascript。 我在 Firefox 控制台上编写了以下代码,但它返回:“ReferenceError:show() 未定义”为什么?
我正在使用 Symfony2 开发一个 web 项目,我使用 Sonata Admin 作为管理面板,一切正常,但我想要做的是,在 Sonata Admin 的仪表板菜单上,我需要显示隐藏一些菜单取决
我试图显示一个div,具体取决于从下拉列表中选择的内容。例如,如果用户从列表中选择“现金”显示现金div或用户从列表中选择“检查”显示现金div 我整理了样本,但样本不完整,需要接线 http://j
我是一名优秀的程序员,十分优秀!