Go代码在go test和go run中的行为不同。

huangapple go评论93阅读模式
英文:

Go Code behaves differently in go test vs go run

问题

我在我的Ubuntu 12.04.1笔记本上运行go 1.0.3,并遇到了一个问题,即如果我在main()中运行一些代码,它的行为与使用go test运行它时完全不同。

这是我的示例:
从main.go

package main

import (
    "image"
    "image/jpeg"
    "fmt"
    "myproj/htmlutil"
    [一些导入已删除]
)

func main() {
    img, err := htmlutil.GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")

    if err != nil {
        fmt.Println("There was a problem ",err)
    }
    fmt.Println("Bounds were ",img.Bounds())
}

从myproj/htmlutil_test.go

package htmlutil

import (
    "image"
    "fmt"
    "testing"
    [一些导入已删除]
)

func TestGetImageFromURL(t *testing.T){
    img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")

    if err != nil {
        t.Fatalf("There was a problem %q",err)
    }
    fmt.Println("Bounds were ",img.Bounds())
}

它们调用的函数GetResizedImageFromWeb()在myproj/htmlutil.go中:

package htmlutil

import (
    "errors"
    "fmt"
    "image"
    "io/ioutil"
    "net/http"
    [一些导入已删除]
)

func GetResizedImageFromWeb(imageURL string) (image.Image, error) {
    resp, err := http.Get(imageURL)
    if err != nil {
        return nil, errors.New(fmt.Sprint("There was a problem reading the site %q Debug[%s]",imageURL, err))
    }
    defer resp.Body.Close()
    //使用image的通用解码器解码图像
    image, s, err := image.Decode(resp.Body)
    if err != nil {
        return nil, err
    }

    return resizeImage(image), nil
}

当我从命令行运行"go run main.go"时,我可以看到来自URL的图像的边界,并且如果需要,可以使用main.go中的一个函数将其保存为jpg文件。 但是,当我从htmlutil包运行"go test"时,我收到以下错误:

There was a problem "image: unknown format"

是什么原因导致这个问题只在单元测试中失败?我做错了什么?

我唯一的猜测是由于某种原因,在测试场景中html.Get()没有返回所有数据,但我仍然对为什么会发生这种情况感到困惑。

英文:

I'm running go 1.0.3 on my Ubuntu 12.04.1 Laptop and I've stumbled upon a problem where if I run some code in main(), it behaves much more differently than if I run it with go test.

Here's my example:
From main.go

package main

import (
	"image"
	"image/jpeg"
	"fmt"
	"myproj/htmlutil"
	[some imports removed]
)

func main() {
	img, err := htmlutil.GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")

	if err != nil {
		fmt.Println("There was a problem ",err)
   	}
	fmt.Println("Bounds were ",img.Bounds())
}

From myproj/htmlutil_test.go

package htmlutil

import (
	"image"
	"fmt"
	"testing"
	[some imports removed]
)

func TestGetImageFromURL(t *testing.T){
	img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")

	if err != nil {
		t.Fatalf("There was a problem %q",err)
	}
	fmt.Println("Bounds were ",img.Bounds())
}

and the function that they call, GetResizedImageFromWeb(), is in myproj/htmlutil.go:

package htmlutil

import (
    "errors"
    "fmt"
    "image"
    "io/ioutil"
    "net/http"
    [some imports removed]
)

func GetResizedImageFromWeb(imageURL string) (image.Image, error) {
	resp, err := http.Get(imageURL)
	if err != nil {
		return nil, errors.New(fmt.Sprint("There was a problem reading the site %q Debug[%s]",imageURL, err))
	}
	defer resp.Body.Close()
	//Decode the image using image's general purpose decoder
	image, s, err := image.Decode(resp.Body)
	if err != nil {
		return nil, err
	}

	return resizeImage(image), nil
}

When I run "go run main.go" from the command line, I see the bounds of the image from the url and can save it as a jpg file on disk if I want using a function in main.go. However, when I run "go test" from the htmlutil package, I get the following error:

There was a problem "image: unknown format"

What is causing the problem to only fail in the unit tests? What am I doing wrong?

My only guess is that for what ever reason, the html.Get() isn't returning all the data in the testing scenario, but I'm still baffled as to why that happens.

答案1

得分: 4

在测试中,你应该确实检查函数调用的结果。

测试在控制台上使用/dev/null运行。因此,fmt / log输出是不可见的。你应该在htmlutil_test.go中做类似以下的事情:

func TestMain(t *testing.T) {
    img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")
    if err != nil {
        t.Error("There was a problem ", err)
    }

    bounds := image.Rectangle{
        image.Point{0, 0},
        image.Point{616, 462}}

    if img.Bounds() != bounds {
        t.Error("Incorrect Bounds were ", img.Bounds())
    }

}

我只是按照你的代码进行了复制:

main.go

package main

import (
    "errors"
    "fmt"
    "image"
    _ "image/jpeg"
    "net/http"
)

func GetResizedImageFromWeb(imageURL string) (image.Image, error) {
    resp, err := http.Get(imageURL)
    if err != nil {
        return nil, errors.New(fmt.Sprint("There was a problem reading the site %q Debug[%s]", imageURL, err))
    }
    defer resp.Body.Close()
    //Decode the image using image's general purpose decoder
    image, _, err := image.Decode(resp.Body)
    if err != nil {
        return nil, err
    }

    return image, nil
}

func main() {
    img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")

    if err != nil {
        fmt.Println("There was a problem ", err)
    }
    fmt.Println("Bounds were ", img.Bounds())
}

main_test.go

package main

import (
    "image"
    "log"
    "testing"
)

func TestMain(t *testing.T) {
    img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")
    if err != nil {
        t.Error("There was a problem ", err)
    }

    bounds := image.Rectangle{
        image.Point{0, 0},
        image.Point{616, 462}}

    if img.Bounds() != bounds {
        t.Error("Incorrect Bounds were ", img.Bounds())
    }
}

go test的输出:

PASS
ok   test 0.843s

我的go版本是go version devel +87f67aadaed6 Sat Dec 22 17:41:00 2012 -0800 darwin/amd64

英文:

In tests you should really check for the results of your function calls.

Tests run with /dev/null on console. Therefore fmt / log outputs are not visible. You should do something like the following in htmlutil_test.go

func TestMain(t *testing.T) {
	img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")
	if err != nil {
		t.Error("There was a problem ", err)
	}

	bounds := image.Rectangle{
		image.Point{0, 0},
		image.Point{616, 462}}

	if img.Bounds() != bounds {
		t.Error("Incorrect Bounds were ", img.Bounds())
	}

}

I just copied your code as follows:

main.go

package main

import (
	"errors"
	"fmt"
	"image"
	_ "image/jpeg"
	"net/http"
)

func GetResizedImageFromWeb(imageURL string) (image.Image, error) {
	resp, err := http.Get(imageURL)
	if err != nil {
		return nil, errors.New(fmt.Sprint("There was a problem reading the site %q Debug[%s]", imageURL, err))
	}
	defer resp.Body.Close()
	//Decode the image using image's general purpose decoder
	image, _, err := image.Decode(resp.Body)
	if err != nil {
		return nil, err
	}

	return image, nil
}

func main() {
	img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")

	if err != nil {
		fmt.Println("There was a problem ", err)
	}
	fmt.Println("Bounds were ", img.Bounds())
}

main_test.go

package main

import (
	"image"
	"log"
	"testing"
)

func TestMain(t *testing.T) {
	img, err := GetResizedImageFromWeb("http://img.foodnetwork.com/FOOD/2011/05/04/FNM_060111-OOT-B005_s4x3.jpg")
	if err != nil {
		t.Error("There was a problem ", err)
	}

	bounds := image.Rectangle{
		image.Point{0, 0},
		image.Point{616, 462}}

	if img.Bounds() != bounds {
		t.Error("Incorrect Bounds were ", img.Bounds())
	}
}

The output of go test

PASS
ok  	test	0.843s

my go version is go version devel +87f67aadaed6 Sat Dec 22 17:41:00 2012 -0800 darwin/amd64

答案2

得分: 2

我尝试了rputikar的解决方案(使用t.Fatal()代替fmt.Println()),但没有帮助。

我注意到rputikar在导入方面与我有些微妙的不同。我的htmlutil.go中的导入看起来像这样:

package htmlutil    

import (
	"errors"
	"fmt"
	"image"
	"io/ioutil"
	[一些导入被删除]
	"net/http"
)

但是我的main.go和rputikar的main_test.go都包含了一个额外的导入,"image/jpeg"。所以,我将它添加到我的htmlutil.go的导入列表中,问题就解决了。我想我会添加**"_ image/png""_ image/gif"**以便未来使用。

英文:

I attempted rputikar's solution (use t.Fatal() instead of fmt.Println()), but that didn't help.

I did notice that rputikar was doing something subtly different with his imports than I was. My imports in the htmlutil.go looked like:

package htmlutil    

import (
	"errors"
	"fmt"
	"image"
	"io/ioutil"
	[some imports removed]
	"net/http"
)

but both my main.go and rputikar's main_test.go contained an additional import, "image/jpeg". So, I added that into my htmlutil.go import list and that solved the problem. I think I'll add "_ image/png" and "_ image/gif" just for future-proofing

huangapple
  • 本文由 发表于 2012年12月30日 10:24:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/14087766.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定