CSV的单元测试失败了

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

go unit test for CSV is failing

问题

我想使用csv包进行一个大型项目,并且我从一些基本测试开始。我无法弄清楚为什么这个单元测试失败了,因为输出似乎与预期输出相匹配。

文件:

package csv

import (
	"bytes"
	"encoding/csv"
)

func GenerateCSV(records [][]string) (string, error) {
	buf := bytes.Buffer{}

	w := csv.NewWriter(&buf)

	for _, record := range records {
		if err := w.Write(record); err != nil {
			// 处理错误
		}
	}
	w.Flush()

	if err := w.Error(); err != nil {
		// 处理错误
	}

	return buf.String(), nil
}

测试文件:

package csv

import "testing"

func TestGenerateCSV(t *testing.T) {

	records := [][]string{
		{"first_name", "last_name", "user_name"},
	}
	type args struct {
		records [][]string
	}
	tests := []struct {
		name    string
		args    args
		want    string
		wantErr bool
	}{
		// TODO: 添加测试用例。
		{"T1", args{records: records}, "first_name,last_name,user_name", false},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := GenerateCSV(tt.args.records)
			if (err != nil) != tt.wantErr {
				t.Errorf("GenerateCSV() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("GenerateCSV() = %v, want %v", got, tt.want)
			}
		})
	}
}

当运行测试时,我得到以下输出:

FAIL: TestGenerateCSV
GenerateCSV() = first_name,last_name,user_name
        , want first_name,last_name,user_name

看起来测试输出正是我所要求的。有人可以帮我找出我做错了什么吗?

英文:

I am wanting to use the csv package for a large project and I am starting with some basic tests. I cannot figure out why this unit test is failing, when it appears that the output matches the expected output.

FILE:

package csv

import (
	"bytes"
	"encoding/csv"
)

func GenerateCSV(records [][]string) (string, error) {
	buf := bytes.Buffer{}

	w := csv.NewWriter(&buf)

	for _, record := range records {
		if err := w.Write(record); err != nil {
			// handle the err
			}
	}
		w.Flush()

		if err := w.Error(); err != nil {
			// handle the error
		}

		return buf.String(), nil
	}

TESTFILE:

package csv

import "testing"

func TestGenerateCSV(t *testing.T) {

	records := [][]string{
		{"first_name","last_name","user_name"},
	}
	type args struct {
		records [][]string
	}
	tests := []struct {
		name    string
		args    args
		want    string
		wantErr bool
	}{
		// TODO: Add test cases.
		{"T1", args{records: records,}, "first_name,last_name,user_name", false},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := GenerateCSV(tt.args.records)
			if (err != nil) != tt.wantErr {
				t.Errorf("GenerateCSV() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("GenerateCSV() = %v, want %v", got, tt.want)
			}
		})
	}

When the test runs, I get this output:

FAIL: TestGenerateCSV
GenerateCSV() = first_name,last_name,user_name
        , want first_name,last_name,user_name

It seems like the test output is exactly what I called for? Can anyone help me identify what I'm doing wrong?

答案1

得分: 0

在你的测试代码中添加以下检查来捕获错误。

if len(got) != len(tt.want) {
    t.Errorf("GenerateCSV() string len = %v, want length %v", len(got), len(tt.want))
    return
}

原因:当你使用w.Flush写入记录时,它会添加一个新行。

英文:

To catch your error add this check in your test code.

	if len(got) != len(tt.want) {
			t.Errorf("GenerateCSV() string len = %v, want length %v", len(got), len(tt.want))
			return
		}

Reason : When you are writing your record using w.Flush, it adds a new line.

答案2

得分: 0

测试失败是因为你的预期字符串在单记录测试用例中没有包含换行符(\n):

{"T1", args{records: records}, "first_name,last_name,user_name", false},

应该是:

{"T1", args{records: records}, "first_name,last_name,user_name\n", false},

每个编码记录都应该有一个换行符。

在测试代码的打印输出中,将%v更改为%q将使查看“引用字符串”差异更容易:

if got != tt.want {
    t.Errorf("GenerateCSV() = %q, want %q", got, tt.want)
}

此外,如果你在将记录编码为CSV时不需要执行任何特殊操作(只需获得CSV字符串的最快路径),你可以在GenerateCSV中剪切循环,并改为使用Writer的WriteAll()方法:

// GenerateCSV返回记录的CSV编码字符串表示。
func GenerateCSV(records [][]string) (string, error) {
    buf := bytes.Buffer{}

    w := csv.NewWriter(&buf)
    if err := w.WriteAll(records); err != nil {
        return "", err
    }

    w.Flush()
    if err := w.Error(); err != nil {
        return "", err
    }

    return buf.String(), nil
}
英文:

The test fails because your expected string doesn't contain a newline (\n) for the single-record test case:

{"T1", args{records: records}, "first_name,last_name,user_name", false},

It should be:

{"T1", args{records: records}, "first_name,last_name,user_name\n", false},

Every encoded record will have a newline.

Changing the %v to %q in your test code print-outs will make seeing the "quoted string" differences easier:

if got != tt.want {
	t.Errorf("GenerateCSV() = %q, want %q", got, tt.want)
}

Also, you if you don't need to do anything special to records as you are CSV-encoding them (you just want the quickest path to a CSV string), you can cut out the loop in GenerateCSV and instead use the Writer's WriteAll() method:

// GenerateCSV returns the CSV-encoded string representation of records.
func GenerateCSV(records [][]string) (string, error) {
	buf := bytes.Buffer{}

	w := csv.NewWriter(&buf)
	if err := w.WriteAll(records); err != nil {
		return "", err
	}

	w.Flush()
	if err := w.Error(); err != nil {
		return "", err
	}

	return buf.String(), nil
}

答案3

得分: -1

预期输出是first_name,last_name,user_name,但实际输出是first_name,last_name,user_name,(注意末尾多了一个逗号)。这就是测试失败的原因。

英文:

The expected output is first_name,last_name,user_name but the actual output is first_name,last_name,user_name, (notice the extra comma at the end). This is why the test is failing.

huangapple
  • 本文由 发表于 2023年4月8日 05:06:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75961940.html
匿名

发表评论

匿名网友

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

确定