如何使用Go进行单元测试指定App Engine的模板路径? [英] How to Specify Path of Template for App Engine with Go for Unit Testing?

查看:135
本文介绍了如何使用Go进行单元测试指定App Engine的模板路径?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个将模板呈现给输出的处理程序。

我使用内置的模板包与Go on App Engine。

  templates:= [] string {templates / head.html,templates / footer.html} 

func pageIndex(w http.ResponseWriter,r * http.Request){
tpls:= append([] string {templates / index.html},templates ...)
tpl:= template.Must(template.ParseFiles(tpls ...))
err:= tpl.ExecuteTemplate(w,index,map [string] string {
Title:Index Page,
})

if err!= nil {
http.Error(w,err.Error(),http.StatusInternalServerError)
}
}

当我运行本地开发服务器时,这工作正常。



当我运行单元测试来测试页面时,它恐慌并给了我信息:
$ b


panic:打开模板/index.html:没有这样的文件或目录[恢复]


单位t est如下:

  func TestPageIndex(t * testing.T){
inst,_:= aetest。 NewInstance(nil)
//为简洁忽略错误
推迟inst.Close()

req,_:= inst.NewRequest(GET,/,无)
resp:= httptest.NewRecorder()
pageIndex(resp,req)
}

基本上,问题在于对于单元测试,服务器无法找到模板的路径。



如何指定模板文件在运行测试时的路径是什么?

解决方案

问题是,当你运行你的应用程序时与 goapp serve ,当前目录是应用程序根目录(其中 app.yaml 驻留)。因此,通常您会提供相对于应用程序根目录的路径。



但是,当您运行测试时使用 goapp test ,当前目录始终是包含正在运行的测试文件的文件夹( * _ test.go )。如果测试文件不在应用程序根目录中(通常不是),那么在解析到另一个文件夹(包含测试文件)时,正确解析到应用程序根目录的相对路径将不起作用。



以下是针对您的问题的两个选项:

1。将工作目录更改为应用程序根目录



您可以使用 os.Chdir() 在调用使用相对路径的代码之前将工作目录更改为应用程序的根文件夹。你甚至可以把它放到 init()函数中,或者从你的测试方法中调用它(以适合你为准)。



假设您的测试文件位于以下文件夹中: [APP_ROOT] /my/package/some_test.go 。您可以像这样设置应用程序的根目录(层次结构中的两个级别):

  if err:= os.Chdir( ../ ..); err!= nil {
panic(err)
}

请注意,I在测试文件的package init函数中添加下面这行代码:

  func init()
if err := os.Chdir(../ ..); err!= nil {
panic(err)
}
}



<因为如果你在测试文件中有多个测试函数,并且你多次运行这个代码,结果将不会是你想要的(因为我们指定从当前的水平上升到2个级别)。



2。重构代码



如果要测试使用相对路径的代码,可以更改/重构代码以获取相对路径的基础,例如从测试可能改变的变量(知道当前目录是它的包含文件夹),以便在从测试运行并解析到不同的基本路径时,原始相对路径也可以工作。



例如,当您的应用程序正常运行时,这个基本路径可能是空字符串(所以这将意味着当前文件夹,在这种情况下是应用程序根目录),并且当测试运行时,你可以将它设置为应用程序的根目录(绝对路径)或类似于../ ..的第2步级别在目录层次结构中(因为当前目录是测试文件的包含文件夹)。



您也可以创建相对路径解析的基本路径,请参阅此问题以获取详细信息:如何引用相关文件从代码和测试


I'm using the built-in template package with Go on App Engine.

I have a handler that renders a template to the output.

templates := []string{"templates/head.html", "templates/footer.html"}

func pageIndex(w http.ResponseWriter, r *http.Request) {
  tpls := append([]string{"templates/index.html"}, templates...)
  tpl := template.Must(template.ParseFiles(tpls...))
  err := tpl.ExecuteTemplate(w, "index", map[string]string{
    "Title": "Index Page",
  })

  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
  }
}

When I run the local development server this works fine.

When I run the unit test to test the page, it panics and gives me the message:

panic: open templates/index.html: no such file or directory [recovered]

The unit test is as follows:

func TestPageIndex(t *testing.T) {
  inst, _ := aetest.NewInstance(nil)
  //ignoring the errors for brevity
  defer inst.Close()

  req, _ := inst.NewRequest("GET", "/", nil)
  resp := httptest.NewRecorder()
  pageIndex(resp, req)
}

Basically, the problem is that for the unit test, the server is unable to find the path of the template.

How do I specify the path for the template files when running the test?

解决方案

The problem is that when you run your app e.g. with goapp serve, the current directory is the app root (where app.yaml resides). So normally you provide paths relative to app root.

But when you run tests e.g. with goapp test, the current directory is always the folder containing the test file being run (*_test.go). If the test file is not in the app root (normally it isn't), relative paths that are correctly resolved to the app root will not work when being resolved to another folder (containing the test file).

Here are 2 options for your problem:

1. Change the working directory to the app root

You may use os.Chdir() to change the working directory to your app's root folder prior to calling code that uses relative paths. You may even put this into an init() function, or call it from your test method (whichever suits you).

Let's assume your test file is in the folder: [APP_ROOT]/my/package/some_test.go. You may set the app's root like this (2 levels up in the hierarchy):

if err := os.Chdir("../.."); err != nil {
    panic(err)
}

Note that I would add this line in a package init function in the test file like this:

func init()
    if err := os.Chdir("../.."); err != nil {
        panic(err)
    }
}

Because if you have multiple test functions in the test file and you run this code multiple times, the result will not be what you want (as we specified to go up 2 levels from the current).

2. Refactoring code

If you want to test code that uses relative paths, you may change / refactor the code to take the base of relative path e.g. from a variable which the test may change (knowing the current directory is its containing folder) so that the original relative path will also work when running from test and being resolved to a different base path.

For example this base path may be the empty string "" when your app is running normally (so it will mean the current folder which in this case is the app root), and when tests are running, you may set it to the app's root (absolute path) or something like "../.." to step 2 levels up in the directory hierarchy (because current directory is the containing folder of the test file).

You can also make the base path to which relative paths are resolved against more configurable, see this question for details: how to reference a relative file from code and tests

这篇关于如何使用Go进行单元测试指定App Engine的模板路径?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆