为归档函数 fs 创建单元测试

Posted

技术标签:

【中文标题】为归档函数 fs 创建单元测试【英文标题】:Create unit test for archive function fs 【发布时间】:2018-08-30 08:10:44 【问题描述】:

我有以下按预期工作的功能。现在我想为它创建单元测试。问题是我正在使用文件系统,我无法弄清楚如何使用一些模拟或任何其他解决方案来做到这一点。知道如何在 Go 中简单地做到这一点吗? 我真的应该创建一个文件然后用单元测试检查吗?恐怕在某些系统中它会起作用,而在某些系统中它会中断(winodos/mac/linux)

这是工作函数:

func Zipper(src string,artifact string,target string) error 

    zf, err := os.Create(artifact)
    if err != nil 
        return err
    
    defer zf.Close()

    ziper := zip.NewWriter(zf)
    defer ziper.Close()

    fileInfo, err := os.Stat(src)
    if err != nil 
        return err
    

    var bs string
    if fileInfo.IsDir(); len(target) > 0 
        bs = target
     else 
        bs = filepath.Base(src)
    

    if bs != "" 
        bs += "/"
    

    filepath.Walk(src, func(path string, info os.FileInfo, err error) error 
        if err != nil 
            return err
        

        if info.IsDir() 
            return nil
        

        header, err := zip.FileInfoHeader(info)
        if err != nil 
            return err
        

        if bs != "" 
            header.Name = filepath.Join(strings.TrimPrefix(path, bs))
        

        header.Method = zip.Deflate

        writer, err := ziper.CreateHeader(header)
        if err != nil 
            return err
        

        file, err := os.Open(path)
        if err != nil 
            return err
        
        defer file.Close()
        _, err = io.Copy(writer, file)
        return err
    )

    return err

我阅读了以下内容,但对我的情况没有多大帮助 How to mock/abstract filesystem in go?

【问题讨论】:

您要测试函数的哪一部分?如果您想测试 zip 部分,您可以创建一个分隔函数,该函数采用 io.Reader。这么长的函数不容易进行单元测试。 @apxp - 我想测试所有:) 当然,你建议划分功能,如何?你能举个例子吗? 【参考方案1】:

测试依赖于文件系统的函数的最简单方法是在每个测试周围添加一些设置和拆卸,在运行测试之前放置必要的文件,然后在运行测试后删除它们.

func TestZipper(t *testing.T) 
    // Create temporary files
    defer func() 
        // Clean up temporary files
    ()
    t.Run("group", func(t *testing.T)  // This is necessary so the above defer function doesn't run too soon
        // your actual tests
    )

【讨论】:

谢谢,所以你建议在测试之前创建一个 zip 并在测试中提取它并测试已创建的文件? 在不大幅改变您的功能的情况下,是的,这就是方法。你也可以在版本控制中保存你的“黄金文件”,然后你不需要创建临时文件——你只需要清理输出文件。 谢谢,更具体地说 :) ,作为黄金文件,您建议在我的testdata 文件夹下保留一些“小 zip”并运行测试并对照此 @987654323 检查功能@ ? @JhonD:没错。尽管这在实践中可能并不总是有效。例如,zip 文件通常包含元数据,例如日期,每次运行时都会更改。 好的,谢谢。因此,如果元数据不同,它将无法工作...【参考方案2】:

我知道“不访问文件系统”是很多人对“单元测试”定义的一部分。如果你的职业不是在寻找和捍卫定义:忘记那个限制。文件系统访问既快速又好,go 工具甚至对名为“testdata”的文件夹进行了特殊处理:此类文件夹应该包含要在测试期间使用的测试数据。

Go(和他们的用户)在区分“单元”和“集成”测试方面并不是很迂腐。看看如何测试这些东西的标准库。编写相关测试比对 fs 访问幼稚更重要。 (请注意,文件系统和数据库在技术上是外部系统,但在现实生活中,没有文件系统就无法编译 Go 代码,因此将测试与“外部系统”隔离开来是荒谬的。)

【讨论】:

【参考方案3】:

好吧,您可能会寻找一种以安全方式操作文件系统的方法,或者在其他地方寻找解决方案。这个函数的职责是什么?它应该准备一个 zip 文件还是将其写入文件系统?

我建议你应该从这个函数中取出文件创建并将函数更改为:

func Zipper(src string, dst io.Writer, target string) error 
    ziper := zip.NewWriter(dst)
    defer ziper.Close()

这样,出于测试目的,您可以提供一个简单的缓冲区,而在生产中使用您喜爱的文件系统!

【讨论】:

该函数的职责是获取源文件夹,目标是创建 zip 的位置...听起来很有趣 :) 您能否给出详细的示例,请您如何更改所有函数跨度>

以上是关于为归档函数 fs 创建单元测试的主要内容,如果未能解决你的问题,请参考以下文章

你如何对 Python DataFrames 进行单元测试

Android单元测试学习总结

PHP单元,使用单元测试测试laravel日志消息

如何使用私有构造函数对类进行单元测试?

Laravel 5 单元测试 - 在 null 上调用成员函数 connection()

单元测试(201421123088,201421123063)