英文:
Golang: Creating temporary directory for testing a file reading function
问题
我正在尝试为一个文件读取函数编写测试。该函数接受目录路径并开始扫描以将文件分类到子目录中。
func FileScan(dir string) (map[string][]string, error) {
var dataset = make(map[string][]string)
files, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
for _, file := range files {
if file.IsDir() {
dirFiles, err := ioutil.ReadDir(fmt.Sprintf("%s/%s", dir, file.Name()))
if err != nil {
return nil, err
}
for _, dirFile := range dirFiles {
if !dirFile.IsDir() {
dataset[file.Name()] = append(dataset[file.Name()], dirFile.Name())
}
}
}
}
return dataset, nil
}
为了进行测试,我在测试文件旁边创建了一个临时目录,并在其中放置了一些子目录和文件,然后开始测试该函数,并通过defer调用一个清理函数来在测试结束后删除该目录。
这是一个好的做法吗?或者也许最好传递一个[]fs.FileInfo
数组而不是目录路径,这样我可以在测试中实现一个模拟的FileInfo
。
英文:
I'm trying to write a test for a file reading function. The function accepts directory path & start scanning to categorize files with the sub-directories.
func FileScan(dir string) (map[string][]string, error) {
var dataset = make(map[string][]string)
files, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
for _, file := range files {
if file.IsDir() {
dirFiles, err := ioutil.ReadDir(fmt.Sprintf("%s/%s", dir, file.Name()))
if err != nil {
return nil, err
}
for _, dirFile := range dirFiles {
if !dirFile.IsDir() {
dataset[file.Name()] = append(dataset[file.Name()], dirFile.Name())
}
}
}
}
return dataset, nil
}
For testing, I created a temporary directory next to the test file & put some sub-directories & files insides them, then start to test the function & call a cleaner function via defer to delete the directory after test.
Is this a good practice? 🤔
or maybe it's better to pass an array of []fs.FileInfo
instead of directory path, so I can implement a mocked FileInfo
in testing.
答案1
得分: 1
你可以尝试通过修改代码的方式,使得你的测试更加清晰、更快,并且避免触碰文件系统。你可以使用https://pkg.go.dev/testing/fstest@go1.17.3#MapFS来测试修改后的代码。
附注:建议使用os.ReadDir
而不是ioutil.ReadDir
,具体可以参考这里。
以下是对你的代码进行最小修改后的工作示例(playground链接):
package main
import (
"fmt"
"io/fs"
"log"
"path"
"reflect"
"testing/fstest"
)
func main() {
var myFiles fstest.MapFS = make(map[string]*fstest.MapFile)
myFiles["test_dir/i_am_a_file"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory/add_me_to_map"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory_too/add_me_to_map_too"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory_too/and_me"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory_too/do_not_add_me_to_map/"] = &fstest.MapFile{}
m, err := FileScan(myFiles, "test_dir")
if err != nil {
log.Fatalln("Test failed:", err)
}
expectedMap := map[string][]string{
"i_am_a_directory": {"add_me_to_map"},
"i_am_a_directory_too": {"add_me_to_map_too", "and_me"},
}
if !reflect.DeepEqual(expectedMap, m) {
log.Fatalf("m: expected = %v, observed = %v", 2, expectedMap, m)
}
fmt.Println("OK")
}
func FileScan(fileSystem fs.FS, dir string) (map[string][]string, error) {
var dataset = make(map[string][]string)
files, err := fs.ReadDir(fileSystem, dir)
if err != nil {
return nil, err
}
for _, file := range files {
if !file.IsDir() {
continue
}
dirFiles, err := fs.ReadDir(fileSystem, path.Join(dir, file.Name()))
if err != nil {
return nil, err
}
for _, dirFile := range dirFiles {
if dirFile.IsDir() {
continue
}
dataset[file.Name()] = append(dataset[file.Name()], dirFile.Name())
}
}
return dataset, nil
}
英文:
You can try to make your tests cleaner, faster and avoid touching the filesystem if you modify your code in a way it could be tested with https://pkg.go.dev/testing/fstest@go1.17.3#MapFS
Side note: it's recommended to use os.ReadDir
instead of ioutil.ReadDir
Here is a working example with the minimal modification of your code (playground link):
package main
import (
"fmt"
"io/fs"
"log"
"path"
"reflect"
"testing/fstest"
)
func main() {
var myFiles fstest.MapFS = make(map[string]*fstest.MapFile)
myFiles["test_dir/i_am_a_file"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory/add_me_to_map"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory_too/add_me_to_map_too"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory_too/and_me"] = &fstest.MapFile{}
myFiles["test_dir/i_am_a_directory_too/do_not_add_me_to_map/"] = &fstest.MapFile{}
m, err := FileScan(myFiles, "test_dir")
if err != nil {
log.Fatalln("Test failed:", err)
}
expectedMap := map[string][]string{
"i_am_a_directory": {"add_me_to_map"},
"i_am_a_directory_too": {"add_me_to_map_too", "and_me"},
}
if !reflect.DeepEqual(expectedMap, m) {
log.Fatalf("m: expected = %v, observed = %v", 2, expectedMap, m)
}
fmt.Println("OK")
}
func FileScan(fileSystem fs.FS, dir string) (map[string][]string, error) {
var dataset = make(map[string][]string)
files, err := fs.ReadDir(fileSystem, dir)
if err != nil {
return nil, err
}
for _, file := range files {
if !file.IsDir() {
continue
}
dirFiles, err := fs.ReadDir(fileSystem, path.Join(dir, file.Name()))
if err != nil {
return nil, err
}
for _, dirFile := range dirFiles {
if dirFile.IsDir() {
continue
}
dataset[file.Name()] = append(dataset[file.Name()], dirFile.Name())
}
}
return dataset, nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论