如何在golang中为包含通道、filewalk和api调用的程序编写单元测试?
Posted
技术标签:
【中文标题】如何在golang中为包含通道、filewalk和api调用的程序编写单元测试?【英文标题】:How to write unit test for a program that contains channels, filewalk and api call in golang? 【发布时间】:2022-01-10 23:56:46 【问题描述】:我的程序整体如下。
func main()
flag.Parse()
if *token == ""
log.Fatal(Red + "please provide a client token => -token=$token")
tokenSource := oauth2.StaticTokenSource(&oauth2.TokenAccessToken: *token)
oauthClient := oauth2.NewClient(context.TODO(), tokenSource)
client := putio.NewClient(oauthClient)
//paths := make(chan string)
var wg = new(sync.WaitGroup)
for i := 0; i < 50; i++
wg.Add(1)
go worker(paths, wg, client)
WalkFilePath()
//if err := filepath.Walk(*rootpath, func(path string, info os.FileInfo, err error) error
// if err != nil
// return fmt.Errorf("Failed to walk directory: %T %w", err, err)
//
// if !info.IsDir()
// paths <- path
//
// return nil
//); err != nil
// panic(fmt.Errorf("failed Walk: %w", err))
//
close(paths)
wg.Wait()
// walks the file path and sends paths to channel
func WalkFilePath()
if err := filepath.Walk(*rootpath, func(path string, info os.FileInfo, err error) error
if err != nil
return fmt.Errorf("Failed to walk directory: %T %w", err, err)
if !info.IsDir()
paths <- path
return nil
); err != nil
panic(fmt.Errorf("failed Walk: %w", err))
func worker(paths <-chan string, wg *sync.WaitGroup, client *putio.Client)
defer wg.Done()
for path := range paths
f, err := os.Open(path)
if err != nil
log.Printf(Red + "Failed to open file %v for reading" + Reset, f.Name())
upload, err := client.Files.Upload(context.TODO(), f, path, 0)
if err != nil
log.Printf(Red + "Failed to upload file %v" + Reset, upload.File.Name)
log.Printf(Green+ "File %v has been uploaded succesfully" + Reset, upload.File.Name)
我确实编写了代码。这是我能做的最干净的事情,我被告知要为程序编写一个单元测试。我糊涂了。例如,考虑WalkFilePath
函数。我应该提供什么以及我应该期望什么样的结果来测试该功能。因为它包含channel
通信含义goroutines
。有没有办法清楚地为这个程序编写单元测试?或者我应该更改在这种情况下对我不利的代码结构。顺便说一句,程序运行正常。
【问题讨论】:
"顺便说一句,程序运行正常。"那个程序没有。你在WalkFilePath
中引用了未定义的变量。
我没有放不必要的代码。这就是为什么。
【参考方案1】:
像大多数事情一样,Go 对于如何测试非常固执己见。请务必阅读https://go.dev/doc/tutorial/add-a-test
例如,考虑 WalkFilePath 函数。我应该提供什么以及我应该期望什么样的结果来测试该功能。
WalkFilePath
的输入应该是paths
和rootpath
。您的WalkFilePath
不会从任何地方获得paths
或rootpath
,因此此代码不会按原样编译(当然,测试将有助于捕获这些内容)。
WalkFilePath
的测试可能会像这样进行:
在testdata/
下的项目中创建一个文件系统结构,一个目录expressly set aside for data used for testing。创建子目录和文件。对于一个可能看起来像这样的示例:
testdata/
walktest/
dir1/
file1.txt
dir2/
file2.txt
dir3/
file3.txt
现在您可以定义您将从频道中获得的预期数据。
expected_paths := []string
"testdata/walktest/dir1/file1.txt",
"testdata/walktest/dir2/file2.txt",
"testdata/walktest/dir3/file3.txt"
现在您需要更改 WalkFilePath
以获取 rootpath
和 paths
的参数。
func WalkFilePath(rootdir string, paths chan<- string)
现在您可以编写测试了。
func TestWalkFilePath(t *testing.T(
paths := make(chan string)
go WalkFilePath("testdata/walktest")
results := make([]string,0)
for path := range paths
results = append(results, path)
exp, res := strings.Join(expected_paths, ""), strings.Join(results, "")
if exp != res
t.Errorf("Expected %s got %s", exp, res)
因为它包含通道通信意义的goroutines。
在单元测试中使用通道和 goroutine 是完全正常和有效的。
【讨论】:
以上是关于如何在golang中为包含通道、filewalk和api调用的程序编写单元测试?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 VSTS 中为 Xamarin iOS 和 Android 部署添加快速通道工具
如何在 Keras 中为维度 (2505,10) 的数据设计 CNN?
如何使用 PySide 在 Maya 中为通道框添加新按钮?