自定义模板中使用 update_behavior: type: "skip" 不生效
Describe the Question
我的目标是为每个 handler.go 添加一个单测文件,但是当使用 hz update 更新时,我希望忽略单测文件,以便于保存我对测试函数的修改
按用户文档描述,我在自定义模板 package.yaml 生成单测文件的部分添加 update_behavior: type: "skip" 来达到这个目的。
但是结果依然覆盖了单测文件。
Reproducible Code
问题复现如下: 首先我的目录如下所示
├── Makefile
├── api
│ └── hello.proto
├── app
├── template
│ └── package.yaml
└── third_party
└── api.proto // hz 提供的注解文件
package.yaml如下
layouts:
- path: "{{.HandlerDir}}/{{.GenPackage}}/{{ToSnakeCase .ServiceName}}_test.go"
loop_service: true
update_behavior:
type: "skip" # 用于在 hz update 时跳过
body: |-
package {{.FilePackage}}
import (
"bytes"
"testing"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/test/assert"
"github.com/cloudwego/hertz/pkg/common/ut"
)
{{range $_, $MethodInfo := $.Methods}}
func Test{{$MethodInfo.Name}}(t *testing.T) {
h := server.Default()
h.{{$MethodInfo.HTTPMethod}}("{{$MethodInfo.Path}}", {{$MethodInfo.Name}})
w := ut.PerformRequest(h.Engine, "{{$MethodInfo.HTTPMethod}}", "{{$MethodInfo.Path}}", &ut.Body{Body: bytes.NewBufferString(""), Len: 1},
ut.Header{})
resp := w.Result()
assert.DeepEqual(t, 201, resp.StatusCode())
assert.DeepEqual(t, "", string(resp.Body()))
// todo edit your unit test.
}
{{end}}
hello.proto如下
syntax = "proto3";
package hello;
import "api.proto";
service hello {
rpc echo(Req) returns (Resp) { option (api.get) = "/echo"; };
}
message Req {}
message Resp {}
Makefile 如下
new:
hz new --idl api/hello.proto --mod issue -I "third_party;." --out_dir app/hello \
--customize_package=template/package.yaml --force
.PHONY: new
update:
hz update --idl api/hello.proto --mod issue -I "third_party;." --out_dir app/hello \
--customize_package=template/package.yaml
.PHONY: update
此时在根目录执行
make new
得到app/hello/biz/handler/hello/hello_test.go
//hello_test.go
package hello
import (
"bytes"
"testing"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/test/assert"
"github.com/cloudwego/hertz/pkg/common/ut"
)
func TestEcho(t *testing.T) {
h := server.Default()
h.GET("/echo", Echo)
w := ut.PerformRequest(h.Engine, "GET", "/echo", &ut.Body{Body: bytes.NewBufferString(""), Len: 1},
ut.Header{})
resp := w.Result()
assert.DeepEqual(t, 201, resp.StatusCode())
assert.DeepEqual(t, "", string(resp.Body()))
// todo edit your unit test.
}
将其略作修改如下
// hello_test.go
package hello
import (
"testing"
)
func TestEcho(t *testing.T) {
// todo edit your unit test.
}
执行
make update
hello_test.go 的修改被覆盖了,没有达到预期
Hertz version:
# hz -v
hz version v0.9.7
github.com/cloudwego/hertz v0.10.2
Environment:
The output of go env.
set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=1
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=on
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=
set GOCACHE=C:\Users\xxx\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\xxx\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\xxx\AppData\Local\Temp\go-build1522494292=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=NUL
set GOMODCACHE=C:\Users\xxx\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\xxx\go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct
set GOROOT=C:/Users/xxx/scoop/apps/go/current
set GOSUMDB=sum.golang.org
set GOTELEMETRY=on
set GOTELEMETRYDIR=C:\Users\xxx\AppData\Roaming\go\telemetry
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Users\xxx\scoop\apps\go\current\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.25.0
set GOWORK=
set PKG_CONFIG=pkg-config
试下把 update_behavior 调整成 append 模式呢
修改为 append 模式也没有效果
我修改后的package.yaml如下所示
layouts:
- path: "{{.HandlerDir}}/{{.GenPackage}}/{{ToSnakeCase .ServiceName}}_test.go"
loop_service: true
update_behavior:
type: "append" # 用于在 hz update 时跳过
append_key: "method"
insert_key: "Test{{$.Name}}"
append_tpl: |-
func Test{{.Name}}(t *testing.T) {
h := server.Default()
h.{{.HTTPMethod}}("{{.Path}}", {{.Name}})
w := ut.PerformRequest(h.Engine, "{{.HTTPMethod}}", "{{.Path}}", &ut.Body{Body: bytes.NewBufferString(""), Len: 1},
ut.Header{})
resp := w.Result()
assert.DeepEqual(t, 201, resp.StatusCode())
assert.DeepEqual(t, "", string(resp.Body()))
// todo edit your unit test.
}
body: |-
package {{.FilePackage}}
import (
"bytes"
"testing"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/test/assert"
"github.com/cloudwego/hertz/pkg/common/ut"
)
{{range $_, $MethodInfo := $.Methods}}
func Test{{$MethodInfo.Name}}(t *testing.T) {
h := server.Default()
h.{{$MethodInfo.HTTPMethod}}("{{$MethodInfo.Path}}", {{$MethodInfo.Name}})
w := ut.PerformRequest(h.Engine, "{{$MethodInfo.HTTPMethod}}", "{{$MethodInfo.Path}}", &ut.Body{Body: bytes.NewBufferString(""), Len: 1},
ut.Header{})
resp := w.Result()
assert.DeepEqual(t, 201, resp.StatusCode())
assert.DeepEqual(t, "", string(resp.Body()))
// todo edit your unit test.
}
{{end}}
可能是 --out_dir app/hello 和自定义模板有冲突,去掉之后试试呢
去掉之后可以实现期望的效果,但是如果不能使用--out_dir 指定输出目录,该如何以 monorepo 方式组织项目呢?
可能先试试手动调整路径吧。工具自定义路径和模板可能有冲突,后面我们会看下原因。
把 package.yaml 的
- path: "{{.HandlerDir}}/{{.GenPackage}}/{{ToSnakeCase .ServiceName}}_test.go"
改成
- path: "{{.ProjectDir}}/{{.HandlerDir}}/{{.GenPackage}}/{{ToSnakeCase .ServiceName}}_test.go"
可以在update时保持正确skip,因为在默认的情况下HandlerDir是 “biz/handler",而在加上out_dir 后实际目录多了一层 “/path/to/app/hello”绝对路径前缀。
hz在“biz/handler"没找到已存在的文件就重新生成覆盖了文件,而加上 {{.ProjectDir}} 后相当于指定了 out_dir,hz 就能够找到文件并识别进行 skip 操作跳过重新生成。
但是这会使得在new时产生错误路径,出现绝对路径嵌套绝对路径的问题。我认为这是不符合预期的,指定 {{.ProjectDir}} 作为绝对路径时不应该按相对路径拼接生成,为此我发起了一个 PR,希望能修复该问题。
原来如此,的确如你所说👍
@nnothing1 感谢~